[Cion] Add new APIs for Advanced Companion Framework (#3472)
authorjeremy-jang <35089715+jeremy-jang@users.noreply.github.com>
Fri, 10 Sep 2021 05:15:28 +0000 (14:15 +0900)
committerGitHub <noreply@github.com>
Fri, 10 Sep 2021 05:15:28 +0000 (14:15 +0900)
* [Cion] Add new APIs for Advanced Companion Framework

Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
* [Cion] Remove PayloadAsyncResult.Id

This is removed from the design.

Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
* 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 <jeremy.jang@samsung.com>
* Fix Cion

- Fix ClientBase.SendPayloadAsync to return Task
- Fix doxygen comments
- Fix some bad code

Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
* Fix Cion

- Add missing doxygen comments
- Fix some bad code

Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
* Fix ServerBase.SendPayloadAsync

Fix same as ClientBase.

Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
* Fix Cion csproj file

Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
* Fix Cion

- Fix IDisposable code
- Fix bad exception throwing
- Fix SendPayloadAsync
- Fix setting connectied peer of ClientBase

Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
* Add missing public keyword

Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
* Add missing API and fix doxygen comments

Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
* 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 <jeremy.jang@samsung.com>
* Fix PayloadAsyncResultCode.Dispose()

The property PeerInfo is a managed object.

Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
* Fix Cion

- Fix ClientBase.SendData to use Marshal.Copy
- Fix SendPayloadAsync to handle error case
- Fix some bad code

Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
Co-authored-by: pjh9216 <jh9216.park@samsung.com>
33 files changed:
src/Tizen.Applications.Cion/Interop/Interop.Cion.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Interop/Interop.CionClient.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Interop/Interop.CionConnectionResult.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Interop/Interop.CionGroup.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Interop/Interop.CionPayload.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Interop/Interop.CionPayloadAsyncResult.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Interop/Interop.CionPeerInfo.cs [new file with mode: 0755]
src/Tizen.Applications.Cion/Interop/Interop.CionSecurity.cs [new file with mode: 0755]
src/Tizen.Applications.Cion/Interop/Interop.CionServer.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Interop/Interop.Libraries.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Tizen.Applications.Cion.csproj [new file with mode: 0755]
src/Tizen.Applications.Cion/Tizen.Applications.Cion.sln [new file with mode: 0644]
src/Tizen.Applications.Cion/Tizen.Applications/Cion/SecurityInfo.cs [new file with mode: 0755]
src/Tizen.Applications.Cion/Tizen.Applications/Cion/SecuritySafeHandle.cs [new file with mode: 0755]
src/Tizen.Applications.Cion/Tizen.Applications/CionErrorFactory.cs [new file with mode: 0755]
src/Tizen.Applications.Cion/Tizen.Applications/ClientBase.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Tizen.Applications/ClientSafeHandle.cs [new file with mode: 0755]
src/Tizen.Applications.Cion/Tizen.Applications/ConnectionResult.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Tizen.Applications/ConnectionStatus.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Tizen.Applications/DataPayload.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Tizen.Applications/FilePayload.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Tizen.Applications/GroupBase.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Tizen.Applications/GroupSafeHandle.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Tizen.Applications/Payload.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Tizen.Applications/PayloadAsyncResult.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Tizen.Applications/PayloadAsyncResultCode.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Tizen.Applications/PayloadSafeHandle.cs [new file with mode: 0755]
src/Tizen.Applications.Cion/Tizen.Applications/PayloadTransferStatus.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Tizen.Applications/PayloadType.cs [new file with mode: 0755]
src/Tizen.Applications.Cion/Tizen.Applications/PeerInfo.cs [new file with mode: 0755]
src/Tizen.Applications.Cion/Tizen.Applications/PeerInfoSafeHandle.cs [new file with mode: 0755]
src/Tizen.Applications.Cion/Tizen.Applications/ServerBase.cs [new file with mode: 0644]
src/Tizen.Applications.Cion/Tizen.Applications/ServerSafeHandle.cs [new file with mode: 0755]

diff --git a/src/Tizen.Applications.Cion/Interop/Interop.Cion.cs b/src/Tizen.Applications.Cion/Interop/Interop.Cion.cs
new file mode 100644 (file)
index 0000000..cbfa407
--- /dev/null
@@ -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 (file)
index 0000000..584be13
--- /dev/null
@@ -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 (file)
index 0000000..359527c
--- /dev/null
@@ -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 (file)
index 0000000..03cbb65
--- /dev/null
@@ -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 (file)
index 0000000..9d9f87d
--- /dev/null
@@ -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 (file)
index 0000000..8cc12f1
--- /dev/null
@@ -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 (executable)
index 0000000..daa08e9
--- /dev/null
@@ -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 (executable)
index 0000000..e4db7a8
--- /dev/null
@@ -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 (file)
index 0000000..b4eedf4
--- /dev/null
@@ -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 (file)
index 0000000..32af828
--- /dev/null
@@ -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 (executable)
index 0000000..b1f36fa
--- /dev/null
@@ -0,0 +1,13 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>netstandard2.0</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\Tizen\Tizen.csproj" />
+    <ProjectReference Include="..\Tizen.Log\Tizen.Log.csproj" />
+  </ItemGroup>
+
+
+</Project>
diff --git a/src/Tizen.Applications.Cion/Tizen.Applications.Cion.sln b/src/Tizen.Applications.Cion/Tizen.Applications.Cion.sln
new file mode 100644 (file)
index 0000000..26ebd2d
--- /dev/null
@@ -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 (executable)
index 0000000..21a8445
--- /dev/null
@@ -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
+{
+    /// <summary>
+    /// A class to represent security info.
+    /// </summary>
+    /// <since_tizen> 9 </since_tizen>
+    public class SecurityInfo : IDisposable
+    {
+        private readonly string LogTag = "Tizen.Cion";
+        internal SecuritySafeHandle _handle = null;
+
+        /// <summary>
+        /// The constructor of SecurityInfo class.
+        /// </summary>
+        /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method.</exception> 
+        /// <since_tizen> 9 </since_tizen>
+        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.");
+            }
+        }
+
+        /// <summary>
+        /// Gets the CA cert path.
+        /// </summary>
+        /// <exception cref="ArgumentException">Thrown when the CA path is invalid.</exception>
+        /// <since_tizen> 9 </since_tizen>
+        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.");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the cert path.
+        /// </summary>
+        /// <exception cref="ArgumentException">Thrown when the cert path is invalid.</exception>
+        /// <since_tizen> 9 </since_tizen>
+        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.");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the private key path.
+        /// </summary>
+        /// <exception cref="ArgumentException">Thrown when the private key path is invalid.</exception>
+        /// <since_tizen> 9 </since_tizen>
+        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;
+
+        /// <summary>
+        /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects.
+        /// </summary>
+        /// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param>
+        /// <since_tizen> 9 </since_tizen>
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!disposedValue)
+            {
+                if (disposing)
+                {
+                    _handle.Dispose();
+                }
+                disposedValue = true;
+            }
+        }
+
+        /// <summary>
+        /// Releases all resources used by the SecurityInfo class.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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 (executable)
index 0000000..2f96bf9
--- /dev/null
@@ -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 (executable)
index 0000000..48e54e8
--- /dev/null
@@ -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 (file)
index 0000000..3c913cd
--- /dev/null
@@ -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
+{
+    /// <summary>
+    /// An abstract class to represent cion client.
+    /// </summary>
+    /// <since_tizen> 9 </since_tizen>
+    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<string, TaskCompletionSource<PayloadAsyncResult>> _tcsDictionary = new Dictionary<string, TaskCompletionSource<PayloadAsyncResult>>();
+
+        /// <summary>
+        /// Gets the service name of current cion client.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        public string ServiceName { get; }
+
+        /// <summary>
+        /// Gets peer info of connected cion server.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        public PeerInfo PeerInfo
+        {
+            get
+            {
+                return _peer;
+            }
+        }
+
+        /// <summary>
+        /// The constructor of ClientBase class.
+        /// </summary>
+        /// <param name="serviceName">The name of service.</param>
+        /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method.</exception> 
+        /// <since_tizen> 9 </since_tizen>
+        public ClientBase(string serviceName) : this(serviceName, null) { }
+
+        /// <summary>
+        /// The constructor of ClientBase class.
+        /// </summary>
+        /// <param name="serviceName">The name of service.</param>
+        /// <param name="security">The security configuration.</param>
+        /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method.</exception> 
+        /// <since_tizen> 9 </since_tizen>
+        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.");
+            }
+        }
+
+        /// <summary>
+        /// Starts discovering cion servers.
+        /// </summary>
+        /// <exception cref="InvalidOperationException">Thrown when the discovery operation is already in progress.</exception>
+        /// <since_tizen> 9 </since_tizen>
+        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.");
+            }
+        }
+
+        /// <summary>
+        /// Stops discovering.
+        /// </summary>
+        /// <exception cref="InvalidOperationException">Thrown when the client is not discovering.</exception>
+        /// <since_tizen> 9 </since_tizen>
+        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.");
+            }
+        }
+
+        /// <summary>
+        /// Connects with the cion server.
+        /// </summary>
+        /// <param name="peer">The peer to connect.</param>
+        /// <privilege>http://tizen.org/privilege/d2d.datasharing</privilege>
+        /// <since_tizen> 9 </since_tizen>
+        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.");
+            }
+        }
+
+        /// <summary>
+        /// Disconnects from the cion server.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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;
+        }
+
+        /// <summary>
+        /// Sends data synchronously to the connected cion server.
+        /// </summary>
+        /// <param name="data">The data to send.</param>
+        /// <param name="timeout">The timeout of sending operation.</param>
+        /// <exception cref="ArgumentException">Thrown when the given data is invalid.</exception>
+        /// <exception cref="InvalidOperationException">Thrown when there is no connected cion server.</exception>
+        /// <since_tizen> 9 </since_tizen>
+        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;
+        }
+
+        /// <summary>
+        /// Sends payload asynchronously to the connected cion server.
+        /// </summary>
+        /// <param name="payload">The payload to send.</param>
+        /// <exception cref="ArgumentException">Thrown when the payload is not valid.</exception>
+        /// <exception cref="InvalidOperationException">Thrown when there is no connected cion server.</exception>
+        /// <since_tizen> 9 </since_tizen>
+        public Task<PayloadAsyncResult> SendPayloadAsync(Payload payload)
+        {
+            if (payload?.Id.Length == 0)
+            {
+                throw new ArgumentException("Payload is invalid.");
+            }
+
+            TaskCompletionSource<PayloadAsyncResult> tcs = new TaskCompletionSource<PayloadAsyncResult>();
+            _tcsDictionary[payload.Id] = tcs;
+
+            if (_payloadAsyncResultCb == null)
+            {
+                Interop.CionClient.CionClientPayloadAsyncResultCb cb = new Interop.CionClient.CionClientPayloadAsyncResultCb(
+                    (IntPtr result, IntPtr userData) =>
+                    {
+                        TaskCompletionSource<PayloadAsyncResult> 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;
+        }
+
+        /// <summary>
+        /// The result callback of connection request.
+        /// </summary>
+        /// <param name="peerInfo">The peer info of the cion server.</param>
+        /// <param name="result">The result of the connection.</param>
+        /// <since_tizen> 9 </since_tizen>
+        protected abstract void OnConnectionResult(PeerInfo peerInfo, ConnectionResult result);
+
+        /// <summary>
+        /// The callback invoked when received payload.
+        /// </summary>
+        /// <param name="payload">The received payload.</param>
+        /// <param name="status">The status of sent payload.</param>
+        /// <since_tizen> 9 </since_tizen>
+        protected abstract void OnPayloadReceived(Payload payload, PayloadTransferStatus status);
+
+        /// <summary>
+        /// The callback invoked when the cion server discovered.
+        /// </summary>
+        /// <param name="peerInfo">The peer info of discovered cion server.</param>
+        /// <since_tizen> 9 </since_tizen>
+        protected abstract void OnDiscovered(PeerInfo peerInfo);
+
+        /// <summary>
+        /// The callback invoked when disconnected with cion client.
+        /// </summary>
+        /// <param name="peerInfo">The peer info of the cion server.</param>
+        /// <since_tizen> 9 </since_tizen>
+        protected abstract void OnDisconnected(PeerInfo peerInfo);
+
+        #region IDisposable Support
+        private bool disposedValue = false;
+
+        /// <summary>
+        /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects.
+        /// </summary>
+        /// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param>
+        /// <since_tizen> 9 </since_tizen>
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!disposedValue)
+            {
+                if (disposing)
+                {
+                    _handle.Dispose();
+                }
+                disposedValue = true;
+            }
+        }
+
+        /// <summary>
+        /// Releases all resources used by the ClientBase class.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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 (executable)
index 0000000..72a03d2
--- /dev/null
@@ -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 (file)
index 0000000..3d04128
--- /dev/null
@@ -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
+{
+    /// <summary>
+    /// A class to represent result of connection.
+    /// </summary>
+    /// <since_tizen> 9 </since_tizen>
+    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);
+        }
+
+        /// <summary>
+        /// Gets the connection status.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        public ConnectionStatus Status
+        {
+            get
+            {
+                return _status;
+            }
+        }
+
+        /// <summary>
+        /// Gets the reason of the connection result.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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 (file)
index 0000000..198315d
--- /dev/null
@@ -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
+{
+    /// <summary>
+    /// Enumeration for connection status.
+    /// </summary>
+    /// <since_tizen> 9 </since_tizen>
+    public enum ConnectionStatus
+    {
+        /// <summary>
+        /// The connection request is accepted.
+        /// </summary>
+        OK,
+        /// <summary>
+        /// The connection request is rejected.
+        /// </summary>
+        Rejected,
+        /// <summary>
+        /// The error occurred while the connection request is in-progress.
+        /// </summary>
+        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 (file)
index 0000000..3d47ba1
--- /dev/null
@@ -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
+{
+    /// <summary>
+    /// A class to represent data type payload.
+    /// </summary>
+    /// <since_tizen> 9 </since_tizen>
+    public class DataPayload : Payload
+    {
+        internal DataPayload(PayloadSafeHandle handle)
+        {
+            _handle = handle;
+        }
+
+        /// <summary>
+        /// The constructor of DataPayload class.
+        /// </summary>
+        /// <param name="data">The data of payload.</param>
+        /// <exception cref="ArgumentException">Thrown when the input data is invalid.</exception>
+        /// <since_tizen> 9 </since_tizen>
+        public DataPayload(byte[] data)
+        {
+            Interop.CionPayload.CionPayloadCreate(out _handle, Interop.CionPayload.PayloadType.Data);
+            Interop.CionPayload.CionPayloadSetData(_handle, data, data?.Length ?? -1);
+        }
+
+        /// <summary>
+        /// Gets type of the payload.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        public override PayloadType PayloadType
+        {
+            get
+            {
+                return PayloadType.DataPayload;
+            }
+        }
+
+        /// <summary>
+        /// Gets data of the payload.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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 (file)
index 0000000..0861961
--- /dev/null
@@ -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
+{
+    /// <summary>
+    /// A class to represent file type payload.
+    /// </summary>
+    /// <since_tizen> 9 </since_tizen>
+    public class FilePayload : Payload
+    {
+        private readonly string LogTag = "Tizen.Cion";
+
+        internal FilePayload(PayloadSafeHandle handle)
+        {
+            _handle = handle;
+        }
+
+        /// <summary>
+        /// The constructor of FilePayload class.
+        /// </summary>
+        /// <param name="path">The path of file for the FilePayload.</param>
+        /// <exception cref="ArgumentException">Thrown when the input file path is invalid.</exception>
+        /// <since_tizen> 9 </since_tizen>
+        public FilePayload(string path)
+        {
+            Interop.CionPayload.CionPayloadCreate(out _handle, Interop.CionPayload.PayloadType.File);
+            Interop.CionPayload.CionPayloadSetFilePath(_handle, path);
+        }
+
+        /// <summary>
+        /// Gets the name of received file.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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;
+            }
+        }
+
+        /// <summary>
+        /// Gets size of received file.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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;
+            }
+        }
+
+        /// <summary>
+        /// Gets total size of the file.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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;
+            }
+        }
+
+        /// <summary>
+        /// Gets type of the payload.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        public override PayloadType PayloadType
+        {
+            get
+            {
+                return PayloadType.FilePayload;
+            }
+        }
+
+        /// <summary>
+        /// Saves file of payload to speicific path.
+        /// </summary>
+        /// <param name="path">The path of file to save.</param>
+        /// <since_tizen> 9 </since_tizen>
+        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 (file)
index 0000000..1038537
--- /dev/null
@@ -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
+{
+    /// <summary>
+    /// An abstract class to represent cion group.
+    /// </summary>
+    /// <since_tizen> 9 </since_tizen>
+    public abstract class GroupBase : IDisposable
+    {
+        private readonly GroupSafeHandle _handle;
+
+        private Interop.CionGroup.CionGroupPayloadReceivedCb _payloadReceivedCb;
+        private Interop.CionGroup.CionGroupLeftCb _leftCb;
+        private Interop.CionGroup.CionGroupJoinedCb _joinedCb;
+
+        /// <summary>
+        /// Gets the topic of current cion group.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        public string Topic { get; }
+
+        /// <summary>
+        /// The constructor of GroupBase class.
+        /// </summary>
+        /// <param name="topicName">The topic of group.</param>
+        /// <since_tizen> 9 </since_tizen>
+        public GroupBase(string topicName) : this(topicName, null) { }
+
+        /// <summary>
+        /// The constructor of GroupBase class.
+        /// </summary>
+        /// <param name="topicName">The topic of group.</param>
+        /// <param name="security">The security configuration.</param>
+        /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method.</exception>
+        /// <since_tizen> 9 </since_tizen>
+        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.");
+            }
+        }
+
+        /// <summary>
+        /// Subscribes the topic.
+        /// </summary>
+        /// <privilege>http://tizen.org/privilege/d2d.datasharing</privilege>
+        /// <since_tizen> 9 </since_tizen>
+        public void Subscribe()
+        {
+            Interop.Cion.ErrorCode ret = Interop.CionGroup.CionGroupSubscribe(_handle);
+            if (ret != Interop.Cion.ErrorCode.None)
+            {
+                throw CionErrorFactory.GetException(ret, "Failed to subscribe.");
+            }
+        }
+
+        /// <summary>
+        /// Unsubscribes the topic.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        public void Unsubscribe()
+        {
+            Interop.Cion.ErrorCode ret = Interop.CionGroup.CionGroupUnsubscribe(_handle);
+            if (ret != Interop.Cion.ErrorCode.None)
+            {
+                throw CionErrorFactory.GetException(ret, "Failed to unsubscribe.");
+            }
+        }
+
+        /// <summary>
+        /// Publishes payload to current group.
+        /// </summary>
+        /// <param name="payload">The payload to publish.</param>
+        /// <exception cref="ArgumentException">Thrown when the payload is invalid.</exception>
+        /// <since_tizen> 9 </since_tizen>
+        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.");
+            }
+        }
+
+        /// <summary>
+        /// The callback invoked when payload received.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        protected abstract void OnPayloadReceived(Payload payload, PeerInfo peer);
+
+        /// <summary>
+        /// The callback invoked when another peer joined in the current group.
+        /// </summary>
+        /// <param name="peerInfo">The peer info of joined in the current group.</param>
+        /// <since_tizen> 9 </since_tizen>
+        protected abstract void OnJoined(PeerInfo peerInfo);
+
+        /// <summary>
+        /// The callback invoked when another peer left from the current group.
+        /// </summary>
+        /// <param name="peerInfo">The peer info of left from the current group.</param>
+        /// <since_tizen> 9 </since_tizen>
+        protected abstract void OnLeft(PeerInfo peerInfo);
+
+        #region IDisposable Support
+        private bool disposedValue = false;
+
+        /// <summary>
+        /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects.
+        /// </summary>
+        /// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param>
+        /// <since_tizen> 9 </since_tizen>
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!disposedValue)
+            {
+                if (disposing)
+                {
+                    _handle.Dispose();
+                }
+                disposedValue = true;
+            }
+        }
+
+        /// <summary>
+        /// Releases all resources used by the GroupBase class.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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 (file)
index 0000000..7f2aad8
--- /dev/null
@@ -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 (file)
index 0000000..1e32c61
--- /dev/null
@@ -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
+{
+    /// <summary>
+    /// An abstract class to represent payload.
+    /// </summary>
+    /// <since_tizen> 9 </since_tizen>
+    public abstract class Payload
+    {
+        private readonly string LogTag = "Tizen.Cion";
+        internal PayloadSafeHandle _handle;
+
+        /// <summary>
+        /// Gets type of the payload.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        public abstract PayloadType PayloadType { get; }
+
+        /// <summary>
+        /// Gets Id of the payload.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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 (file)
index 0000000..855621a
--- /dev/null
@@ -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
+{
+    /// <summary>
+    /// A class to represent result of payload.
+    /// </summary>
+    /// <since_tizen> 9 </since_tizen>
+    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);
+        }
+
+        /// <summary>
+        /// Gets the result of payload.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        public PayloadAsyncResultCode Result { get; }
+
+        /// <summary>
+        /// Gets the peer info of payload.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        public PeerInfo PeerInfo { get; }
+
+        /// <summary>
+        /// Gets the payload id.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        public string PayloadId { get; }
+
+        #region IDisposable Support
+        private bool disposedValue = false;
+
+        /// <summary>
+        /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects.
+        /// </summary>
+        /// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param>
+        /// <since_tizen> 9 </since_tizen>
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!disposedValue)
+            {
+                if (disposing)
+                {
+                    PeerInfo?.Dispose();
+                }
+                disposedValue = true;
+            }
+        }
+
+        /// <summary>
+        /// Releases all resources used by the PayloadAsyncResult class.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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 (file)
index 0000000..1af27e0
--- /dev/null
@@ -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
+{
+    /// <summary>
+    /// Enumeration for payload result code.
+    /// </summary>
+    /// <since_tizen> 9 </since_tizen>
+    public enum PayloadAsyncResultCode
+    {
+        /// <summary>
+        /// Fail to get the result code.
+        /// </summary>
+        Error = -1,
+        /// <summary>
+        /// The async request result is not yet received.
+        /// </summary>
+        Pending = 0,
+        /// <summary>
+        /// The async request result is success.
+        /// </summary>
+        Success,
+        /// <summary>
+        /// The async request result is fail.
+        /// </summary>
+        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 (executable)
index 0000000..95d5090
--- /dev/null
@@ -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 (file)
index 0000000..73092d5
--- /dev/null
@@ -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
+{
+    /// <summary>
+    /// Enumeration for payload transfer status.
+    /// </summary>
+    /// <since_tizen> 9 </since_tizen>
+    public enum PayloadTransferStatus
+    {
+        /// <summary>
+        /// Success.
+        /// </summary>
+        Success,
+        /// <summary>
+        /// Failure.
+        /// </summary>
+        Failure,
+        /// <summary>
+        /// In Progress.
+        /// </summary>
+        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 (executable)
index 0000000..ac956d4
--- /dev/null
@@ -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
+{
+    /// <summary>
+    /// Enumeration for payload type.
+    /// </summary>
+    /// <since_tizen> 9 </since_tizen>
+    public enum PayloadType
+    {
+        /// <summary>
+        /// Data payload.
+        /// </summary>
+        DataPayload,
+        /// <summary>
+        /// File payload.
+        /// </summary>
+        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 (executable)
index 0000000..f5da1cb
--- /dev/null
@@ -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
+{
+    /// <summary>
+    /// A class to represent peer info.
+    /// </summary>
+    /// <since_tizen> 9 </since_tizen>
+    public class PeerInfo : IDisposable
+    {
+        private readonly string LogTag = "Tizen.Cion";
+        internal PeerInfoSafeHandle _handle;
+
+        internal PeerInfo(PeerInfoSafeHandle handle)
+        {
+            _handle = handle;
+        }
+
+        /// <summary>
+        /// Gets the device id.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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;
+            }
+        }
+
+        /// <summary>
+        /// Gets the device name.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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;
+            }
+        }
+
+        /// <summary>
+        /// Gets the device platform.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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;
+            }
+        }
+
+        /// <summary>
+        /// Gets the device platform version.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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;
+            }
+        }
+
+        /// <summary>
+        /// Gets the device type.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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;
+            }
+        }
+
+        /// <summary>
+        /// Gets the application id.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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;
+            }
+        }
+
+        /// <summary>
+        /// Gets the application version.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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;
+            }
+        }
+
+        /// <summary>
+        /// Gets the UUID.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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;
+
+        /// <summary>
+        /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects.
+        /// </summary>
+        /// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param>
+        /// <since_tizen> 9 </since_tizen>
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!disposedValue)
+            {
+                if (disposing)
+                {
+                    _handle.Dispose();
+                }
+                disposedValue = true;
+            }
+        }
+
+        /// <summary>
+        /// Releases all resources used by the PeerInfo class.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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 (executable)
index 0000000..c6ef32c
--- /dev/null
@@ -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 (file)
index 0000000..88d60c2
--- /dev/null
@@ -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
+{
+    /// <summary>
+    /// An abstract class to represent cion server.
+    /// </summary>
+    /// <since_tizen> 9 </since_tizen>
+    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<Tuple<string, string>, TaskCompletionSource<PayloadAsyncResult>> _tcsDictionary = new Dictionary<Tuple<string, string>, TaskCompletionSource<PayloadAsyncResult>>();
+
+        /// <summary>
+        /// Gets the service name of current cion server.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        public string ServiceName { get; }
+
+        /// <summary>
+        /// Gets the display name of current cion server.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        public string DisplayName { get; }
+
+        /// <summary>
+        /// The constructor of ServerBase class.
+        /// </summary>
+        /// <param name="serviceName">The name of service.</param>
+        /// <param name="displayName">The display name of service.</param>
+        /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method.</exception> 
+        /// <since_tizen> 9 </since_tizen>
+        public ServerBase(string serviceName, string displayName) : this(serviceName, displayName, null) { }
+
+        /// <summary>
+        /// The constructor of ServerBase class.
+        /// </summary>
+        /// <param name="serviceName">The name of service.</param>
+        /// <param name="displayName">The display name of service.</param>
+        /// <param name="security">The security configuration.</param>
+        /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method.</exception>
+        /// <since_tizen> 9 </since_tizen>
+        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.");
+            }
+        }
+
+        /// <summary>
+        /// Starts server and listens for requests from cion clients.
+        /// </summary>
+        /// <exception cref="InvalidOperationException">Thrown when the listen operation is already in progress.</exception>
+        /// <privilege>http://tizen.org/privilege/d2d.datasharing</privilege>
+        /// <since_tizen> 9 </since_tizen>
+        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.");
+            }
+        }
+
+        /// <summary>
+        /// Stops the listen operation.
+        /// </summary>
+        /// <exception cref="InvalidOperationException">Thrown when the server is not listening.</exception>
+        /// <since_tizen> 9 </since_tizen>
+        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.");
+            }
+        }
+
+        /// <summary>
+        /// Disconnects with the peer.
+        /// </summary>
+        /// <param name="peerInfo">The peer to disconnect.</param>
+        /// <exception cref="ArgumentException">Thrown when the given peer info is invalid.</exception>
+        /// <since_tizen> 9 </since_tizen>
+        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.");
+            }
+        }
+
+        /// <summary>
+        /// Sends the payload to a peer asynchronously.
+        /// </summary>
+        /// <param name="payload">The payload to send.</param>
+        /// <param name="peerInfo">The peer to send payload.</param>
+        /// <exception cref="ArgumentException">Thrown when the payload is not valid.</exception>
+        /// <exception cref="InvalidOperationException">Thrown when there is no such connected cion client.</exception>
+        /// <since_tizen> 9 </since_tizen>
+        public Task<PayloadAsyncResult> SendPayloadAsync(Payload payload, PeerInfo peerInfo)
+        {
+            if (payload?.Id.Length == 0 || peerInfo?.UUID.Length == 0)
+            {
+                throw new ArgumentException("Payload or peerinfo is invalid.");
+            }
+
+            TaskCompletionSource<PayloadAsyncResult> tcs = new TaskCompletionSource<PayloadAsyncResult>();
+            _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<PayloadAsyncResult> 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;
+        }
+
+        /// <summary>
+        /// Sends the payload to all of connected peer asynchronously.
+        /// </summary>
+        /// <param name="payload">The payload to send.</param>
+        /// <since_tizen> 9 </since_tizen>
+        public void SendPayloadAsync(Payload payload)
+        {
+            var peerList = GetConnectedPeerList();
+            foreach (var peer in peerList)
+            {
+                SendPayloadAsync(payload, peer);
+            }
+        }
+
+        /// <summary>
+        /// Accepts the connection request from the peer.
+        /// </summary>
+        /// <param name="peerInfo">The peer to accept the connection request.</param>
+        /// <since_tizen> 9 </since_tizen>
+        public void Accept(PeerInfo peerInfo)
+        {
+            Interop.CionServer.CionServerAccept(_handle, peerInfo?._handle);
+        }
+
+        /// <summary>
+        /// Rejects the connection request from the peer.
+        /// </summary>
+        /// <param name="peerInfo">The peer to reject the connection request.</param>
+        /// <param name="reason">The reason why reject the connection request.</param>
+        /// <since_tizen> 9 </since_tizen>
+        public void Reject(PeerInfo peerInfo, string reason)
+        {
+            Interop.CionServer.CionServerReject(_handle, peerInfo?._handle, reason);
+        }
+
+        /// <summary>
+        /// Gets connected peers.
+        /// </summary>
+        /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method.</exception> 
+        /// <since_tizen> 9 </since_tizen>
+        public IEnumerable<PeerInfo> GetConnectedPeerList()
+        {
+            List<PeerInfo> peerInfoList = new List<PeerInfo>();
+            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;
+        }
+
+        /// <summary>
+        /// Sets ondemand launch enabled flag.
+        /// </summary>
+        /// <param name="enable">Whether ondemand launch is enabled or not.</param>
+        /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
+        /// <privilege>http://tizen.org/privilege/d2d.remotelaunch</privilege>
+        /// <since_tizen> 9 </since_tizen>
+        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");
+            }
+        }
+
+        /// <summary>
+        /// The result callback of connection request.
+        /// </summary>
+        /// <param name="peerInfo">The peer info of the cion client.</param>
+        /// <param name="result">The result of the connection.</param>
+        /// <since_tizen> 9 </since_tizen>
+        protected abstract void OnConnectionResult(PeerInfo peerInfo, ConnectionResult result);
+
+        /// <summary>
+        /// The callback invoked when received data.
+        /// </summary>
+        /// <param name="data">The received data.</param>
+        /// <param name="peerInfo">The peer info of the cion client.</param>
+        /// <since_tizen> 9 </since_tizen>
+        protected abstract byte[] OnDataReceived(byte[] data, PeerInfo peerInfo);
+
+        /// <summary>
+        /// The callback invoked when received payload.
+        /// </summary>
+        /// <param name="data">The received data.</param>
+        /// <param name="peerInfo">The peer info of the cion client.</param>
+        /// <param name="status">The status of payload transfer.</param>
+        /// <since_tizen> 9 </since_tizen>
+        protected abstract void OnPayloadReceived(Payload data, PeerInfo peerInfo, PayloadTransferStatus status);
+
+        /// <summary>
+        /// The callback invoked when connection requested from the cion client.
+        /// </summary>
+        /// <param name="peerInfo">The peer info of the cion client.</param>
+        /// <since_tizen> 9 </since_tizen>
+        protected abstract void OnConnentionRequest(PeerInfo peerInfo);
+
+        /// <summary>
+        /// The callback invoked when disconnected with cion client.
+        /// </summary>
+        /// <param name="peerInfo">The peer info of the cion client.</param>
+        /// <since_tizen> 9 </since_tizen>
+        protected abstract void OnDisconnected(PeerInfo peerInfo);
+
+        #region IDisposable Support
+        private bool disposedValue = false;
+
+        /// <summary>
+        /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects.
+        /// </summary>
+        /// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param>
+        /// <since_tizen> 9 </since_tizen>
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!disposedValue)
+            {
+                if (disposing)
+                {
+                    _handle.Dispose();
+                }
+                disposedValue = true;
+            }
+        }
+
+        /// <summary>
+        /// Releases all resources used by the ServerBase class.
+        /// </summary>
+        /// <since_tizen> 9 </since_tizen>
+        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 (executable)
index 0000000..5bd0fed
--- /dev/null
@@ -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;
+        }
+    }
+}