From fb6637886a3c66fa23ef42719c554af5aa7b9cef Mon Sep 17 00:00:00 2001 From: jeremy-jang <35089715+jeremy-jang@users.noreply.github.com> Date: Fri, 10 Sep 2021 14:15:28 +0900 Subject: [PATCH] [Cion] Add new APIs for Advanced Companion Framework (#3472) * [Cion] Add new APIs for Advanced Companion Framework Signed-off-by: Sangyoon Jang * [Cion] Remove PayloadAsyncResult.Id This is removed from the design. Signed-off-by: Sangyoon Jang * Fix Cion - Fix namespace of SecurityInfo, SecuritySafeHandle - Fix some callback lifecycle (unmanged) - Fix some simple getters to property - Fix IPayload to Payload - Fix some bad code Signed-off-by: Sangyoon Jang * Fix Cion - Fix ClientBase.SendPayloadAsync to return Task - Fix doxygen comments - Fix some bad code Signed-off-by: Sangyoon Jang * Fix Cion - Add missing doxygen comments - Fix some bad code Signed-off-by: Sangyoon Jang * Fix ServerBase.SendPayloadAsync Fix same as ClientBase. Signed-off-by: Sangyoon Jang * Fix Cion csproj file Signed-off-by: Sangyoon Jang * Fix Cion - Fix IDisposable code - Fix bad exception throwing - Fix SendPayloadAsync - Fix setting connectied peer of ClientBase Signed-off-by: Sangyoon Jang * Add missing public keyword Signed-off-by: Sangyoon Jang * Add missing API and fix doxygen comments Signed-off-by: Sangyoon Jang * Fix Cion - Fix some doxygen comments. - Remove PayloadAsyncResultSafeHandle class. - Fix Ctor of PayloadAsyncResult. - Fix to remove unmanaged callback after setting result. Signed-off-by: Sangyoon Jang * Fix PayloadAsyncResultCode.Dispose() The property PeerInfo is a managed object. Signed-off-by: Sangyoon Jang * Fix Cion - Fix ClientBase.SendData to use Marshal.Copy - Fix SendPayloadAsync to handle error case - Fix some bad code Signed-off-by: Sangyoon Jang Co-authored-by: pjh9216 --- .../Interop/Interop.Cion.cs | 32 ++ .../Interop/Interop.CionClient.cs | 75 ++++ .../Interop/Interop.CionConnectionResult.cs | 33 ++ .../Interop/Interop.CionGroup.cs | 60 +++ .../Interop/Interop.CionPayload.cs | 66 ++++ .../Interop/Interop.CionPayloadAsyncResult.cs | 36 ++ .../Interop/Interop.CionPeerInfo.cs | 57 +++ .../Interop/Interop.CionSecurity.cs | 51 +++ .../Interop/Interop.CionServer.cs | 97 +++++ .../Interop/Interop.Libraries.cs | 23 ++ .../Tizen.Applications.Cion.csproj | 13 + .../Tizen.Applications.Cion.sln | 37 ++ .../Tizen.Applications/Cion/SecurityInfo.cs | 159 ++++++++ .../Tizen.Applications/Cion/SecuritySafeHandle.cs | 43 +++ .../Tizen.Applications/CionErrorFactory.cs | 45 +++ .../Tizen.Applications/ClientBase.cs | 366 ++++++++++++++++++ .../Tizen.Applications/ClientSafeHandle.cs | 43 +++ .../Tizen.Applications/ConnectionResult.cs | 60 +++ .../Tizen.Applications/ConnectionStatus.cs | 38 ++ .../Tizen.Applications/DataPayload.cs | 78 ++++ .../Tizen.Applications/FilePayload.cs | 126 +++++++ .../Tizen.Applications/GroupBase.cs | 217 +++++++++++ .../Tizen.Applications/GroupSafeHandle.cs | 43 +++ .../Tizen.Applications/Payload.cs | 52 +++ .../Tizen.Applications/PayloadAsyncResult.cs | 111 ++++++ .../Tizen.Applications/PayloadAsyncResultCode.cs | 42 +++ .../Tizen.Applications/PayloadSafeHandle.cs | 48 +++ .../Tizen.Applications/PayloadTransferStatus.cs | 38 ++ .../Tizen.Applications/PayloadType.cs | 34 ++ .../Tizen.Applications/PeerInfo.cs | 210 +++++++++++ .../Tizen.Applications/PeerInfoSafeHandle.cs | 48 +++ .../Tizen.Applications/ServerBase.cs | 407 +++++++++++++++++++++ .../Tizen.Applications/ServerSafeHandle.cs | 43 +++ 33 files changed, 2831 insertions(+) create mode 100644 src/Tizen.Applications.Cion/Interop/Interop.Cion.cs create mode 100644 src/Tizen.Applications.Cion/Interop/Interop.CionClient.cs create mode 100644 src/Tizen.Applications.Cion/Interop/Interop.CionConnectionResult.cs create mode 100644 src/Tizen.Applications.Cion/Interop/Interop.CionGroup.cs create mode 100644 src/Tizen.Applications.Cion/Interop/Interop.CionPayload.cs create mode 100644 src/Tizen.Applications.Cion/Interop/Interop.CionPayloadAsyncResult.cs create mode 100755 src/Tizen.Applications.Cion/Interop/Interop.CionPeerInfo.cs create mode 100755 src/Tizen.Applications.Cion/Interop/Interop.CionSecurity.cs create mode 100644 src/Tizen.Applications.Cion/Interop/Interop.CionServer.cs create mode 100644 src/Tizen.Applications.Cion/Interop/Interop.Libraries.cs create mode 100755 src/Tizen.Applications.Cion/Tizen.Applications.Cion.csproj create mode 100644 src/Tizen.Applications.Cion/Tizen.Applications.Cion.sln create mode 100755 src/Tizen.Applications.Cion/Tizen.Applications/Cion/SecurityInfo.cs create mode 100755 src/Tizen.Applications.Cion/Tizen.Applications/Cion/SecuritySafeHandle.cs create mode 100755 src/Tizen.Applications.Cion/Tizen.Applications/CionErrorFactory.cs create mode 100644 src/Tizen.Applications.Cion/Tizen.Applications/ClientBase.cs create mode 100755 src/Tizen.Applications.Cion/Tizen.Applications/ClientSafeHandle.cs create mode 100644 src/Tizen.Applications.Cion/Tizen.Applications/ConnectionResult.cs create mode 100644 src/Tizen.Applications.Cion/Tizen.Applications/ConnectionStatus.cs create mode 100644 src/Tizen.Applications.Cion/Tizen.Applications/DataPayload.cs create mode 100644 src/Tizen.Applications.Cion/Tizen.Applications/FilePayload.cs create mode 100644 src/Tizen.Applications.Cion/Tizen.Applications/GroupBase.cs create mode 100644 src/Tizen.Applications.Cion/Tizen.Applications/GroupSafeHandle.cs create mode 100644 src/Tizen.Applications.Cion/Tizen.Applications/Payload.cs create mode 100644 src/Tizen.Applications.Cion/Tizen.Applications/PayloadAsyncResult.cs create mode 100644 src/Tizen.Applications.Cion/Tizen.Applications/PayloadAsyncResultCode.cs create mode 100755 src/Tizen.Applications.Cion/Tizen.Applications/PayloadSafeHandle.cs create mode 100644 src/Tizen.Applications.Cion/Tizen.Applications/PayloadTransferStatus.cs create mode 100755 src/Tizen.Applications.Cion/Tizen.Applications/PayloadType.cs create mode 100755 src/Tizen.Applications.Cion/Tizen.Applications/PeerInfo.cs create mode 100755 src/Tizen.Applications.Cion/Tizen.Applications/PeerInfoSafeHandle.cs create mode 100644 src/Tizen.Applications.Cion/Tizen.Applications/ServerBase.cs create mode 100755 src/Tizen.Applications.Cion/Tizen.Applications/ServerSafeHandle.cs diff --git a/src/Tizen.Applications.Cion/Interop/Interop.Cion.cs b/src/Tizen.Applications.Cion/Interop/Interop.Cion.cs new file mode 100644 index 0000000..cbfa407 --- /dev/null +++ b/src/Tizen.Applications.Cion/Interop/Interop.Cion.cs @@ -0,0 +1,32 @@ +/* + * 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 Cion + { + internal enum ErrorCode : int + { + 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, + InvalidOperation = Tizen.Internals.Errors.ErrorCode.InvalidOperation, + NotSupported = Tizen.Internals.Errors.ErrorCode.NotSupported, + } + } +} diff --git a/src/Tizen.Applications.Cion/Interop/Interop.CionClient.cs b/src/Tizen.Applications.Cion/Interop/Interop.CionClient.cs new file mode 100644 index 0000000..584be13 --- /dev/null +++ b/src/Tizen.Applications.Cion/Interop/Interop.CionClient.cs @@ -0,0 +1,75 @@ +/* + * 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 ErrorCode = Interop.Cion.ErrorCode; + +internal static partial class Interop +{ + internal static partial class CionClient + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CionClientDiscoveredCb(string serviceName, IntPtr peerInfo, IntPtr userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CionClientConnectionResultCb(string serviceName, IntPtr peerInfo, IntPtr result, IntPtr userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CionClientPayloadRecievedCb(string serviceName, IntPtr peerInfo, IntPtr payload, int status, IntPtr userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CionClientDisconnectedCb(string serviceName, IntPtr peerInfo, IntPtr userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CionClientPayloadAsyncResultCb(IntPtr result, IntPtr userData); + + [DllImport(Libraries.Cion, EntryPoint = "cion_client_create")] + internal static extern ErrorCode CionClientCreate(out ClientSafeHandle client, string serviceName, IntPtr security); + + [DllImport(Libraries.Cion, EntryPoint = "cion_client_destory")] + internal static extern ErrorCode CionClientDestroy(IntPtr client); + + [DllImport(Libraries.Cion, EntryPoint = "cion_client_try_discovery")] + internal static extern ErrorCode CionClientTryDiscovery(ClientSafeHandle client, CionClientDiscoveredCb cb, IntPtr userData); + + [DllImport(Libraries.Cion, EntryPoint = "cion_client_stop_discovery")] + internal static extern ErrorCode CionClientStopDiscovery(ClientSafeHandle client); + + [DllImport(Libraries.Cion, EntryPoint = "cion_client_connect")] + internal static extern ErrorCode CionClientConnect(ClientSafeHandle client, PeerInfoSafeHandle peerInfo); + + [DllImport(Libraries.Cion, EntryPoint = "cion_client_disconnect")] + internal static extern ErrorCode CionClientDisconnect(ClientSafeHandle client); + + [DllImport(Libraries.Cion, EntryPoint = "cion_client_send_data")] + internal static extern ErrorCode CionClientSendData(ClientSafeHandle client, byte[] data, int dataSize, int timeout, out IntPtr returnData, out int returnDataSize); + + [DllImport(Libraries.Cion, EntryPoint = "cion_client_send_payload_async")] + internal static extern ErrorCode CionClientSendPayloadAsync(ClientSafeHandle client, PayloadSafeHandle payload, CionClientPayloadAsyncResultCb cb, IntPtr userData); + + [DllImport(Libraries.Cion, EntryPoint = "cion_client_add_connection_result_cb")] + internal static extern ErrorCode CionClientAddConnectionResultCb(ClientSafeHandle client, CionClientConnectionResultCb cb, IntPtr userData); + + [DllImport(Libraries.Cion, EntryPoint = "cion_client_add_payload_recieved_cb")] + internal static extern ErrorCode CionClientAddPayloadReceivedCb(ClientSafeHandle client, CionClientPayloadRecievedCb cb, IntPtr userData); + + [DllImport(Libraries.Cion, EntryPoint = "cion_client_add_disconnected_cb")] + internal static extern ErrorCode CionClientAddDisconnectedCb(ClientSafeHandle client, CionClientDisconnectedCb cb, IntPtr userData); + } +} diff --git a/src/Tizen.Applications.Cion/Interop/Interop.CionConnectionResult.cs b/src/Tizen.Applications.Cion/Interop/Interop.CionConnectionResult.cs new file mode 100644 index 0000000..359527c --- /dev/null +++ b/src/Tizen.Applications.Cion/Interop/Interop.CionConnectionResult.cs @@ -0,0 +1,33 @@ +/* + * 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 ErrorCode = Interop.Cion.ErrorCode; + +internal static partial class Interop +{ + internal static partial class CionConnectionResult + { + [DllImport(Libraries.Cion, EntryPoint = "cion_connection_result_get_status")] + internal static extern ErrorCode CionConnectionResultGetStatus(IntPtr result, out ConnectionStatus status); + + [DllImport(Libraries.Cion, EntryPoint = "cion_connection_result_get_reason")] + internal static extern ErrorCode CionConnectionResultGetReason(IntPtr result, out string reason); + } +} diff --git a/src/Tizen.Applications.Cion/Interop/Interop.CionGroup.cs b/src/Tizen.Applications.Cion/Interop/Interop.CionGroup.cs new file mode 100644 index 0000000..03cbb65 --- /dev/null +++ b/src/Tizen.Applications.Cion/Interop/Interop.CionGroup.cs @@ -0,0 +1,60 @@ +/* + * 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 ErrorCode = Interop.Cion.ErrorCode; + +internal static partial class Interop +{ + internal static partial class CionGroup + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CionGroupPayloadReceivedCb(IntPtr group, IntPtr peerInfo, IntPtr payload, IntPtr userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CionGroupJoinedCb(string topicName, IntPtr peerInfo, IntPtr userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CionGroupLeftCb(string topicName, IntPtr peerInfo, IntPtr userData); + + [DllImport(Libraries.Cion, EntryPoint = "cion_group_create")] + internal static extern ErrorCode CionGroupCreate(out GroupSafeHandle group, string topicName, IntPtr security); + + [DllImport(Libraries.Cion, EntryPoint = "cion_group_destroy")] + internal static extern ErrorCode CionGroupDestroy(IntPtr group); + + [DllImport(Libraries.Cion, EntryPoint = "cion_group_subscribe")] + internal static extern ErrorCode CionGroupSubscribe(GroupSafeHandle group); + + [DllImport(Libraries.Cion, EntryPoint = "cion_group_unsubscribe")] + internal static extern ErrorCode CionGroupUnsubscribe(GroupSafeHandle group); + + [DllImport(Libraries.Cion, EntryPoint = "cion_group_publish")] + internal static extern ErrorCode CionGroupPublish(GroupSafeHandle group, PayloadSafeHandle data); + + [DllImport(Libraries.Cion, EntryPoint = "cion_group_add_payload_received_cb")] + internal static extern ErrorCode CionGroupAddPayloadReceivedCb(GroupSafeHandle group, CionGroupPayloadReceivedCb cb, IntPtr userData); + + [DllImport(Libraries.Cion, EntryPoint = "cion_group_add_joined_cb")] + internal static extern ErrorCode CionGroupAddJoinedCb(GroupSafeHandle group, CionGroupJoinedCb cb, IntPtr userData); + + [DllImport(Libraries.Cion, EntryPoint = "cion_group_add_left_cb")] + internal static extern ErrorCode CionGroupAddLeftCb(GroupSafeHandle group, CionGroupLeftCb cb, IntPtr userData); + } +} diff --git a/src/Tizen.Applications.Cion/Interop/Interop.CionPayload.cs b/src/Tizen.Applications.Cion/Interop/Interop.CionPayload.cs new file mode 100644 index 0000000..9d9f87d --- /dev/null +++ b/src/Tizen.Applications.Cion/Interop/Interop.CionPayload.cs @@ -0,0 +1,66 @@ +/* + * 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 ErrorCode = Interop.Cion.ErrorCode; + +internal static partial class Interop +{ + internal static partial class CionPayload + { + internal enum PayloadType : int + { + Data, + File, + } + + [DllImport(Libraries.Cion, EntryPoint = "cion_payload_create")] + internal static extern ErrorCode CionPayloadCreate(out PayloadSafeHandle payload, PayloadType type); + + [DllImport(Libraries.Cion, EntryPoint = "cion_payload_destroy")] + internal static extern ErrorCode CionPayloadDestroy(IntPtr payload); + + [DllImport(Libraries.Cion, EntryPoint = "cion_payload_get_type")] + internal static extern ErrorCode CionPayloadGetType(IntPtr payload, out PayloadType type); + + [DllImport(Libraries.Cion, EntryPoint = "cion_payload_get_data")] + internal static extern ErrorCode CionPayloadGetData(PayloadSafeHandle payload, out IntPtr data, out int dataSize); + + [DllImport(Libraries.Cion, EntryPoint = "cion_payload_set_data")] + internal static extern ErrorCode CionPayloadSetData(PayloadSafeHandle payload, byte[] data, int dataSize); + + [DllImport(Libraries.Cion, EntryPoint = "cion_payload_save_as_file")] + internal static extern ErrorCode CionPayloadSaveAsFile(PayloadSafeHandle payload, string path); + + [DllImport(Libraries.Cion, EntryPoint = "cion_payload_get_received_file_name")] + internal static extern ErrorCode CionPayloadGetReceivedFileName(PayloadSafeHandle payload, out string path); + + [DllImport(Libraries.Cion, EntryPoint = "cion_payload_get_received_bytes")] + internal static extern ErrorCode CionPayloadGetReceivedBytes(PayloadSafeHandle payload, out UInt64 bytes); + + [DllImport(Libraries.Cion, EntryPoint = "cion_payload_get_total_bytes")] + internal static extern ErrorCode CionPayloadGetTotalBytes(PayloadSafeHandle payload, out UInt64 bytes); + + [DllImport(Libraries.Cion, EntryPoint = "cion_payload_set_file_path")] + internal static extern ErrorCode CionPayloadSetFilePath(PayloadSafeHandle payload, string path); + + [DllImport(Libraries.Cion, EntryPoint = "cion_payload_get_payload_id")] + internal static extern ErrorCode CionPayloadGetPayloadID(PayloadSafeHandle payload, out string id); + } +} diff --git a/src/Tizen.Applications.Cion/Interop/Interop.CionPayloadAsyncResult.cs b/src/Tizen.Applications.Cion/Interop/Interop.CionPayloadAsyncResult.cs new file mode 100644 index 0000000..8cc12f1 --- /dev/null +++ b/src/Tizen.Applications.Cion/Interop/Interop.CionPayloadAsyncResult.cs @@ -0,0 +1,36 @@ +/* + * 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 ErrorCode = Interop.Cion.ErrorCode; + +internal static partial class Interop +{ + internal static partial class CionPayloadAsyncResult + { + [DllImport(Libraries.Cion, EntryPoint = "cion_payload_async_result_get_result")] + internal static extern ErrorCode CionPayloadAsyncResultGetResult(IntPtr result, out int code); + + [DllImport(Libraries.Cion, EntryPoint = "cion_payload_async_result_get_peer_info")] + internal static extern ErrorCode CionPayloadAsyncResultGetPeerInfo(IntPtr result, out IntPtr peerInfo); + + [DllImport(Libraries.Cion, EntryPoint = "cion_payload_async_result_get_payload_id")] + internal static extern ErrorCode CionPayloadAsyncResultGetPayloadID(IntPtr result, out string payloadID); + } +} diff --git a/src/Tizen.Applications.Cion/Interop/Interop.CionPeerInfo.cs b/src/Tizen.Applications.Cion/Interop/Interop.CionPeerInfo.cs new file mode 100755 index 0000000..daa08e9 --- /dev/null +++ b/src/Tizen.Applications.Cion/Interop/Interop.CionPeerInfo.cs @@ -0,0 +1,57 @@ +/* + * 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 ErrorCode = Interop.Cion.ErrorCode; + +internal static partial class Interop +{ + internal static partial class CionPeerInfo + { + [DllImport(Libraries.Cion, EntryPoint = "cion_peer_info_clone")] + internal static extern ErrorCode CionPeerInfoClone(IntPtr peerInfo, out PeerInfoSafeHandle peerInfoClone); + + [DllImport(Libraries.Cion, EntryPoint = "cion_peer_info_destroy")] + internal static extern ErrorCode CionPeerInfoDestroy(IntPtr peerInfo); + + [DllImport(Libraries.Cion, EntryPoint = "cion_peer_info_get_device_id")] + internal static extern ErrorCode CionPeerInfoGetDeviceId(PeerInfoSafeHandle peerInfo, out string deviceId); + + [DllImport(Libraries.Cion, EntryPoint = "cion_peer_info_get_device_name")] + internal static extern ErrorCode CionPeerInfoGetDeviceName(PeerInfoSafeHandle peerInfo, out string deviceName); + + [DllImport(Libraries.Cion, EntryPoint = "cion_peer_info_get_device_platform")] + internal static extern ErrorCode CionPeerInfoGetDevicePlatform(PeerInfoSafeHandle peerInfo, out string devicePlatform); + + [DllImport(Libraries.Cion, EntryPoint = "cion_peer_info_get_device_platform_version")] + internal static extern ErrorCode CionPeerInfoGetDevicePlatformVersion(PeerInfoSafeHandle peerInfo, out string devicePlatformVersion); + + [DllImport(Libraries.Cion, EntryPoint = "cion_peer_info_get_device_type")] + internal static extern ErrorCode CionPeerInfoGetDeviceType(PeerInfoSafeHandle peerInfo, out string deviceType); + + [DllImport(Libraries.Cion, EntryPoint = "cion_peer_info_get_app_id")] + internal static extern ErrorCode CionPeerInfoGetAppId(PeerInfoSafeHandle peerInfo, out string appId); + + [DllImport(Libraries.Cion, EntryPoint = "cion_peer_info_get_app_version")] + internal static extern ErrorCode CionPeerInfoGetAppVersion(PeerInfoSafeHandle peerInfo, out string appVersion); + + [DllImport(Libraries.Cion, EntryPoint = "cion_peer_info_get_uuid")] + internal static extern ErrorCode CionPeerInfoGetUuid(PeerInfoSafeHandle peerInfo, out string uuid); + } +} diff --git a/src/Tizen.Applications.Cion/Interop/Interop.CionSecurity.cs b/src/Tizen.Applications.Cion/Interop/Interop.CionSecurity.cs new file mode 100755 index 0000000..e4db7a8 --- /dev/null +++ b/src/Tizen.Applications.Cion/Interop/Interop.CionSecurity.cs @@ -0,0 +1,51 @@ +/* + * 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.Cion; + +using ErrorCode = Interop.Cion.ErrorCode; + +internal static partial class Interop +{ + internal static partial class CionSecurity + { + [DllImport(Libraries.Cion, EntryPoint = "cion_security_create")] + internal static extern ErrorCode CionSecurityCreate(out SecuritySafeHandle security); + + [DllImport(Libraries.Cion, EntryPoint = "cion_security_destroy")] + internal static extern ErrorCode CionSecurityDestroy(IntPtr security); + + [DllImport(Libraries.Cion, EntryPoint = "cion_security_set_ca_path")] + internal static extern ErrorCode CionSecuritySetCaPath(SecuritySafeHandle peerInfo, string caPath); + + [DllImport(Libraries.Cion, EntryPoint = "cion_security_set_cert_path")] + internal static extern ErrorCode CionSecuritySetCertPath(SecuritySafeHandle peerInfo, string certPath); + + [DllImport(Libraries.Cion, EntryPoint = "cion_security_set_private_key_path")] + internal static extern ErrorCode CionSecuritySetPrivateKeyPath(SecuritySafeHandle peerInfo, string keyPath); + + [DllImport(Libraries.Cion, EntryPoint = "cion_security_get_ca_path")] + internal static extern ErrorCode CionSecurityGetCaPath(SecuritySafeHandle peerInfo, out string caPath); + + [DllImport(Libraries.Cion, EntryPoint = "cion_security_get_cert_path")] + internal static extern ErrorCode CionSecurityGetCertPath(SecuritySafeHandle peerInfo, out string certPath); + + [DllImport(Libraries.Cion, EntryPoint = "cion_security_get_private_key_path")] + internal static extern ErrorCode CionSecurityGetPrivateKeyPath(SecuritySafeHandle peerInfo, out string keyPath); + } +} diff --git a/src/Tizen.Applications.Cion/Interop/Interop.CionServer.cs b/src/Tizen.Applications.Cion/Interop/Interop.CionServer.cs new file mode 100644 index 0000000..b4eedf4 --- /dev/null +++ b/src/Tizen.Applications.Cion/Interop/Interop.CionServer.cs @@ -0,0 +1,97 @@ +/* + * 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 ErrorCode = Interop.Cion.ErrorCode; + +internal static partial class Interop +{ + internal static partial class CionServer + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CionServerPeerInfoIterator(IntPtr peerInfo, IntPtr userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CionServerPayloadAsyncResultCb(IntPtr result, IntPtr userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CionServerConnectionResultCb(string serviceName, IntPtr peerInfo, IntPtr result, IntPtr userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CionServerDataReceivedCb(string serviceName, IntPtr peerInfo, byte[] data, int dataSize, out byte[] returnData, out int returnDataSize, IntPtr userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CionServerPayloadRecievedCb(string serviceName, IntPtr peerInfo, IntPtr payload, int status, IntPtr userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CionServerConnectionRequestCb(string serviceName, IntPtr peerInfo, IntPtr userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CionServerErrorReportedCb(string serviceName, IntPtr peerInfo, int error, IntPtr userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CionServerDisconnectedCb(string serviceName, IntPtr peerInfo, IntPtr userData); + + [DllImport(Libraries.Cion, EntryPoint = "cion_server_create")] + internal static extern ErrorCode CionServerCreate(out ServerSafeHandle server, string serviceName, string displayName, IntPtr security); + + [DllImport(Libraries.Cion, EntryPoint = "cion_server_destory")] + internal static extern ErrorCode CionServerDestroy(IntPtr server); + + [DllImport(Libraries.Cion, EntryPoint = "cion_server_listen")] + internal static extern ErrorCode CionServerListen(ServerSafeHandle server, CionServerConnectionRequestCb cb, IntPtr userData); + + [DllImport(Libraries.Cion, EntryPoint = "cion_server_stop")] + internal static extern ErrorCode CionServerStop(ServerSafeHandle server); + + [DllImport(Libraries.Cion, EntryPoint = "cion_server_accept")] + internal static extern ErrorCode CionServerAccept(ServerSafeHandle server, PeerInfoSafeHandle peerInfo); + + [DllImport(Libraries.Cion, EntryPoint = "cion_server_reject")] + internal static extern ErrorCode CionServerReject(ServerSafeHandle server, PeerInfoSafeHandle peerInfo, string reason); + + [DllImport(Libraries.Cion, EntryPoint = "cion_server_disconnect")] + internal static extern ErrorCode CionServerDisconnect(ServerSafeHandle server, PeerInfoSafeHandle peerInfo); + + [DllImport(Libraries.Cion, EntryPoint = "cion_server_send_payload_async")] + internal static extern ErrorCode CionServerSendPayloadAsync(ServerSafeHandle server, PeerInfoSafeHandle peerInfo, PayloadSafeHandle payload, + CionServerPayloadAsyncResultCb cb, IntPtr userData); + + [DllImport(Libraries.Cion, EntryPoint = "cion_server_foreach_connected_peer_info")] + internal static extern ErrorCode CionServerForeachConnectedPeerInfo(ServerSafeHandle server, CionServerPeerInfoIterator cb, IntPtr userData); + + [DllImport(Libraries.Cion, EntryPoint = "cion_server_add_connection_result_cb")] + internal static extern ErrorCode CionServerAddConnectionResultCb(ServerSafeHandle server, CionServerConnectionResultCb cb, IntPtr userData); + + [DllImport(Libraries.Cion, EntryPoint = "cion_server_add_payload_recieved_cb")] + internal static extern ErrorCode CionServerAddPayloadReceivedCb(ServerSafeHandle server, CionServerPayloadRecievedCb cb, IntPtr userData); + + [DllImport(Libraries.Cion, EntryPoint = "cion_server_add_error_reported_cb")] + internal static extern ErrorCode CionServerAddErrorReportedCb(ServerSafeHandle server, CionServerErrorReportedCb cb, IntPtr userData); + + [DllImport(Libraries.Cion, EntryPoint = "cion_server_set_data_recieved_cb")] + internal static extern ErrorCode CionServerSetDataReceivedCb(ServerSafeHandle server, CionServerDataReceivedCb cb, IntPtr userData); + + [DllImport(Libraries.Cion, EntryPoint = "cion_server_add_disconnected_cb")] + internal static extern ErrorCode CionServerAddDisconnectedCb(ServerSafeHandle server, CionServerDisconnectedCb cb, IntPtr userData); + + [DllImport(Libraries.Cion, EntryPoint = "cion_server_set_ondemand_launch_enable")] + internal static extern ErrorCode CionServerSetOndemandLaunchEnable(ServerSafeHandle server, bool enable); + } +} diff --git a/src/Tizen.Applications.Cion/Interop/Interop.Libraries.cs b/src/Tizen.Applications.Cion/Interop/Interop.Libraries.cs new file mode 100644 index 0000000..32af828 --- /dev/null +++ b/src/Tizen.Applications.Cion/Interop/Interop.Libraries.cs @@ -0,0 +1,23 @@ +/* + * 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 Cion = "libcion.so.1"; + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications.Cion.csproj b/src/Tizen.Applications.Cion/Tizen.Applications.Cion.csproj new file mode 100755 index 0000000..b1f36fa --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications.Cion.csproj @@ -0,0 +1,13 @@ + + + + netstandard2.0 + + + + + + + + + diff --git a/src/Tizen.Applications.Cion/Tizen.Applications.Cion.sln b/src/Tizen.Applications.Cion/Tizen.Applications.Cion.sln new file mode 100644 index 0000000..26ebd2d --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications.Cion.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31613.86 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tizen.Applications.Cion", "Tizen.Applications.Cion.csproj", "{9FDBB6A2-0E97-4B7F-8C71-C09C3C37A44E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tizen", "..\Tizen\Tizen.csproj", "{DA6CC280-5D47-4A88-A7D0-D96156C03DAA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tizen.Log", "..\Tizen.Log\Tizen.Log.csproj", "{DB0F0139-CDFD-41E6-B8F7-CAE066DDFA6D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9FDBB6A2-0E97-4B7F-8C71-C09C3C37A44E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9FDBB6A2-0E97-4B7F-8C71-C09C3C37A44E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9FDBB6A2-0E97-4B7F-8C71-C09C3C37A44E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9FDBB6A2-0E97-4B7F-8C71-C09C3C37A44E}.Release|Any CPU.Build.0 = Release|Any CPU + {DA6CC280-5D47-4A88-A7D0-D96156C03DAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DA6CC280-5D47-4A88-A7D0-D96156C03DAA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DA6CC280-5D47-4A88-A7D0-D96156C03DAA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DA6CC280-5D47-4A88-A7D0-D96156C03DAA}.Release|Any CPU.Build.0 = Release|Any CPU + {DB0F0139-CDFD-41E6-B8F7-CAE066DDFA6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DB0F0139-CDFD-41E6-B8F7-CAE066DDFA6D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DB0F0139-CDFD-41E6-B8F7-CAE066DDFA6D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DB0F0139-CDFD-41E6-B8F7-CAE066DDFA6D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0A1F9790-D5BF-4F3F-BAB5-CB9C7B1DA87F} + EndGlobalSection +EndGlobal diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/Cion/SecurityInfo.cs b/src/Tizen.Applications.Cion/Tizen.Applications/Cion/SecurityInfo.cs new file mode 100755 index 0000000..21a8445 --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/Cion/SecurityInfo.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; + +namespace Tizen.Applications.Cion +{ + /// + /// A class to represent security info. + /// + /// 9 + public class SecurityInfo : IDisposable + { + private readonly string LogTag = "Tizen.Cion"; + internal SecuritySafeHandle _handle = null; + + /// + /// The constructor of SecurityInfo class. + /// + /// Thrown when there is not enough memory to continue the execution of the method. + /// 9 + public SecurityInfo() + { + Interop.Cion.ErrorCode ret = Interop.CionSecurity.CionSecurityCreate(out _handle); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to create security info."); + } + } + + /// + /// Gets the CA cert path. + /// + /// Thrown when the CA path is invalid. + /// 9 + public string CaPath + { + get + { + Interop.Cion.ErrorCode ret = Interop.CionSecurity.CionSecurityGetCaPath(_handle, out string caPath); + if (ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, "Failed to get CA path."); + return ""; + } + return caPath; + } + + set + { + Interop.Cion.ErrorCode ret = Interop.CionSecurity.CionSecuritySetCaPath(_handle, value); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to set CA path."); + } + } + } + + /// + /// Gets the cert path. + /// + /// Thrown when the cert path is invalid. + /// 9 + public string CertPath + { + get + { + Interop.Cion.ErrorCode ret = Interop.CionSecurity.CionSecurityGetCertPath(_handle, out string certPath); + if (ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, "Failed to get cert path."); + return ""; + } + return certPath; + } + + set + { + Interop.Cion.ErrorCode ret = Interop.CionSecurity.CionSecuritySetCertPath(_handle, value); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to set cert path."); + } + } + } + + /// + /// Gets the private key path. + /// + /// Thrown when the private key path is invalid. + /// 9 + public string PrivateKeyPath + { + get + { + Interop.Cion.ErrorCode ret = Interop.CionSecurity.CionSecurityGetPrivateKeyPath(_handle, out string privateKeyPath); + if (ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, "Failed to get private key path."); + return ""; + } + return privateKeyPath; + } + + set + { + Interop.Cion.ErrorCode ret = Interop.CionSecurity.CionSecuritySetPrivateKeyPath(_handle, value); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to set private key path."); + } + } + } + + #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. If false, does not dispose disposable objects. + /// 9 + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + _handle.Dispose(); + } + disposedValue = true; + } + } + + /// + /// Releases all resources used by the SecurityInfo class. + /// + /// 9 + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + #endregion + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/Cion/SecuritySafeHandle.cs b/src/Tizen.Applications.Cion/Tizen.Applications/Cion/SecuritySafeHandle.cs new file mode 100755 index 0000000..2f96bf9 --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/Cion/SecuritySafeHandle.cs @@ -0,0 +1,43 @@ +/* + * 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.ComponentModel; +using System.Runtime.InteropServices; + +namespace Tizen.Applications.Cion +{ + internal sealed class SecuritySafeHandle : SafeHandle + { + [EditorBrowsable(EditorBrowsableState.Never)] + public SecuritySafeHandle() : base(IntPtr.Zero, true) + { + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool IsInvalid + { + get { return this.DangerousGetHandle() == IntPtr.Zero; } + } + + protected override bool ReleaseHandle() + { + Interop.CionSecurity.CionSecurityDestroy(this.handle); + SetHandle(IntPtr.Zero); + return true; + } + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/CionErrorFactory.cs b/src/Tizen.Applications.Cion/Tizen.Applications/CionErrorFactory.cs new file mode 100755 index 0000000..48e54e8 --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/CionErrorFactory.cs @@ -0,0 +1,45 @@ +/* + * 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; + +namespace Tizen.Applications +{ + internal static class CionErrorFactory + { + internal static Exception GetException(Interop.Cion.ErrorCode err, string message) + { + string errMessage = string.Format("{0} err = {1}", message, err); + switch (err) + { + case Interop.Cion.ErrorCode.InvalidParameter: + return new ArgumentException(errMessage); + case Interop.Cion.ErrorCode.OutOfMemory: + return new InvalidOperationException(errMessage); + case Interop.Cion.ErrorCode.IoError: + return new global::System.IO.IOException(errMessage); + case Interop.Cion.ErrorCode.PermissionDenied: + return new UnauthorizedAccessException(errMessage); + case Interop.Cion.ErrorCode.InvalidOperation: + return new InvalidOperationException(errMessage); + case Interop.Cion.ErrorCode.NotSupported: + return new NotSupportedException(errMessage); + default: + return new InvalidOperationException(errMessage); + } + } + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/ClientBase.cs b/src/Tizen.Applications.Cion/Tizen.Applications/ClientBase.cs new file mode 100644 index 0000000..3c913cd --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/ClientBase.cs @@ -0,0 +1,366 @@ +/* + * 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.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace Tizen.Applications +{ + /// + /// An abstract class to represent cion client. + /// + /// 9 + public abstract class ClientBase : IDisposable + { + private readonly string LogTag = "Tizen.Cion"; + private readonly ClientSafeHandle _handle; + + private PeerInfo _peer; + + private Interop.CionClient.CionClientDiscoveredCb _discoveredCb; + private Interop.CionClient.CionClientConnectionResultCb _connectionResultCb; + private Interop.CionClient.CionClientPayloadRecievedCb _payloadRecievedCb; + private Interop.CionClient.CionClientDisconnectedCb _disconnectedCb; + private Interop.CionClient.CionClientPayloadAsyncResultCb _payloadAsyncResultCb; + private Dictionary> _tcsDictionary = new Dictionary>(); + + /// + /// Gets the service name of current cion client. + /// + /// 9 + public string ServiceName { get; } + + /// + /// Gets peer info of connected cion server. + /// + /// 9 + public PeerInfo PeerInfo + { + get + { + return _peer; + } + } + + /// + /// The constructor of ClientBase class. + /// + /// The name of service. + /// Thrown when there is not enough memory to continue the execution of the method. + /// 9 + public ClientBase(string serviceName) : this(serviceName, null) { } + + /// + /// The constructor of ClientBase class. + /// + /// The name of service. + /// The security configuration. + /// Thrown when there is not enough memory to continue the execution of the method. + /// 9 + public ClientBase(string serviceName, Cion.SecurityInfo security) + { + ServiceName = serviceName; + + Cion.SecuritySafeHandle handle = security?._handle; + Interop.Cion.ErrorCode ret = Interop.CionClient.CionClientCreate(out _handle, serviceName, handle?.DangerousGetHandle() ?? IntPtr.Zero); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to create client."); + } + + _connectionResultCb = new Interop.CionClient.CionClientConnectionResultCb( + (string service, IntPtr peerInfo, IntPtr result, IntPtr userData) => + { + Interop.Cion.ErrorCode clone_ret = Interop.CionPeerInfo.CionPeerInfoClone(peerInfo, out PeerInfoSafeHandle clone); + if (clone_ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, string.Format("Failed to clone peer info.")); + return; + } + + PeerInfo peer = new PeerInfo(clone); + ConnectionResult connectionResult = new ConnectionResult(result); + if (connectionResult.Status == ConnectionStatus.OK) + { + _peer = peer; + } + + OnConnectionResult(peer, connectionResult); + }); + ret = Interop.CionClient.CionClientAddConnectionResultCb(_handle, _connectionResultCb, IntPtr.Zero); + if (ret != Interop.Cion.ErrorCode.None) + { + _handle.Dispose(); + throw CionErrorFactory.GetException(ret, "Failed to add connection status changed callback."); + } + + _payloadRecievedCb = new Interop.CionClient.CionClientPayloadRecievedCb( + (string service, IntPtr peerInfo, IntPtr payload, int status, IntPtr userData) => + { + Payload receivedPayload; + Interop.CionPayload.CionPayloadGetType(payload, out Interop.CionPayload.PayloadType type); + switch (type) + { + case Interop.CionPayload.PayloadType.Data: + receivedPayload = new DataPayload(new PayloadSafeHandle(payload, false)); + break; + case Interop.CionPayload.PayloadType.File: + receivedPayload = new FilePayload(new PayloadSafeHandle(payload, false)); + break; + default: + Log.Error(LogTag, "Invalid payload type received."); + return; + } + OnPayloadReceived(receivedPayload, (PayloadTransferStatus)status); + }); + ret = Interop.CionClient.CionClientAddPayloadReceivedCb(_handle, _payloadRecievedCb, IntPtr.Zero); + if (ret != Interop.Cion.ErrorCode.None) + { + _handle.Dispose(); + throw CionErrorFactory.GetException(ret, "Failed to add payload received callback."); + } + + _disconnectedCb = new Interop.CionClient.CionClientDisconnectedCb( + (string service, IntPtr peerInfo, IntPtr userData) => + { + Interop.Cion.ErrorCode clone_ret = Interop.CionPeerInfo.CionPeerInfoClone(peerInfo, out PeerInfoSafeHandle clone); + if (clone_ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, string.Format("Failed to clone peer info.")); + return; + } + OnDisconnected(new PeerInfo(clone)); + }); + ret = Interop.CionClient.CionClientAddDisconnectedCb(_handle, _disconnectedCb, IntPtr.Zero); + if (ret != Interop.Cion.ErrorCode.None) + { + _handle.Dispose(); + throw CionErrorFactory.GetException(ret, "Failed to add disconnected callback."); + } + } + + /// + /// Starts discovering cion servers. + /// + /// Thrown when the discovery operation is already in progress. + /// 9 + public void TryDiscovery() + { + Log.Error(LogTag, string.Format("Try discovery start")); + + if (_discoveredCb == null) + { + Interop.CionClient.CionClientDiscoveredCb cb = new Interop.CionClient.CionClientDiscoveredCb( + (string serviceName, IntPtr peerInfo, IntPtr userData) => + { + Log.Error(LogTag, string.Format("callback called !!")); + + Interop.Cion.ErrorCode clone_ret = Interop.CionPeerInfo.CionPeerInfoClone(peerInfo, out PeerInfoSafeHandle clone); + if (clone_ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, "Failed to clone peer info."); + return; + } + OnDiscovered(new PeerInfo(clone)); + }); + _discoveredCb = cb; + } + + Interop.Cion.ErrorCode ret = Interop.CionClient.CionClientTryDiscovery(_handle, _discoveredCb, IntPtr.Zero); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to try discovery."); + } + } + + /// + /// Stops discovering. + /// + /// Thrown when the client is not discovering. + /// 9 + public void StopDiscovery() + { + Interop.Cion.ErrorCode ret = Interop.CionClient.CionClientStopDiscovery(_handle); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to stop discovery."); + } + } + + /// + /// Connects with the cion server. + /// + /// The peer to connect. + /// http://tizen.org/privilege/d2d.datasharing + /// 9 + public void Connect(PeerInfo peer) + { + Interop.Cion.ErrorCode ret = Interop.CionClient.CionClientConnect(_handle, peer?._handle); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to connect."); + } + } + + /// + /// Disconnects from the cion server. + /// + /// 9 + public void Disconnect() + { + Interop.Cion.ErrorCode ret = Interop.CionClient.CionClientDisconnect(_handle); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to disconnect."); + } + _peer = null; + } + + /// + /// Sends data synchronously to the connected cion server. + /// + /// The data to send. + /// The timeout of sending operation. + /// Thrown when the given data is invalid. + /// Thrown when there is no connected cion server. + /// 9 + public byte[] SendData(byte[] data, int timeout) + { + Interop.Cion.ErrorCode ret = Interop.CionClient.CionClientSendData(_handle, data, data?.Length ?? -1, timeout, out IntPtr returnDataPtr, out int returnDataSize); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to send data."); + } + byte[] returnData = new byte[returnDataSize]; + Marshal.Copy(returnDataPtr, returnData, 0, returnDataSize); + Log.Info(LogTag, string.Format("Returned data size: {0}", returnDataSize)); + + return returnData; + } + + /// + /// Sends payload asynchronously to the connected cion server. + /// + /// The payload to send. + /// Thrown when the payload is not valid. + /// Thrown when there is no connected cion server. + /// 9 + public Task SendPayloadAsync(Payload payload) + { + if (payload?.Id.Length == 0) + { + throw new ArgumentException("Payload is invalid."); + } + + TaskCompletionSource tcs = new TaskCompletionSource(); + _tcsDictionary[payload.Id] = tcs; + + if (_payloadAsyncResultCb == null) + { + Interop.CionClient.CionClientPayloadAsyncResultCb cb = new Interop.CionClient.CionClientPayloadAsyncResultCb( + (IntPtr result, IntPtr userData) => + { + TaskCompletionSource tcsToReturn = _tcsDictionary[payload.Id]; + PayloadAsyncResult resultPayload = null; + try + { + resultPayload = PayloadAsyncResult.CreateFromHandle(result); + } + catch (Exception e) + { + Log.Error(LogTag, string.Format("Failed to create PayloadAsyncResult from result handle: {0}.", e.Message)); + tcsToReturn.SetException(e); + return; + } + tcsToReturn.SetResult(resultPayload); + _tcsDictionary.Remove(resultPayload.PayloadId); + }); + _payloadAsyncResultCb = cb; + } + + Interop.Cion.ErrorCode ret = Interop.CionClient.CionClientSendPayloadAsync(_handle, payload?._handle, _payloadAsyncResultCb, IntPtr.Zero); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to send payload."); + } + + return tcs.Task; + } + + /// + /// The result callback of connection request. + /// + /// The peer info of the cion server. + /// The result of the connection. + /// 9 + protected abstract void OnConnectionResult(PeerInfo peerInfo, ConnectionResult result); + + /// + /// The callback invoked when received payload. + /// + /// The received payload. + /// The status of sent payload. + /// 9 + protected abstract void OnPayloadReceived(Payload payload, PayloadTransferStatus status); + + /// + /// The callback invoked when the cion server discovered. + /// + /// The peer info of discovered cion server. + /// 9 + protected abstract void OnDiscovered(PeerInfo peerInfo); + + /// + /// The callback invoked when disconnected with cion client. + /// + /// The peer info of the cion server. + /// 9 + protected abstract void OnDisconnected(PeerInfo peerInfo); + + #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. If false, does not dispose disposable objects. + /// 9 + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + _handle.Dispose(); + } + disposedValue = true; + } + } + + /// + /// Releases all resources used by the ClientBase class. + /// + /// 9 + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + #endregion + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/ClientSafeHandle.cs b/src/Tizen.Applications.Cion/Tizen.Applications/ClientSafeHandle.cs new file mode 100755 index 0000000..72a03d2 --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/ClientSafeHandle.cs @@ -0,0 +1,43 @@ +/* + * 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.ComponentModel; +using System.Runtime.InteropServices; + +namespace Tizen.Applications +{ + internal sealed class ClientSafeHandle : SafeHandle + { + [EditorBrowsable(EditorBrowsableState.Never)] + public ClientSafeHandle() : base(IntPtr.Zero, true) + { + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool IsInvalid + { + get { return this.DangerousGetHandle() == IntPtr.Zero; } + } + + protected override bool ReleaseHandle() + { + Interop.CionClient.CionClientDestroy(this.handle); + SetHandle(IntPtr.Zero); + return true; + } + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/ConnectionResult.cs b/src/Tizen.Applications.Cion/Tizen.Applications/ConnectionResult.cs new file mode 100644 index 0000000..3d04128 --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/ConnectionResult.cs @@ -0,0 +1,60 @@ +/* + * 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; + +namespace Tizen.Applications +{ + /// + /// A class to represent result of connection. + /// + /// 9 + public class ConnectionResult + { + private readonly string _reason; + private readonly ConnectionStatus _status; + + internal ConnectionResult(IntPtr handle) + { + Interop.CionConnectionResult.CionConnectionResultGetReason(handle, out _reason); + Interop.CionConnectionResult.CionConnectionResultGetStatus(handle, out _status); + } + + /// + /// Gets the connection status. + /// + /// 9 + public ConnectionStatus Status + { + get + { + return _status; + } + } + + /// + /// Gets the reason of the connection result. + /// + /// 9 + public string Reason + { + get + { + return _reason; + } + } + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/ConnectionStatus.cs b/src/Tizen.Applications.Cion/Tizen.Applications/ConnectionStatus.cs new file mode 100644 index 0000000..198315d --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/ConnectionStatus.cs @@ -0,0 +1,38 @@ +/* + * 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. + */ + +namespace Tizen.Applications +{ + /// + /// Enumeration for connection status. + /// + /// 9 + public enum ConnectionStatus + { + /// + /// The connection request is accepted. + /// + OK, + /// + /// The connection request is rejected. + /// + Rejected, + /// + /// The error occurred while the connection request is in-progress. + /// + Error, + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/DataPayload.cs b/src/Tizen.Applications.Cion/Tizen.Applications/DataPayload.cs new file mode 100644 index 0000000..3d47ba1 --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/DataPayload.cs @@ -0,0 +1,78 @@ +/* + * 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.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; + +namespace Tizen.Applications +{ + /// + /// A class to represent data type payload. + /// + /// 9 + public class DataPayload : Payload + { + internal DataPayload(PayloadSafeHandle handle) + { + _handle = handle; + } + + /// + /// The constructor of DataPayload class. + /// + /// The data of payload. + /// Thrown when the input data is invalid. + /// 9 + public DataPayload(byte[] data) + { + Interop.CionPayload.CionPayloadCreate(out _handle, Interop.CionPayload.PayloadType.Data); + Interop.CionPayload.CionPayloadSetData(_handle, data, data?.Length ?? -1); + } + + /// + /// Gets type of the payload. + /// + /// 9 + public override PayloadType PayloadType + { + get + { + return PayloadType.DataPayload; + } + } + + /// + /// Gets data of the payload. + /// + /// 9 + public byte[] Data + { + get + { + Interop.CionPayload.CionPayloadGetData(_handle, out IntPtr byteArrPtr, out int size); + byte[] byteArr = new byte[size]; + Marshal.Copy(byteArrPtr, byteArr, 0, size); + return byteArr; + } + set + { + Interop.CionPayload.CionPayloadSetData(_handle, value, value?.Length ?? 0); + } + } + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/FilePayload.cs b/src/Tizen.Applications.Cion/Tizen.Applications/FilePayload.cs new file mode 100644 index 0000000..0861961 --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/FilePayload.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; + +namespace Tizen.Applications +{ + /// + /// A class to represent file type payload. + /// + /// 9 + public class FilePayload : Payload + { + private readonly string LogTag = "Tizen.Cion"; + + internal FilePayload(PayloadSafeHandle handle) + { + _handle = handle; + } + + /// + /// The constructor of FilePayload class. + /// + /// The path of file for the FilePayload. + /// Thrown when the input file path is invalid. + /// 9 + public FilePayload(string path) + { + Interop.CionPayload.CionPayloadCreate(out _handle, Interop.CionPayload.PayloadType.File); + Interop.CionPayload.CionPayloadSetFilePath(_handle, path); + } + + /// + /// Gets the name of received file. + /// + /// 9 + public string ReceivedFileName + { + get + { + Interop.Cion.ErrorCode ret = Interop.CionPayload.CionPayloadGetReceivedFileName(_handle, out string path); + if (ret != Interop.Cion.ErrorCode.None) + { + // property should not throw exception. + return ""; + } + return path; + } + } + + /// + /// Gets size of received file. + /// + /// 9 + public UInt64 ReceivedBytes + { + get + { + Interop.Cion.ErrorCode ret = Interop.CionPayload.CionPayloadGetReceivedBytes(_handle, out UInt64 bytes); + if (ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, "Failed to get received bytes."); + return Byte.MinValue; + } + return bytes; + } + } + + /// + /// Gets total size of the file. + /// + /// 9 + public UInt64 TotalBytes + { + get + { + Interop.Cion.ErrorCode ret = Interop.CionPayload.CionPayloadGetTotalBytes(_handle, out UInt64 bytes); + if (ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, "Failed to get total bytes."); + return Byte.MinValue; + } + return bytes; + } + } + + /// + /// Gets type of the payload. + /// + /// 9 + public override PayloadType PayloadType + { + get + { + return PayloadType.FilePayload; + } + } + + /// + /// Saves file of payload to speicific path. + /// + /// The path of file to save. + /// 9 + public void SaveAsFile(string path) + { + Interop.Cion.ErrorCode ret = Interop.CionPayload.CionPayloadSaveAsFile(_handle, path); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to save as file."); + } + } + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/GroupBase.cs b/src/Tizen.Applications.Cion/Tizen.Applications/GroupBase.cs new file mode 100644 index 0000000..1038537 --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/GroupBase.cs @@ -0,0 +1,217 @@ +/* + * 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; + +namespace Tizen.Applications +{ + /// + /// An abstract class to represent cion group. + /// + /// 9 + public abstract class GroupBase : IDisposable + { + private readonly GroupSafeHandle _handle; + + private Interop.CionGroup.CionGroupPayloadReceivedCb _payloadReceivedCb; + private Interop.CionGroup.CionGroupLeftCb _leftCb; + private Interop.CionGroup.CionGroupJoinedCb _joinedCb; + + /// + /// Gets the topic of current cion group. + /// + /// 9 + public string Topic { get; } + + /// + /// The constructor of GroupBase class. + /// + /// The topic of group. + /// 9 + public GroupBase(string topicName) : this(topicName, null) { } + + /// + /// The constructor of GroupBase class. + /// + /// The topic of group. + /// The security configuration. + /// Thrown when there is not enough memory to continue the execution of the method. + /// 9 + public GroupBase(string topicName, Cion.SecurityInfo security) + { + Topic = topicName; + + Cion.SecuritySafeHandle handle = security?._handle; + Interop.Cion.ErrorCode ret = Interop.CionGroup.CionGroupCreate(out _handle, topicName, handle?.DangerousGetHandle() ?? IntPtr.Zero); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to create group."); + } + + _payloadReceivedCb = new Interop.CionGroup.CionGroupPayloadReceivedCb( + (IntPtr group, IntPtr peerInfo, IntPtr payload, IntPtr userData) => + { + Payload receivedPayload; + Interop.CionPayload.CionPayloadGetType(payload, out Interop.CionPayload.PayloadType type); + switch (type) + { + case Interop.CionPayload.PayloadType.Data: + receivedPayload = new DataPayload(new PayloadSafeHandle(payload, false)); + break; + case Interop.CionPayload.PayloadType.File: + receivedPayload = new FilePayload(new PayloadSafeHandle(payload, false)); + break; + default: + throw new ArgumentException("Invalid payload type received."); + } + OnPayloadReceived(receivedPayload, new PeerInfo(new PeerInfoSafeHandle(peerInfo, false))); + }); + ret = Interop.CionGroup.CionGroupAddPayloadReceivedCb(_handle, _payloadReceivedCb, IntPtr.Zero); + if (ret != Interop.Cion.ErrorCode.None) + { + _handle.Dispose(); + throw CionErrorFactory.GetException(ret, "Failed to add payload received callback."); + } + + _joinedCb = new Interop.CionGroup.CionGroupJoinedCb( + (string name, IntPtr peerInfo, IntPtr userData) => + { + Interop.Cion.ErrorCode clone_ret = Interop.CionPeerInfo.CionPeerInfoClone(peerInfo, out PeerInfoSafeHandle clone); + if (clone_ret != Interop.Cion.ErrorCode.None) + { + return; + } + OnJoined(new PeerInfo(clone)); + }); + ret = Interop.CionGroup.CionGroupAddJoinedCb(_handle, _joinedCb, IntPtr.Zero); + if (ret != Interop.Cion.ErrorCode.None) + { + _handle.Dispose(); + throw CionErrorFactory.GetException(ret, "Failed to add joined callback."); + } + + _leftCb = new Interop.CionGroup.CionGroupLeftCb( + (string name, IntPtr peerInfo, IntPtr userData) => + { + Interop.Cion.ErrorCode clone_ret = Interop.CionPeerInfo.CionPeerInfoClone(peerInfo, out PeerInfoSafeHandle clone); + if (clone_ret != Interop.Cion.ErrorCode.None) + { + return; + } + OnLeft(new PeerInfo(clone)); + }); + ret = Interop.CionGroup.CionGroupAddLeftCb(_handle, _leftCb, IntPtr.Zero); + if (ret != Interop.Cion.ErrorCode.None) + { + _handle.Dispose(); + throw CionErrorFactory.GetException(ret, "Failed to add joined callback."); + } + } + + /// + /// Subscribes the topic. + /// + /// http://tizen.org/privilege/d2d.datasharing + /// 9 + public void Subscribe() + { + Interop.Cion.ErrorCode ret = Interop.CionGroup.CionGroupSubscribe(_handle); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to subscribe."); + } + } + + /// + /// Unsubscribes the topic. + /// + /// 9 + public void Unsubscribe() + { + Interop.Cion.ErrorCode ret = Interop.CionGroup.CionGroupUnsubscribe(_handle); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to unsubscribe."); + } + } + + /// + /// Publishes payload to current group. + /// + /// The payload to publish. + /// Thrown when the payload is invalid. + /// 9 + public void Publish(Payload payload) + { + Interop.Cion.ErrorCode ret = Interop.CionGroup.CionGroupPublish(_handle, payload?._handle); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to publish payload."); + } + } + + /// + /// The callback invoked when payload received. + /// + /// 9 + protected abstract void OnPayloadReceived(Payload payload, PeerInfo peer); + + /// + /// The callback invoked when another peer joined in the current group. + /// + /// The peer info of joined in the current group. + /// 9 + protected abstract void OnJoined(PeerInfo peerInfo); + + /// + /// The callback invoked when another peer left from the current group. + /// + /// The peer info of left from the current group. + /// 9 + protected abstract void OnLeft(PeerInfo peerInfo); + + #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. If false, does not dispose disposable objects. + /// 9 + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + _handle.Dispose(); + } + disposedValue = true; + } + } + + /// + /// Releases all resources used by the GroupBase class. + /// + /// 9 + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + #endregion + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/GroupSafeHandle.cs b/src/Tizen.Applications.Cion/Tizen.Applications/GroupSafeHandle.cs new file mode 100644 index 0000000..7f2aad8 --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/GroupSafeHandle.cs @@ -0,0 +1,43 @@ +/* + * 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.ComponentModel; +using System.Runtime.InteropServices; + +namespace Tizen.Applications +{ + internal sealed class GroupSafeHandle : SafeHandle + { + [EditorBrowsable(EditorBrowsableState.Never)] + public GroupSafeHandle() : base(IntPtr.Zero, true) + { + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool IsInvalid + { + get { return this.DangerousGetHandle() == IntPtr.Zero; } + } + + protected override bool ReleaseHandle() + { + Interop.CionGroup.CionGroupDestroy(this.handle); + SetHandle(IntPtr.Zero); + return true; + } + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/Payload.cs b/src/Tizen.Applications.Cion/Tizen.Applications/Payload.cs new file mode 100644 index 0000000..1e32c61 --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/Payload.cs @@ -0,0 +1,52 @@ +/* + * 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. + */ + +namespace Tizen.Applications +{ + /// + /// An abstract class to represent payload. + /// + /// 9 + public abstract class Payload + { + private readonly string LogTag = "Tizen.Cion"; + internal PayloadSafeHandle _handle; + + /// + /// Gets type of the payload. + /// + /// 9 + public abstract PayloadType PayloadType { get; } + + /// + /// Gets Id of the payload. + /// + /// 9 + public string Id + { + get + { + Interop.Cion.ErrorCode ret = Interop.CionPayload.CionPayloadGetPayloadID(_handle, out string id); + if (ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, "Failed to get id of payload."); + return ""; + } + return id; + } + } + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/PayloadAsyncResult.cs b/src/Tizen.Applications.Cion/Tizen.Applications/PayloadAsyncResult.cs new file mode 100644 index 0000000..855621a --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/PayloadAsyncResult.cs @@ -0,0 +1,111 @@ +/* + * 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; + +namespace Tizen.Applications +{ + /// + /// A class to represent result of payload. + /// + /// 9 + public class PayloadAsyncResult : IDisposable + { + private PayloadAsyncResult(PayloadAsyncResultCode result, PeerInfo peer, string payloadId) + { + Result = result; + PeerInfo = peer; + PayloadId = payloadId; + } + + internal static PayloadAsyncResult CreateFromHandle(IntPtr handle) + { + Interop.Cion.ErrorCode ret = Interop.CionPayloadAsyncResult.CionPayloadAsyncResultGetResult(handle, out int code); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Fail to get result code from the AsyncResult"); + } + + ret = Interop.CionPayloadAsyncResult.CionPayloadAsyncResultGetPayloadID(handle, out string payloadId); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Fail to get payload id from the AsyncResult"); + } + + ret = Interop.CionPayloadAsyncResult.CionPayloadAsyncResultGetPeerInfo(handle, out IntPtr peer); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Fail to get peerinfo from the AsyncResult"); + } + ret = Interop.CionPeerInfo.CionPeerInfoClone(peer, out PeerInfoSafeHandle clone); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to clone peer info."); + } + + return new PayloadAsyncResult((PayloadAsyncResultCode)code, new PeerInfo(clone), payloadId); + } + + /// + /// Gets the result of payload. + /// + /// 9 + public PayloadAsyncResultCode Result { get; } + + /// + /// Gets the peer info of payload. + /// + /// 9 + public PeerInfo PeerInfo { get; } + + /// + /// Gets the payload id. + /// + /// 9 + public string PayloadId { get; } + + #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. If false, does not dispose disposable objects. + /// 9 + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + PeerInfo?.Dispose(); + } + disposedValue = true; + } + } + + /// + /// Releases all resources used by the PayloadAsyncResult class. + /// + /// 9 + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + #endregion + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/PayloadAsyncResultCode.cs b/src/Tizen.Applications.Cion/Tizen.Applications/PayloadAsyncResultCode.cs new file mode 100644 index 0000000..1af27e0 --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/PayloadAsyncResultCode.cs @@ -0,0 +1,42 @@ +/* + * 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. + */ + +namespace Tizen.Applications +{ + /// + /// Enumeration for payload result code. + /// + /// 9 + public enum PayloadAsyncResultCode + { + /// + /// Fail to get the result code. + /// + Error = -1, + /// + /// The async request result is not yet received. + /// + Pending = 0, + /// + /// The async request result is success. + /// + Success, + /// + /// The async request result is fail. + /// + Fail, + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/PayloadSafeHandle.cs b/src/Tizen.Applications.Cion/Tizen.Applications/PayloadSafeHandle.cs new file mode 100755 index 0000000..95d5090 --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/PayloadSafeHandle.cs @@ -0,0 +1,48 @@ +/* + * 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.ComponentModel; +using System.Runtime.InteropServices; + +namespace Tizen.Applications +{ + internal sealed class PayloadSafeHandle : SafeHandle + { + [EditorBrowsable(EditorBrowsableState.Never)] + public PayloadSafeHandle() : base(IntPtr.Zero, true) + { + } + + internal PayloadSafeHandle(IntPtr existingHandle, bool ownsHandle) : base(IntPtr.Zero, ownsHandle) + { + SetHandle(existingHandle); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool IsInvalid + { + get { return this.DangerousGetHandle() == IntPtr.Zero; } + } + + protected override bool ReleaseHandle() + { + Interop.CionPayload.CionPayloadDestroy(this.handle); + SetHandle(IntPtr.Zero); + return true; + } + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/PayloadTransferStatus.cs b/src/Tizen.Applications.Cion/Tizen.Applications/PayloadTransferStatus.cs new file mode 100644 index 0000000..73092d5 --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/PayloadTransferStatus.cs @@ -0,0 +1,38 @@ +/* + * 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. + */ + +namespace Tizen.Applications +{ + /// + /// Enumeration for payload transfer status. + /// + /// 9 + public enum PayloadTransferStatus + { + /// + /// Success. + /// + Success, + /// + /// Failure. + /// + Failure, + /// + /// In Progress. + /// + InProgress, + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/PayloadType.cs b/src/Tizen.Applications.Cion/Tizen.Applications/PayloadType.cs new file mode 100755 index 0000000..ac956d4 --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/PayloadType.cs @@ -0,0 +1,34 @@ +/* + * 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. + */ + +namespace Tizen.Applications +{ + /// + /// Enumeration for payload type. + /// + /// 9 + public enum PayloadType + { + /// + /// Data payload. + /// + DataPayload, + /// + /// File payload. + /// + FilePayload, + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/PeerInfo.cs b/src/Tizen.Applications.Cion/Tizen.Applications/PeerInfo.cs new file mode 100755 index 0000000..f5da1cb --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/PeerInfo.cs @@ -0,0 +1,210 @@ +/* + * 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; + +namespace Tizen.Applications +{ + /// + /// A class to represent peer info. + /// + /// 9 + public class PeerInfo : IDisposable + { + private readonly string LogTag = "Tizen.Cion"; + internal PeerInfoSafeHandle _handle; + + internal PeerInfo(PeerInfoSafeHandle handle) + { + _handle = handle; + } + + /// + /// Gets the device id. + /// + /// 9 + public string DeviceId + { + get + { + Interop.Cion.ErrorCode ret = Interop.CionPeerInfo.CionPeerInfoGetDeviceId(_handle, out string deviceId); + if (ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, "Failed to get device id."); + return ""; + } + return deviceId; + } + } + + /// + /// Gets the device name. + /// + /// 9 + public string DeviceName + { + get + { + Interop.Cion.ErrorCode ret = Interop.CionPeerInfo.CionPeerInfoGetDeviceName(_handle, out string deviceName); + if (ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, "Failed to get device name."); + return ""; + } + return deviceName; + } + } + + /// + /// Gets the device platform. + /// + /// 9 + public string DevicePlatform + { + get + { + Interop.Cion.ErrorCode ret = Interop.CionPeerInfo.CionPeerInfoGetDevicePlatform(_handle, out string devicePlatform); + if (ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, "Failed to get device platform."); + return ""; + } + return devicePlatform; + } + } + + /// + /// Gets the device platform version. + /// + /// 9 + public string DevicePlatformVersion + { + get + { + Interop.Cion.ErrorCode ret = Interop.CionPeerInfo.CionPeerInfoGetDevicePlatformVersion(_handle, out string devicePlatformVersion); + if (ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, "Failed to get device platform version."); + return ""; + } + return devicePlatformVersion; + } + } + + /// + /// Gets the device type. + /// + /// 9 + public string DeviceType + { + get + { + Interop.Cion.ErrorCode ret = Interop.CionPeerInfo.CionPeerInfoGetDeviceType(_handle, out string deviceType); + if (ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, "Failed to get device platform type."); + return ""; + } + return deviceType; + } + } + + /// + /// Gets the application id. + /// + /// 9 + public string AppId + { + get + { + Interop.Cion.ErrorCode ret = Interop.CionPeerInfo.CionPeerInfoGetAppId(_handle, out string AppId); + if (ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, "Failed to get application id."); + return ""; + } + return AppId; + } + } + + /// + /// Gets the application version. + /// + /// 9 + public string AppVersion + { + get + { + Interop.Cion.ErrorCode ret = Interop.CionPeerInfo.CionPeerInfoGetAppVersion(_handle, out string AppVersion); + if (ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, "Failed to get application version."); + return ""; + } + return AppVersion; + } + } + + /// + /// Gets the UUID. + /// + /// 9 + public string UUID + { + get + { + Interop.Cion.ErrorCode ret = Interop.CionPeerInfo.CionPeerInfoGetUuid(_handle, out string uuid); + if (ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, "Failed to get UUID."); + return ""; + } + return uuid; + } + } + + #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. If false, does not dispose disposable objects. + /// 9 + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + _handle.Dispose(); + } + disposedValue = true; + } + } + + /// + /// Releases all resources used by the PeerInfo class. + /// + /// 9 + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + #endregion + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/PeerInfoSafeHandle.cs b/src/Tizen.Applications.Cion/Tizen.Applications/PeerInfoSafeHandle.cs new file mode 100755 index 0000000..c6ef32c --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/PeerInfoSafeHandle.cs @@ -0,0 +1,48 @@ +/* + * 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.ComponentModel; +using System.Runtime.InteropServices; + +namespace Tizen.Applications +{ + internal sealed class PeerInfoSafeHandle : SafeHandle + { + [EditorBrowsable(EditorBrowsableState.Never)] + public PeerInfoSafeHandle() : base(IntPtr.Zero, true) + { + } + + internal PeerInfoSafeHandle(IntPtr existingHandle, bool ownsHandle) : base(IntPtr.Zero, ownsHandle) + { + SetHandle(existingHandle); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool IsInvalid + { + get { return this.DangerousGetHandle() == IntPtr.Zero; } + } + + protected override bool ReleaseHandle() + { + Interop.CionPeerInfo.CionPeerInfoDestroy(this.handle); + SetHandle(IntPtr.Zero); + return true; + } + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/ServerBase.cs b/src/Tizen.Applications.Cion/Tizen.Applications/ServerBase.cs new file mode 100644 index 0000000..88d60c2 --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/ServerBase.cs @@ -0,0 +1,407 @@ +/* + * 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.Collections.Generic; +using System.Threading.Tasks; + +namespace Tizen.Applications +{ + /// + /// An abstract class to represent cion server. + /// + /// 9 + public abstract class ServerBase : IDisposable + { + private const string LogTag = "Tizen.Cion"; + + private readonly ServerSafeHandle _handle; + private Interop.CionServer.CionServerConnectionRequestCb _connectionRequestCb; + private Interop.CionServer.CionServerConnectionResultCb _connectionResultCb; + private Interop.CionServer.CionServerDataReceivedCb _dataReceivedCb; + private Interop.CionServer.CionServerPayloadRecievedCb _payloadRecievedCb; + private Interop.CionServer.CionServerDisconnectedCb _disconnectedCb; + private Interop.CionServer.CionServerPayloadAsyncResultCb _payloadAsyncResultCb; + private Dictionary, TaskCompletionSource> _tcsDictionary = new Dictionary, TaskCompletionSource>(); + + /// + /// Gets the service name of current cion server. + /// + /// 9 + public string ServiceName { get; } + + /// + /// Gets the display name of current cion server. + /// + /// 9 + public string DisplayName { get; } + + /// + /// The constructor of ServerBase class. + /// + /// The name of service. + /// The display name of service. + /// Thrown when there is not enough memory to continue the execution of the method. + /// 9 + public ServerBase(string serviceName, string displayName) : this(serviceName, displayName, null) { } + + /// + /// The constructor of ServerBase class. + /// + /// The name of service. + /// The display name of service. + /// The security configuration. + /// Thrown when there is not enough memory to continue the execution of the method. + /// 9 + public ServerBase(string serviceName, string displayName, Cion.SecurityInfo security) + { + ServiceName = serviceName; + DisplayName = displayName; + + Cion.SecuritySafeHandle handle = security?._handle; + Interop.Cion.ErrorCode ret = Interop.CionServer.CionServerCreate(out _handle, serviceName, displayName, handle?.DangerousGetHandle() ?? IntPtr.Zero); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to create server handle."); + } + + _connectionResultCb = new Interop.CionServer.CionServerConnectionResultCb( + (string service, IntPtr peerInfo, IntPtr result, IntPtr userData) => + { + Interop.Cion.ErrorCode clone_ret = Interop.CionPeerInfo.CionPeerInfoClone(peerInfo, out PeerInfoSafeHandle clone); + if (clone_ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, "Failed to clone peer info."); + return; + } + OnConnectionResult(new PeerInfo(clone), new ConnectionResult(result)); + }); + ret = Interop.CionServer.CionServerAddConnectionResultCb(_handle, _connectionResultCb, IntPtr.Zero); + if (ret != Interop.Cion.ErrorCode.None) + { + _handle.Dispose(); + throw CionErrorFactory.GetException(ret, "Failed to add connection status changed callback."); + } + + _dataReceivedCb = new Interop.CionServer.CionServerDataReceivedCb( + (string service, IntPtr peerInfo, byte[] data, int dataSize, out byte[] returnData, out int returnDataSize, IntPtr userData) => + { + returnData = OnDataReceived(data, new PeerInfo(new PeerInfoSafeHandle(peerInfo, false))); + returnDataSize = returnData.Length; + }); + ret = Interop.CionServer.CionServerSetDataReceivedCb(_handle, _dataReceivedCb, IntPtr.Zero); + if (ret != Interop.Cion.ErrorCode.None) + { + _handle.Dispose(); + throw CionErrorFactory.GetException(ret, "Failed to set data received callback."); + } + + _payloadRecievedCb = new Interop.CionServer.CionServerPayloadRecievedCb( + (string service, IntPtr peerInfo, IntPtr payload, int status, IntPtr userData) => + { + Payload receivedPayload; + Interop.CionPayload.CionPayloadGetType(payload, out Interop.CionPayload.PayloadType type); + switch (type) + { + case Interop.CionPayload.PayloadType.Data: + receivedPayload = new DataPayload(new PayloadSafeHandle(payload, false)); + break; + case Interop.CionPayload.PayloadType.File: + receivedPayload = new FilePayload(new PayloadSafeHandle(payload, false)); + break; + default: + Log.Error(LogTag, "Invalid payload type received."); + return; + } + OnPayloadReceived(receivedPayload, new PeerInfo(new PeerInfoSafeHandle(peerInfo, false)), (PayloadTransferStatus)status); + }); + ret = Interop.CionServer.CionServerAddPayloadReceivedCb(_handle, _payloadRecievedCb, IntPtr.Zero); + if (ret != Interop.Cion.ErrorCode.None) + { + _handle.Dispose(); + throw CionErrorFactory.GetException(ret, "Failed to add payload received callback."); + } + + _disconnectedCb = new Interop.CionServer.CionServerDisconnectedCb( + (string service, IntPtr peerInfo, IntPtr userData) => + { + Interop.Cion.ErrorCode clone_ret = Interop.CionPeerInfo.CionPeerInfoClone(peerInfo, out PeerInfoSafeHandle clone); + if (clone_ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, string.Format("Failed to clone peer info.")); + return; + } + OnDisconnected(new PeerInfo(clone)); + }); + ret = Interop.CionServer.CionServerAddDisconnectedCb(_handle, _disconnectedCb, IntPtr.Zero); + if (ret != Interop.Cion.ErrorCode.None) + { + _handle.Dispose(); + throw CionErrorFactory.GetException(ret, "Failed to add disconnected callback."); + } + } + + /// + /// Starts server and listens for requests from cion clients. + /// + /// Thrown when the listen operation is already in progress. + /// http://tizen.org/privilege/d2d.datasharing + /// 9 + public void Listen() + { + if (_connectionRequestCb == null) + { + Interop.CionServer.CionServerConnectionRequestCb cb = new Interop.CionServer.CionServerConnectionRequestCb( + (serviceName, peerInfo, userData) => + { + Interop.Cion.ErrorCode clone_ret = Interop.CionPeerInfo.CionPeerInfoClone(peerInfo, out PeerInfoSafeHandle clone); + if (clone_ret != Interop.Cion.ErrorCode.None) + { + Log.Error(LogTag, "Failed to clone peer info"); + return; + } + OnConnentionRequest(new PeerInfo(clone)); + }); + _connectionRequestCb = cb; + } + + Interop.Cion.ErrorCode ret = Interop.CionServer.CionServerListen(_handle, _connectionRequestCb, IntPtr.Zero); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to listen server."); + } + } + + /// + /// Stops the listen operation. + /// + /// Thrown when the server is not listening. + /// 9 + public void Stop() + { + Interop.Cion.ErrorCode ret = Interop.CionServer.CionServerStop(_handle); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to stop server."); + } + } + + /// + /// Disconnects with the peer. + /// + /// The peer to disconnect. + /// Thrown when the given peer info is invalid. + /// 9 + public void Disconnect(PeerInfo peerInfo) + { + Interop.Cion.ErrorCode ret = Interop.CionServer.CionServerDisconnect(_handle, peerInfo?._handle); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to stop server."); + } + } + + /// + /// Sends the payload to a peer asynchronously. + /// + /// The payload to send. + /// The peer to send payload. + /// Thrown when the payload is not valid. + /// Thrown when there is no such connected cion client. + /// 9 + public Task SendPayloadAsync(Payload payload, PeerInfo peerInfo) + { + if (payload?.Id.Length == 0 || peerInfo?.UUID.Length == 0) + { + throw new ArgumentException("Payload or peerinfo is invalid."); + } + + TaskCompletionSource tcs = new TaskCompletionSource(); + _tcsDictionary[Tuple.Create(payload.Id, peerInfo.UUID)] = tcs; + + if (_payloadAsyncResultCb == null) + { + Interop.CionServer.CionServerPayloadAsyncResultCb cb = new Interop.CionServer.CionServerPayloadAsyncResultCb( + (IntPtr result, IntPtr userData) => + { + PayloadAsyncResult resultPayload = null; + try + { + resultPayload = PayloadAsyncResult.CreateFromHandle(result); + } + catch (Exception e) + { + Log.Error(LogTag, string.Format("Failed to create PayloadAsyncResult from result handle: {0}.", e.Message)); + return; + } + TaskCompletionSource tcsToReturn = _tcsDictionary[Tuple.Create(resultPayload.PayloadId, resultPayload.PeerInfo.UUID)]; + tcsToReturn.SetResult(resultPayload); + _tcsDictionary.Remove(Tuple.Create(resultPayload.PayloadId, resultPayload.PeerInfo.UUID)); + }); + _payloadAsyncResultCb = cb; + } + + Interop.Cion.ErrorCode ret = Interop.CionServer.CionServerSendPayloadAsync(_handle, peerInfo?._handle, payload?._handle, _payloadAsyncResultCb, IntPtr.Zero); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to send payload."); + } + + return tcs.Task; + } + + /// + /// Sends the payload to all of connected peer asynchronously. + /// + /// The payload to send. + /// 9 + public void SendPayloadAsync(Payload payload) + { + var peerList = GetConnectedPeerList(); + foreach (var peer in peerList) + { + SendPayloadAsync(payload, peer); + } + } + + /// + /// Accepts the connection request from the peer. + /// + /// The peer to accept the connection request. + /// 9 + public void Accept(PeerInfo peerInfo) + { + Interop.CionServer.CionServerAccept(_handle, peerInfo?._handle); + } + + /// + /// Rejects the connection request from the peer. + /// + /// The peer to reject the connection request. + /// The reason why reject the connection request. + /// 9 + public void Reject(PeerInfo peerInfo, string reason) + { + Interop.CionServer.CionServerReject(_handle, peerInfo?._handle, reason); + } + + /// + /// Gets connected peers. + /// + /// Thrown when there is not enough memory to continue the execution of the method. + /// 9 + public IEnumerable GetConnectedPeerList() + { + List peerInfoList = new List(); + Interop.Cion.ErrorCode ret = Interop.CionServer.CionServerForeachConnectedPeerInfo(_handle, (peer, userData) => + { + Interop.Cion.ErrorCode clone_ret = Interop.CionPeerInfo.CionPeerInfoClone(peer, out PeerInfoSafeHandle clone); + if (clone_ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(clone_ret, "Failed to clone peer info."); + } + peerInfoList.Add(new PeerInfo(clone)); + }, IntPtr.Zero); + return peerInfoList; + } + + /// + /// Sets ondemand launch enabled flag. + /// + /// Whether ondemand launch is enabled or not. + /// Thrown when an application does not have the privilege to access this method. + /// http://tizen.org/privilege/d2d.remotelaunch + /// 9 + public void SetOndemandLaunchEnabled(bool enable) + { + Interop.Cion.ErrorCode ret = Interop.CionServer.CionServerSetOndemandLaunchEnable(_handle, enable); + if (ret != Interop.Cion.ErrorCode.None) + { + throw CionErrorFactory.GetException(ret, "Failed to set ondemand launch enable"); + } + } + + /// + /// The result callback of connection request. + /// + /// The peer info of the cion client. + /// The result of the connection. + /// 9 + protected abstract void OnConnectionResult(PeerInfo peerInfo, ConnectionResult result); + + /// + /// The callback invoked when received data. + /// + /// The received data. + /// The peer info of the cion client. + /// 9 + protected abstract byte[] OnDataReceived(byte[] data, PeerInfo peerInfo); + + /// + /// The callback invoked when received payload. + /// + /// The received data. + /// The peer info of the cion client. + /// The status of payload transfer. + /// 9 + protected abstract void OnPayloadReceived(Payload data, PeerInfo peerInfo, PayloadTransferStatus status); + + /// + /// The callback invoked when connection requested from the cion client. + /// + /// The peer info of the cion client. + /// 9 + protected abstract void OnConnentionRequest(PeerInfo peerInfo); + + /// + /// The callback invoked when disconnected with cion client. + /// + /// The peer info of the cion client. + /// 9 + protected abstract void OnDisconnected(PeerInfo peerInfo); + + #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. If false, does not dispose disposable objects. + /// 9 + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + _handle.Dispose(); + } + disposedValue = true; + } + } + + /// + /// Releases all resources used by the ServerBase class. + /// + /// 9 + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + #endregion + } +} diff --git a/src/Tizen.Applications.Cion/Tizen.Applications/ServerSafeHandle.cs b/src/Tizen.Applications.Cion/Tizen.Applications/ServerSafeHandle.cs new file mode 100755 index 0000000..5bd0fed --- /dev/null +++ b/src/Tizen.Applications.Cion/Tizen.Applications/ServerSafeHandle.cs @@ -0,0 +1,43 @@ +/* + * 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.ComponentModel; +using System.Runtime.InteropServices; + +namespace Tizen.Applications +{ + internal sealed class ServerSafeHandle : SafeHandle + { + [EditorBrowsable(EditorBrowsableState.Never)] + public ServerSafeHandle() : base(IntPtr.Zero, true) + { + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool IsInvalid + { + get { return this.DangerousGetHandle() == IntPtr.Zero; } + } + + protected override bool ReleaseHandle() + { + Interop.CionServer.CionServerDestroy(this.handle); + SetHandle(IntPtr.Zero); + return true; + } + } +} -- 2.7.4