From: hjhun <36876573+hjhun@users.noreply.github.com> Date: Tue, 26 Jan 2021 23:37:43 +0000 (+0900) Subject: [Tizen.Applications.ComponentBased][TCSACR-398] Add ComponentPort class (#2548) X-Git-Tag: accepted/tizen/unified/20210219.040944~54 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f29e30c09c2874b5bb0a39f0338c35ac63e1d72a;p=platform%2Fcore%2Fcsapi%2Ftizenfx.git [Tizen.Applications.ComponentBased][TCSACR-398] Add ComponentPort class (#2548) * Devel Component Port Signed-off-by: Hwankyu Jhun * Change parameter name to endpoint Signed-off-by: Hwankyu Jhun * Use Serializable instead of Parcelable Signed-off-by: Hwankyu Jhun * Remove Marker interface Signed-off-by: Hwankyu Jhun * Check result object The result has to be a serializble object. Signed-off-by: Hwankyu Jhun * Fix wrong description Signed-off-by: Hwankyu Jhun * Remove SafePortHandle Signed-off-by: Hwankyu Jhun * Modify using directives Signed-off-by: Hwankyu Jhun * Fix typo Signed-off-by: Hwankyu Jhun Co-authored-by: pjh9216 --- diff --git a/src/Tizen.Applications.ComponentBased.Port/Interop/Interop.ComponentPort.cs b/src/Tizen.Applications.ComponentBased.Port/Interop/Interop.ComponentPort.cs new file mode 100755 index 0000000..8dc3b3d --- /dev/null +++ b/src/Tizen.Applications.ComponentBased.Port/Interop/Interop.ComponentPort.cs @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Runtime.InteropServices; +using Tizen.Applications; +using Tizen.Applications.ComponentBased; + +internal static partial class Interop +{ + internal static partial class ComponentPort + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ComponentPortRequestCallback(string sender, IntPtr request, IntPtr userData); + // typedef void (*component_port_request_cb)(const char *sender, parcel_h request, IntPtr user_data); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ComponentPortSyncRequestCallback(string sender, IntPtr request, IntPtr response, IntPtr userData); + // typedef void (*component_port_request_cb)(const char *sender, parcel_h request, parcel_h response IntPtr user_data); + + internal enum ErrorCode + { + None = Tizen.Internals.Errors.ErrorCode.None, + InvalidParameter = Tizen.Internals.Errors.ErrorCode.InvalidParameter, + OutOfMemory = Tizen.Internals.Errors.ErrorCode.OutOfMemory, + IOError = Tizen.Internals.Errors.ErrorCode.IoError, + PermissionDenied = Tizen.Internals.Errors.ErrorCode.PermissionDenied, + } + + [DllImport(Libraries.ComponentPort, EntryPoint = "component_port_create")] + internal static extern ErrorCode Create(string portName, out IntPtr handle); + // int component_port_create(const char *port_name, component_port_h *port); + + [DllImport(Libraries.ComponentPort, EntryPoint = "component_port_destroy")] + internal static extern ErrorCode Destroy(IntPtr handle); + // int component_port_destroy(component_port_h port); + + [DllImport(Libraries.ComponentPort, EntryPoint = "component_port_set_request_cb")] + internal static extern ErrorCode SetRequestCb(IntPtr handle, ComponentPortRequestCallback callback, IntPtr userData); + // int component_port_set_request_cb(component_port_h port, component_port_request_cb callback, void *user_data); + + [DllImport(Libraries.ComponentPort, EntryPoint = "component_port_set_sync_request_cb")] + internal static extern ErrorCode SetSyncRequestCb(IntPtr handle, ComponentPortSyncRequestCallback callback, IntPtr userData); + // int component_port_set_sync_request_cb(component_port_h port, component_port_sync_request_cb callback, void *user_data); + + [DllImport(Libraries.ComponentPort, EntryPoint = "component_port_add_privilege")] + internal static extern ErrorCode AddPrivilege(IntPtr handle, string privilege); + // int component_port_add_privilege(component_port_h port, const char *privilege); + + [DllImport(Libraries.ComponentPort, EntryPoint = "component_port_wait_for_event")] + internal static extern void WaitForEvent(IntPtr handle); + // void component_port_wait_for_event(component_port_h port); + + [DllImport(Libraries.ComponentPort, EntryPoint = "component_port_cancel")] + internal static extern void Cancel(IntPtr handle); + // void component_port_cancel(component_port_h port); + + [DllImport(Libraries.ComponentPort, EntryPoint = "component_port_send")] + internal static extern ErrorCode Send(IntPtr handle, string endpoint, Int32 timeout, SafeParcelHandle request); + // int component_port_send(component_port_h port, const char *endpoint, int timeout, parcel_h request); + + [DllImport(Libraries.ComponentPort, EntryPoint = "component_port_send_sync")] + internal static extern ErrorCode SendSync(IntPtr handle, string endpoint, Int32 timeout, SafeParcelHandle request, out SafeParcelHandle response); + // int component_port_send(component_port_h port, const char *endpoint, int timeout, parcel_h request, parcel_h *response); + } +} \ No newline at end of file diff --git a/src/Tizen.Applications.ComponentBased.Port/Interop/Interop.Libraries.cs b/src/Tizen.Applications.ComponentBased.Port/Interop/Interop.Libraries.cs new file mode 100755 index 0000000..e7d08de --- /dev/null +++ b/src/Tizen.Applications.ComponentBased.Port/Interop/Interop.Libraries.cs @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +internal static partial class Interop +{ + internal static partial class Libraries + { + public const string ComponentPort = "libcomponent-based-port.so.1"; + public const string Parcel = "libparcel.so.0"; + } +} \ No newline at end of file diff --git a/src/Tizen.Applications.ComponentBased.Port/Interop/Interop.Parcel.cs b/src/Tizen.Applications.ComponentBased.Port/Interop/Interop.Parcel.cs new file mode 100755 index 0000000..a45bbd9 --- /dev/null +++ b/src/Tizen.Applications.ComponentBased.Port/Interop/Interop.Parcel.cs @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Runtime.InteropServices; +using Tizen.Internals; +using Tizen.Applications; + +internal static partial class Interop +{ + internal static partial class Parcel + { + internal enum ErrorCode + { + None = Tizen.Internals.Errors.ErrorCode.None, + InvalidParameter = Tizen.Internals.Errors.ErrorCode.InvalidParameter, + IllegalByteSeq = Tizen.Internals.Errors.ErrorCode.IllegalByteSeq, + NoData = Tizen.Internals.Errors.ErrorCode.NoData, + OutOfMemory = Tizen.Internals.Errors.ErrorCode.OutOfMemory, + } + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_create")] + internal static extern ErrorCode Create(out SafeParcelHandle handle); + // int parcel_create(parcel_h *parcel); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_destroy")] + internal static extern ErrorCode DangerousDestroy(IntPtr handle); + // int parcel_destroy(parcel_h parcel); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_clone")] + internal static extern ErrorCode DangerousClone(IntPtr handle, out SafeParcelHandle clone); + // int parcel_clone(parcel_h parcel, parcel_h *clone); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_burst_write")] + internal static extern ErrorCode BurstWrite(SafeParcelHandle handle, byte[] buf, UInt32 size); + // int parcel_burst_write(parcel_h parcel, cont void *buf, uint32_t size); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_burst_read")] + internal static extern ErrorCode BurstRead(SafeParcelHandle handle, [In, Out] byte[] buf, UInt32 size); + // int parcel_burst_read(parcel_h parcel, void *buf, uint32_t size); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_write_bool")] + internal static extern ErrorCode WriteBool(SafeParcelHandle handle, bool val); + // int parcel_write_bool(parcel_h parcel, bool val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_write_byte")] + internal static extern ErrorCode WriteByte(SafeParcelHandle handle, byte val); + // int parcel_write_byte(parcel_h parcel, char val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_write_uint16")] + internal static extern ErrorCode WriteUInt16(SafeParcelHandle handle, UInt16 val); + // int parcel_write_uint16(parcel_h parcel, uint16_t val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_write_uint32")] + internal static extern ErrorCode WriteUInt32(SafeParcelHandle handle, UInt32 val); + // int parcel_write_uint32(parcel_h parcel, uint32_t val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_write_uint64")] + internal static extern ErrorCode WriteUInt64(SafeParcelHandle handle, UInt64 val); + // int parcel_write_uint64(parcel_h parcel, uint64_t val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_write_int16")] + internal static extern ErrorCode WriteInt16(SafeParcelHandle handle, Int16 val); + // int parcel_write_int16(parcel_h parcel, int16_t val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_write_int32")] + internal static extern ErrorCode WriteInt32(SafeParcelHandle handle, Int32 val); + // int parcel_write_int32(parcel_h parcel, int32_t val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_write_int64")] + internal static extern ErrorCode WriteInt64(SafeParcelHandle handle, Int64 val); + // int parcel_write_int64(parcel_h parcel, int64_t val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_write_float")] + internal static extern ErrorCode WriteFloat(SafeParcelHandle handle, float val); + // int parcel_write_float(parcel_h parcel, float val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_write_double")] + internal static extern ErrorCode WriteDouble(SafeParcelHandle handle, double val); + // int parcel_write_double(parcel_h parcel, double val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_write_string")] + internal static extern ErrorCode WriteString(SafeParcelHandle handle, string str); + // int parcel_write_string(parcel_h parcel, const char *str); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_write_bundle")] + internal static extern ErrorCode WriteBundle(SafeParcelHandle handle, IntPtr b); + // int parcel_write_bundle(parcel_h parcel, bundle *b); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_read_bool")] + internal static extern ErrorCode ReadBool(SafeParcelHandle handle, out bool val); + // int parcel_read_bool(parcel_h parcel, bool *val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_read_byte")] + internal static extern ErrorCode ReadByte(SafeParcelHandle handle, out byte val); + // int parcel_read_byte(parcel_h parcel, char *val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_read_uint16")] + internal static extern ErrorCode ReadUInt16(SafeParcelHandle handle, out UInt16 val); + // int parcel_read_uint16(parcel_h parcel, uint16_t *val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_read_uint32")] + internal static extern ErrorCode ReadUInt32(SafeParcelHandle handle, out UInt32 val); + // int parcel_read_uint32(parcel_h parcel, uint32_t *val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_read_uint64")] + internal static extern ErrorCode ReadUInt64(SafeParcelHandle handle, out UInt64 val); + // int parcel_read_uint64(parcel_h parcel, uint64_t *val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_read_int16")] + internal static extern ErrorCode ReadInt16(SafeParcelHandle handle, out Int16 val); + // int parcel_read_int16(parcel_h parcel, int16_t *val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_read_int32")] + internal static extern ErrorCode ReadInt32(SafeParcelHandle handle, out Int32 val); + // int parcel_read_int32(parcel_h parcel, int32_t *val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_read_int64")] + internal static extern ErrorCode ReadInt64(SafeParcelHandle handle, out Int64 val); + // int parcel_read_int64(parcel_h parcel, int64_t *val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_read_float")] + internal static extern ErrorCode ReadFloat(SafeParcelHandle handle, out float val); + // int parcel_read_float(parcel_h parcel, float *val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_read_double")] + internal static extern ErrorCode ReadDouble(SafeParcelHandle handle, out double val); + // int parcel_read_double(parcel_h parcel, double *val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_read_string")] + internal static extern ErrorCode ReadString(SafeParcelHandle handle, out string val); + // int parcel_read_string(parcel_h parcel, char **val); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_read_bundle")] + internal static extern ErrorCode ReadBundle(SafeParcelHandle handle, out IntPtr b); + // int parcel_read_bundle(parcel_h parcel, bundle **b); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_get_raw")] + internal static extern ErrorCode GetRaw(SafeParcelHandle handle, out IntPtr raw, out UInt32 size); + // int parcel_get_raw(parcel_h parcel, void **raw, uint32_t *size); + + [DllImport(Libraries.Parcel, EntryPoint = "parcel_reset")] + internal static extern ErrorCode Reset(SafeParcelHandle handle, byte[] buf, UInt32 size); + // int parcel_reset(parcel_h parcel, const void *buf, uint32_t size); + } +} \ No newline at end of file diff --git a/src/Tizen.Applications.ComponentBased.Port/Tizen.Applications.ComponentBased.Port.csproj b/src/Tizen.Applications.ComponentBased.Port/Tizen.Applications.ComponentBased.Port.csproj new file mode 100644 index 0000000..4c51c41 --- /dev/null +++ b/src/Tizen.Applications.ComponentBased.Port/Tizen.Applications.ComponentBased.Port.csproj @@ -0,0 +1,12 @@ + + + + netstandard2.0 + + + + + + + + \ No newline at end of file diff --git a/src/Tizen.Applications.ComponentBased.Port/Tizen.Applications.ComponentBased.Port.sln b/src/Tizen.Applications.ComponentBased.Port/Tizen.Applications.ComponentBased.Port.sln new file mode 100755 index 0000000..ee842a1 --- /dev/null +++ b/src/Tizen.Applications.ComponentBased.Port/Tizen.Applications.ComponentBased.Port.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30517.126 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tizen.Applications.ComponentBased.Port", "Tizen.Applications.ComponentBased.Port.csproj", "{FF190549-DDD6-47ED-ABA3-717B0C130C3D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tizen", "..\Tizen\Tizen.csproj", "{2E04FB0F-03F4-40B0-BB25-5ADFB08C8DF3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tizen.Log", "..\Tizen.Log\Tizen.Log.csproj", "{8DA5B43B-63E9-460C-B64F-0B691539DC5D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FF190549-DDD6-47ED-ABA3-717B0C130C3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FF190549-DDD6-47ED-ABA3-717B0C130C3D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FF190549-DDD6-47ED-ABA3-717B0C130C3D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FF190549-DDD6-47ED-ABA3-717B0C130C3D}.Release|Any CPU.Build.0 = Release|Any CPU + {2E04FB0F-03F4-40B0-BB25-5ADFB08C8DF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E04FB0F-03F4-40B0-BB25-5ADFB08C8DF3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E04FB0F-03F4-40B0-BB25-5ADFB08C8DF3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E04FB0F-03F4-40B0-BB25-5ADFB08C8DF3}.Release|Any CPU.Build.0 = Release|Any CPU + {8DA5B43B-63E9-460C-B64F-0B691539DC5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8DA5B43B-63E9-460C-B64F-0B691539DC5D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8DA5B43B-63E9-460C-B64F-0B691539DC5D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8DA5B43B-63E9-460C-B64F-0B691539DC5D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0335C3BF-98CA-4337-96E5-088E9CEFDFFC} + EndGlobalSection +EndGlobal diff --git a/src/Tizen.Applications.ComponentBased.Port/Tizen.Applications.ComponentBased.Port/ComponentPort.cs b/src/Tizen.Applications.ComponentBased.Port/Tizen.Applications.ComponentBased.Port/ComponentPort.cs new file mode 100755 index 0000000..c7d68e4 --- /dev/null +++ b/src/Tizen.Applications.ComponentBased.Port/Tizen.Applications.ComponentBased.Port/ComponentPort.cs @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.IO; +using System.Reflection; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters; +using System.Runtime.Serialization.Formatters.Binary; +using System.Security; +using System.Xml.Serialization; + +namespace Tizen.Applications.ComponentBased +{ + /// + /// Abstract class for creating a component port class. + /// + /// 9 + public abstract class ComponentPort : IDisposable + { + private static string LogTag = "ComponentPort"; + private readonly string _portName; + private IntPtr _port = IntPtr.Zero; + private Interop.ComponentPort.ComponentPortRequestCallback _requestEventCallback; + private Interop.ComponentPort.ComponentPortSyncRequestCallback _syncRequestEventCallback; + + /// + /// Constructor for this class. + /// + /// Thrown when the argument is invalid. + /// Thrown when the memory is insufficient. + /// Thrown when because of I/O error. + /// The name of the port. + /// 9 + public ComponentPort(string portName) + { + var ret = Interop.ComponentPort.Create(portName, out _port); + if (ret != Interop.ComponentPort.ErrorCode.None) + throw ComponentPortErrorFactory.GetException(ret, "ComponentPort(" + portName + ")."); + + _portName = portName; + _requestEventCallback = new Interop.ComponentPort.ComponentPortRequestCallback(OnRequestEvent); + _syncRequestEventCallback = new Interop.ComponentPort.ComponentPortSyncRequestCallback(OnSyncRequestEvent); + Interop.ComponentPort.SetRequestCb(_port, _requestEventCallback, IntPtr.Zero); + Interop.ComponentPort.SetSyncRequestCb(_port, _syncRequestEventCallback, IntPtr.Zero); + } + + /// + /// Gets the port name. + /// + /// 9 + public string PortName + { + get + { + return _portName; + } + } + + /// + /// Adds a privilege to the port object. + /// + /// Thrown when the argument is invalid. + /// privilege data + /// 9 + public void AddPrivilege(string privilege) + { + Interop.ComponentPort.AddPrivilege(_port, privilege); + } + + /// + /// Waits for events. + /// + /// 9 + public void WaitForEvent() + { + Interop.ComponentPort.WaitForEvent(_port); + } + + /// + /// Cancels waiting for events. + /// + /// 9 + public void Cancel() + { + Interop.ComponentPort.Cancel(_port); + } + + /// + /// Sends the request data. + /// + /// Thrown when the argument is invalid. + /// Thrown when the memory is insufficient. + /// Thrown when because of permission denied. + /// Thrown when because of I/O error. + /// The name of the endpoint + /// The interval of timeout + /// The serializable data to send + /// 9 + public void Send(string endpoint, int timeout, object request) + { + if (request == null) + { + throw new ArgumentException("request is null"); + } + + if (!request.GetType().IsSerializable) + { + throw new ArgumentException("request is not serializable"); + } + + Interop.ComponentPort.ErrorCode err; + using (Parcel reqParcel = ToParcel(request)) + { + err = Interop.ComponentPort.Send(_port, endpoint, timeout, reqParcel.SafeParcelHandle); + } + if (err != Interop.ComponentPort.ErrorCode.None) + { + throw ComponentPortErrorFactory.GetException(err, "Failed to send the request."); + } + } + + /// + /// Sends the request data synchronously. + /// + /// Thrown when the argument is invalid. + /// Thrown when the memory is insufficient. + /// Thrown when because of permission denied. + /// Thrown when because of I/O error. + /// The name of the endpoint + /// The interval of timeout + /// The serializable data to send + /// The received serializable data + /// /// 9 + public object SendSync(string endpoint, int timeout, object request) + { + if (request == null) + { + throw new ArgumentException("request is null"); + } + + if (!request.GetType().IsSerializable) + { + throw new ArgumentException("request is not serializable"); + } + + SafeParcelHandle resSafeHandle = null; + Interop.ComponentPort.ErrorCode err; + using (Parcel reqParcel = ToParcel(request)) + { + err = Interop.ComponentPort.SendSync(_port, endpoint, timeout, reqParcel.SafeParcelHandle, out resSafeHandle); + } + if (err != Interop.ComponentPort.ErrorCode.None) + { + throw ComponentPortErrorFactory.GetException(err, "Failed to send the request."); + } + + using (Parcel resParcel = new Parcel(resSafeHandle)) + { + object response = FromParcel(resParcel); + return response; + } + } + + /// + /// Abstract method for receiving a request event. + /// + /// The name of the sender + /// The serializable data + /// 9 + protected abstract void OnRequestEvent(string sender, object request); + + /// + /// Abstract method for receiving a synchronous request event. + /// + /// The name of the sender + /// The serializable data + /// The serializable data + /// 9 + protected abstract object OnSyncRequestEvent(string sender, object request); + + + private void OnRequestEvent(string sender, IntPtr request, IntPtr data) + { + SafeParcelHandle reqSafeHandle = new SafeParcelHandle(request, false); + using (var reqParcel = new Parcel(reqSafeHandle)) + { + object req = FromParcel(reqParcel); + OnRequestEvent(sender, req); + } + } + + private void OnSyncRequestEvent(string sender, IntPtr request, IntPtr response, IntPtr data) + { + SafeParcelHandle reqSafeHandle = new SafeParcelHandle(request, false); + + object req = null; + using (Parcel reqParcel = new Parcel(reqSafeHandle)) + { + req = FromParcel(reqParcel); + } + + object result = OnSyncRequestEvent(sender, req); + if (!result.GetType().IsSerializable) + { + Log.Error(LogTag, "result is not serializable"); + } + else + { + SafeParcelHandle resSafeHandle = new SafeParcelHandle(response, false); + using (Parcel resParcel = new Parcel(resSafeHandle)) + { + using (Parcel resultParcel = ToParcel(result)) + { + resParcel.UnMarshall(resultParcel.Marshall()); + } + } + } + } + + private Parcel ToParcel(object envelope) + { + if (envelope == null) + return null; + + BinaryFormatter formatter = new BinaryFormatter + { + Binder = new PortBinder(), + AssemblyFormat = FormatterAssemblyStyle.Full + }; + + using (MemoryStream stream = new MemoryStream()) + { + formatter.Serialize(stream, envelope); + Parcel parcel = new Parcel(); + parcel.UnMarshall(stream.ToArray()); + return parcel; + } + } + + private object FromParcel(Parcel parcel) + { + if (parcel == null) + return null; + + BinaryFormatter formatter = new BinaryFormatter + { + Binder = new PortBinder(), + AssemblyFormat = FormatterAssemblyStyle.Full, + }; + + object envelope = null; + using (MemoryStream stream = new MemoryStream(parcel.Marshall())) + { + try + { + envelope = (object)formatter.Deserialize(stream); + } + catch (ArgumentException e) + { + Log.Error(LogTag, "ArgumentException occurs: " + e.Message); + } + catch (SerializationException e) + { + Log.Error(LogTag, "SerializationException occurs: " + e.Message); + } + catch (SecurityException e) + { + Log.Error(LogTag, "SecurityException occurs: " + e.Message); + } + } + + return envelope; + } + + + #region IDisposable Support + private bool disposedValue = false; + + /// + /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects. + /// + /// If true, disposes any disposable objects, or false not to dispose disposable objects. + /// 9 + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + if (_port != IntPtr.Zero) + Interop.ComponentPort.Destroy(_port); + _port = IntPtr.Zero; + } + + disposedValue = true; + } + } + + /// + /// Finalizer of the class ComponentPort. + /// + /// 9 + ~ComponentPort() + { + Dispose(disposing: false); + } + + /// + /// Releases all the resources used by the class ComponentPort. + /// + /// 9 > + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + #endregion + + internal sealed class PortBinder : SerializationBinder + { + private static string LogTag = "PortBinder"; + + private string GetAssemblyName(string typeName) + { + foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) + { + foreach (Type t in a.GetTypes()) + { + if (t.FullName == typeName) + { + Log.Warn(LogTag, "Found! AssemblyName: " + a.FullName); + return a.FullName; + } + } + } + + return string.Empty; + } + + public override Type BindToType(string assemblyName, string typeName) + { + Type returntype = null; + Log.Warn(LogTag, "AssemblyName: " + assemblyName); + Log.Warn(LogTag, "TypeName: " + typeName); + string foundAssemblyName = GetAssemblyName(typeName); + if (foundAssemblyName.Length != 0) + { + returntype = Type.GetType(String.Format("{0}, {1}", typeName, foundAssemblyName)); + } + else + { + returntype = Type.GetType(String.Format("{0}, {1}", typeName, assemblyName)); + } + return returntype; + } + } + + internal static class ComponentPortErrorFactory + { + internal static Exception GetException(Interop.ComponentPort.ErrorCode err, string message) + { + string errMessage = string.Format("{0} err = {1}", message, err); + switch (err) + { + case Interop.ComponentPort.ErrorCode.InvalidParameter: + return new ArgumentException(errMessage); + case Interop.ComponentPort.ErrorCode.PermissionDenied: + return new UnauthorizedAccessException(errMessage); + case Interop.ComponentPort.ErrorCode.OutOfMemory: + return new OutOfMemoryException(errMessage); + default: + return new global::System.IO.IOException(errMessage); + } + } + } + } +} diff --git a/src/Tizen.Applications.ComponentBased.Port/Tizen.Applications.ComponentBased.Port/Parcel.cs b/src/Tizen.Applications.ComponentBased.Port/Tizen.Applications.ComponentBased.Port/Parcel.cs new file mode 100755 index 0000000..4f2db8a --- /dev/null +++ b/src/Tizen.Applications.ComponentBased.Port/Tizen.Applications.ComponentBased.Port/Parcel.cs @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Runtime.InteropServices; + +namespace Tizen.Applications.ComponentBased +{ + internal class Parcel : IDisposable + { + private readonly SafeParcelHandle _handle; + + public Parcel() + { + var ret = Interop.Parcel.Create(out _handle); + if (ret != Interop.Parcel.ErrorCode.None) + { + throw ParcelErrorFactory.GetException(ret, "Parcel() is failed."); + } + } + + public Parcel(SafeParcelHandle handle) + { + if (handle == null) + { + throw new ArgumentException("handle is null"); + } + + _handle = handle; + } + + public SafeParcelHandle SafeParcelHandle + { + get + { + return _handle; + } + } + + public byte[] Marshall() + { + Interop.Parcel.GetRaw(_handle, out IntPtr raw, out UInt32 size); + byte[] ret = new byte[size]; + Marshal.Copy((IntPtr)raw, (byte[])ret, 0, (int)size); + return ret; + } + + public void UnMarshall(byte[] bytes) + { + Interop.Parcel.Reset(_handle, bytes, (UInt32)bytes.Length); + } + + #region IDisposable Support + private bool disposedValue = false; + + /// + /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects. + /// + /// If true, disposes any disposable object. + /// 9 + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + if (_handle != null && !_handle.IsInvalid) + _handle.Dispose(); + } + + disposedValue = true; + } + } + + /// + /// Finalizer of the class Parcel. + /// + /// 9 + ~Parcel() + { + Dispose(disposing: false); + } + + /// + /// Releases all the resources used by the class parcel. + /// + /// 9 > + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + #endregion + + internal static class ParcelErrorFactory + { + internal static Exception GetException(Interop.Parcel.ErrorCode err, string message) + { + string errMessage = string.Format("{0} err = {1}", message, err); + switch (err) + { + case Interop.Parcel.ErrorCode.NoData: + case Interop.Parcel.ErrorCode.IllegalByteSeq: + return new InvalidOperationException(errMessage); + case Interop.Parcel.ErrorCode.InvalidParameter: + return new ArgumentException(errMessage); + default: + return new OutOfMemoryException(errMessage); + } + } + } + } +} \ No newline at end of file diff --git a/src/Tizen.Applications.ComponentBased.Port/Tizen.Applications.ComponentBased.Port/SafeParcelHandle.cs b/src/Tizen.Applications.ComponentBased.Port/Tizen.Applications.ComponentBased.Port/SafeParcelHandle.cs new file mode 100755 index 0000000..0a3396a --- /dev/null +++ b/src/Tizen.Applications.ComponentBased.Port/Tizen.Applications.ComponentBased.Port/SafeParcelHandle.cs @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Runtime.InteropServices; + +namespace Tizen.Applications +{ + internal sealed class SafeParcelHandle : SafeHandle + { + public SafeParcelHandle() : base(IntPtr.Zero, true) + { + + } + + public SafeParcelHandle(IntPtr existingHandle, bool ownsHandle) : base(IntPtr.Zero, ownsHandle) + { + SetHandle(existingHandle); + } + + public override bool IsInvalid + { + get { return this.handle == IntPtr.Zero; } + } + + protected override bool ReleaseHandle() + { + Interop.Parcel.DangerousDestroy(this.handle); + this.SetHandle(IntPtr.Zero); + return true; + } + } +} \ No newline at end of file