[MessagePort] Modify MessagePort, modify Bundle's handle
authorSeunghyun Choi <sh4682.choi@samsung.com>
Mon, 14 Mar 2016 05:05:56 +0000 (14:05 +0900)
committerSeunghyun Choi <sh4682.choi@samsung.com>
Mon, 28 Mar 2016 05:35:25 +0000 (14:35 +0900)
Signed-off-by: Seunghyun Choi <sh4682.choi@samsung.com>
Change-Id: I390271d30a98baf71d395bf0ab840e020eb163e3

Tizen.Applications/Interop/Interop.MessagePort.cs [new file with mode: 0644]
Tizen.Applications/Tizen.Applications.MessagePort/MessagePort.cs [new file with mode: 0644]
Tizen.Applications/Tizen.Applications.MessagePort/MessageReceivedEventArgs.cs [new file with mode: 0644]
Tizen.Applications/Tizen.Applications.MessagePort/RemoteValues.cs [new file with mode: 0644]

diff --git a/Tizen.Applications/Interop/Interop.MessagePort.cs b/Tizen.Applications/Interop/Interop.MessagePort.cs
new file mode 100644 (file)
index 0000000..44af04d
--- /dev/null
@@ -0,0 +1,29 @@
+using System;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+    internal static partial class MessagePort
+    {
+        [DllImport(Libraries.MessagePort, EntryPoint = "message_port_register_local_port", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int RegisterPort(string local_port, message_port_message_cb callback, IntPtr userData);
+
+        [DllImport(Libraries.MessagePort, EntryPoint = "message_port_register_trusted_local_port", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int RegisterTrustedPort(string trusted_local_port, message_port_message_cb callback, IntPtr userData);
+
+        [DllImport(Libraries.MessagePort, EntryPoint = "message_port_unregister_local_port", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int UnregisterPort(int local_port_id);
+
+        [DllImport(Libraries.MessagePort, EntryPoint = "message_port_unregister_trusted_local_port", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int UnregisterTrustedPort(int trusted_local_port_id);
+
+        [DllImport(Libraries.MessagePort, EntryPoint = "message_port_send_message_with_local_port", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int SendMessageWithLocalPort(string remote_app_id, string remote_port, IntPtr message, int local_port_id);
+
+        [DllImport(Libraries.MessagePort, EntryPoint = "message_port_send_message_with_local_port", CallingConvention = CallingConvention.Cdecl)]
+        internal static extern int SendTrustedMessageWithLocalPort(string remote_app_id, string remote_port, IntPtr message, int local_port_id);
+
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        internal delegate void message_port_message_cb(int local_port_id, string remote_app_id, string remote_port, bool trusted_remote_port, IntPtr message, IntPtr userData);
+    }
+}
\ No newline at end of file
diff --git a/Tizen.Applications/Tizen.Applications.MessagePort/MessagePort.cs b/Tizen.Applications/Tizen.Applications.MessagePort/MessagePort.cs
new file mode 100644 (file)
index 0000000..81fb6d3
--- /dev/null
@@ -0,0 +1,286 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Tizen.Internals;
+
+namespace Tizen.Applications.MessagePort
+{
+    /// <summary>
+    /// The Message Port API provides functions to send and receive messages between applications.
+    /// </summary>
+    /// <remarks>
+    /// The Message Port API provides functions for passing messages between applications. An application should register its own local port to receive messages from remote applications.
+    /// If a remote application sends a message, the registered callback function of the local port is called.
+    /// The trusted message-port API allows communications between applications that are signed by the same developer(author) certificate.
+    /// </remarks>
+    public class MessagePort
+    {
+        private static Dictionary<MessagePort, int> s_portMap = new Dictionary<MessagePort, int>();
+
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="portName">The name of the local message port</param>
+        /// <param name="trusted">If true is the trusted message port of application, otherwise false</param>
+        public MessagePort(string portName, bool trusted)
+        {
+            _portName = portName;
+            _trusted = trusted;
+        }
+
+        ~MessagePort()
+        {
+            if (_listening)
+            {
+                StopListening();
+            }
+        }
+
+        /// <summary>
+        /// Called when a message is received.
+        /// </summary>
+        public event EventHandler<MessageReceivedEventArgs> MessageReceived;
+
+        private enum MessagePortError
+        {
+            None = Internals.Errors.ErrorCode.None,
+            IOError = Internals.Errors.ErrorCode.IoError,
+            OutOfMemory = Internals.Errors.ErrorCode.OutOfMemory,
+            InvalidParameter = Internals.Errors.ErrorCode.InvalidParameter,
+            PortNotFound = -0x01130000 | 0x01,
+            CertificateNotMatch = -0x01130000 | 0x02,
+            MaxExceeded = -0x01130000 | 0x03,
+            ResourceUnavailable = -0x01130000 | 0x04
+        }
+
+        /// <summary>
+        /// The name of the local message port
+        /// </summary>
+        public string PortName
+        {
+            get
+            {
+                return _portName;
+            }
+        }
+        /// <summary>
+        /// If true the message port is a trusted port, otherwise false it is not
+        /// </summary>
+        public bool Trusted
+        {
+            get
+            {
+                return _trusted;
+            }
+        }
+
+        /// <summary>
+        /// If true the message port is listening, otherwise false it is not
+        /// </summary>
+        public bool Listening
+        {
+            get
+            {
+                return _listening;
+            }
+        }
+
+        /// <summary>
+        /// The local message port ID
+        /// </summary>
+        private int _portId = 0;
+
+        /// <summary>
+        /// The name of the local message port
+        /// </summary>
+        private string _portName = null;
+
+        /// <summary>
+        /// If true the message port is a trusted port, otherwise false it is not
+        /// </summary>
+        private bool _trusted = false;
+
+        /// <summary>
+        /// If true the message port is listening, otherwise false it is not
+        /// </summary>
+        private bool _listening = false;
+
+        private Interop.MessagePort.message_port_message_cb _messageCallBack;
+
+        /// <summary>
+        /// Register the local message port.
+        /// </summary>
+        public void Listen()
+        {
+            if (!s_portMap.ContainsKey(this))
+            {
+                _messageCallBack = (int localPortId, string remoteAppId, string remotePortName, bool trusted, IntPtr message, IntPtr userData) =>
+                {
+                    Bundle bundle = new Bundle(message);
+                    MessageReceivedEventArgs args;
+
+                    if (remotePortName != null)
+                    {
+                        args = new MessageReceivedEventArgs(bundle, remoteAppId, remotePortName, trusted);
+                    }
+                    else
+                    {
+                        args = new MessageReceivedEventArgs(bundle);
+                    }
+
+                    RaiseMessageReceivedEvent(MessageReceived, args);
+                };
+
+                if (_trusted)
+                {
+                    _portId = Interop.MessagePort.RegisterTrustedPort(_portName, _messageCallBack, IntPtr.Zero);
+                }
+                else
+                {
+                    _portId = Interop.MessagePort.RegisterPort(_portName, _messageCallBack, IntPtr.Zero);
+                }
+
+                if(_portId > 0)
+                {
+                    s_portMap.Add(this, 1);
+                    _listening = true;
+                }
+                else
+                {
+                    switch ((MessagePortError)_portId)
+                    {
+                        case MessagePortError.IOError: throw new IOException("I/O Error");
+                        case MessagePortError.OutOfMemory: throw new InvalidOperationException("Out of memory");
+                        case MessagePortError.InvalidParameter: throw new ArgumentException("Invalid parameter");
+                    }
+                }
+            }
+            else
+            {
+                throw new ArgumentException("Already listening");
+            }
+        }
+
+        /// <summary>
+        /// Unregisters the local message port.
+        /// </summary>
+        public void StopListening()
+        {
+            if (_listening)
+            {
+                int ret;
+                if (_trusted)
+                {
+                    ret = Interop.MessagePort.UnregisterTrustedPort(_portId);
+                }
+                else
+                {
+                    ret = Interop.MessagePort.UnregisterPort(_portId);
+                }
+
+                if (ret == 0)
+                {
+                    s_portMap.Remove(this);
+                    _portId = 0;
+                    _listening = false;
+                }
+                else
+                {
+                    switch ((MessagePortError)ret)
+                    {
+                        case MessagePortError.IOError: throw new IOException("I/O Error");
+                        case MessagePortError.OutOfMemory: throw new InvalidOperationException("Out of memory");
+                        case MessagePortError.InvalidParameter: throw new ArgumentException("Invalid parameter");
+                        case MessagePortError.PortNotFound: throw new ArgumentNullException("Port not found");
+                    }
+                }
+            }
+            else
+            {
+                throw new InvalidOperationException("Already stopped");
+            }
+        }
+
+        /// <summary>
+        /// Sends a message to the message port of a remote application.
+        /// </summary>
+        /// <param name="message">The message to be passed to the remote application, the recommended message size is under 4KB</param>
+        /// <param name="remoteAppId">The ID of the remote application</param>
+        /// <param name="remotePortName">The name of the remote message port</param>
+        /// <param name="trusted">If true the trusted message port of remote application otherwise false</param>
+        public void Send(Bundle message, string remoteAppId, string remotePortName, bool trusted=false)
+        {
+            if (_listening)
+            {
+                int ret;
+                if (trusted)
+                {
+                    ret = Interop.MessagePort.SendTrustedMessageWithLocalPort(remoteAppId, remotePortName, message.Handle, _portId);
+                }
+                else
+                {
+                    ret = Interop.MessagePort.SendMessageWithLocalPort(remoteAppId, remotePortName, message.Handle, _portId);
+                }
+                if (ret != 0)
+                {
+                    switch ((MessagePortError)ret)
+                    {
+                        case MessagePortError.IOError: throw new IOException("I/O Error");
+                        case MessagePortError.InvalidParameter: throw new ArgumentException("Invalid parameter");
+                        case MessagePortError.OutOfMemory: throw new InvalidOperationException("Out of memory");
+                        case MessagePortError.PortNotFound: throw new ArgumentNullException("Port not found");
+                        case MessagePortError.CertificateNotMatch: throw new ArgumentException("Certification not match");
+                        case MessagePortError.MaxExceeded: throw new ArgumentOutOfRangeException("Max(4KB) exceeded");
+                        case MessagePortError.ResourceUnavailable: throw new ArgumentNullException("Resource unavailable");
+                    }
+                }
+            }
+            else
+            {
+                throw new InvalidOperationException("Need listening");
+            }
+        }
+
+        /// <summary>
+        /// Override GetHashCode
+        /// </summary>
+        /// <returns></returns>
+        public override int GetHashCode()
+        {
+            int hash = 0;
+            if (_portName != null)
+            {
+                hash ^= _portName.GetHashCode();
+            }
+            hash ^= _trusted.GetHashCode();
+            return hash;
+        }
+
+        /// <summary>
+        /// Override Equals
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <returns></returns>
+        public override bool Equals(object obj)
+        {
+            MessagePort p = obj as MessagePort;
+            if (p == null)
+            {
+                return false;
+            }
+            return (_portName == p._portName) & (_trusted == p._trusted);
+        }
+
+        private void RaiseMessageReceivedEvent(EventHandler<MessageReceivedEventArgs> evt, MessageReceivedEventArgs args)
+        {
+            if (evt != null)
+            {
+                evt(this, args);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Tizen.Applications/Tizen.Applications.MessagePort/MessageReceivedEventArgs.cs b/Tizen.Applications/Tizen.Applications.MessagePort/MessageReceivedEventArgs.cs
new file mode 100644 (file)
index 0000000..5cbbf97
--- /dev/null
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tizen.Applications.MessagePort
+{
+    /// <summary>
+    /// An extended EventArgs class which contains remote message port information and message
+    /// </summary>
+    public class MessageReceivedEventArgs : EventArgs
+    {
+        private RemoteValues _remote;
+        private Bundle _message;
+
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        public MessageReceivedEventArgs(Bundle message, string appId, string portName, bool trusted)
+        {
+            _message = message;
+
+            _remote = new RemoteValues();
+            _remote.AppId = appId;
+            _remote.PortName = portName;
+            _remote.Trusted = trusted;
+        }
+
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        public MessageReceivedEventArgs(Bundle message)
+        {
+            _message = message;
+        }
+
+        /// <summary>
+        /// Contains AppId, Port Name, Trusted
+        /// </summary>
+        public RemoteValues Remote
+        {
+            get
+            {
+                return _remote;
+            }
+        }
+
+        /// <summary>
+        /// The message passed from the remote application
+        /// </summary>
+        public Bundle Message
+        {
+            get
+            {
+                return _message;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Tizen.Applications/Tizen.Applications.MessagePort/RemoteValues.cs b/Tizen.Applications/Tizen.Applications.MessagePort/RemoteValues.cs
new file mode 100644 (file)
index 0000000..6279cc4
--- /dev/null
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tizen.Applications.MessagePort
+{
+    /// <summary>
+    /// Contains AppId, Port Name, Trusted
+    /// </summary>
+    public struct RemoteValues
+    {
+        /// <summary>
+        /// The ID of the remote application that sent this message
+        /// </summary>
+        public string AppId;
+        /// <summary>
+        /// The name of the remote message port
+        /// </summary>
+        public string PortName;
+        /// <summary>
+        /// If true the remote port is a trusted port, otherwise if false it is not
+        /// </summary>
+        public bool Trusted;
+    }
+}
\ No newline at end of file