From: Seunghyun Choi Date: Mon, 14 Mar 2016 05:05:56 +0000 (+0900) Subject: [MessagePort] Modify MessagePort, modify Bundle's handle X-Git-Tag: submit/trunk/20170823.075128~121^2~206^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3bfd8d983711ff4ac16b3542963f1cbd139761b2;p=platform%2Fcore%2Fcsapi%2Ftizenfx.git [MessagePort] Modify MessagePort, modify Bundle's handle Signed-off-by: Seunghyun Choi Change-Id: I390271d30a98baf71d395bf0ab840e020eb163e3 --- diff --git a/Tizen.Applications/Interop/Interop.MessagePort.cs b/Tizen.Applications/Interop/Interop.MessagePort.cs new file mode 100644 index 0000000..44af04d --- /dev/null +++ b/Tizen.Applications/Interop/Interop.MessagePort.cs @@ -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 index 0000000..81fb6d3 --- /dev/null +++ b/Tizen.Applications/Tizen.Applications.MessagePort/MessagePort.cs @@ -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 +{ + /// + /// The Message Port API provides functions to send and receive messages between applications. + /// + /// + /// 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. + /// + public class MessagePort + { + private static Dictionary s_portMap = new Dictionary(); + + /// + /// Constructor + /// + /// The name of the local message port + /// If true is the trusted message port of application, otherwise false + public MessagePort(string portName, bool trusted) + { + _portName = portName; + _trusted = trusted; + } + + ~MessagePort() + { + if (_listening) + { + StopListening(); + } + } + + /// + /// Called when a message is received. + /// + public event EventHandler 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 + } + + /// + /// The name of the local message port + /// + public string PortName + { + get + { + return _portName; + } + } + /// + /// If true the message port is a trusted port, otherwise false it is not + /// + public bool Trusted + { + get + { + return _trusted; + } + } + + /// + /// If true the message port is listening, otherwise false it is not + /// + public bool Listening + { + get + { + return _listening; + } + } + + /// + /// The local message port ID + /// + private int _portId = 0; + + /// + /// The name of the local message port + /// + private string _portName = null; + + /// + /// If true the message port is a trusted port, otherwise false it is not + /// + private bool _trusted = false; + + /// + /// If true the message port is listening, otherwise false it is not + /// + private bool _listening = false; + + private Interop.MessagePort.message_port_message_cb _messageCallBack; + + /// + /// Register the local message port. + /// + 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"); + } + } + + /// + /// Unregisters the local message port. + /// + 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"); + } + } + + /// + /// Sends a message to the message port of a remote application. + /// + /// The message to be passed to the remote application, the recommended message size is under 4KB + /// The ID of the remote application + /// The name of the remote message port + /// If true the trusted message port of remote application otherwise false + 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"); + } + } + + /// + /// Override GetHashCode + /// + /// + public override int GetHashCode() + { + int hash = 0; + if (_portName != null) + { + hash ^= _portName.GetHashCode(); + } + hash ^= _trusted.GetHashCode(); + return hash; + } + + /// + /// Override Equals + /// + /// + /// + 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 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 index 0000000..5cbbf97 --- /dev/null +++ b/Tizen.Applications/Tizen.Applications.MessagePort/MessageReceivedEventArgs.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tizen.Applications.MessagePort +{ + /// + /// An extended EventArgs class which contains remote message port information and message + /// + public class MessageReceivedEventArgs : EventArgs + { + private RemoteValues _remote; + private Bundle _message; + + /// + /// Constructor + /// + public MessageReceivedEventArgs(Bundle message, string appId, string portName, bool trusted) + { + _message = message; + + _remote = new RemoteValues(); + _remote.AppId = appId; + _remote.PortName = portName; + _remote.Trusted = trusted; + } + + /// + /// Constructor + /// + public MessageReceivedEventArgs(Bundle message) + { + _message = message; + } + + /// + /// Contains AppId, Port Name, Trusted + /// + public RemoteValues Remote + { + get + { + return _remote; + } + } + + /// + /// The message passed from the remote application + /// + 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 index 0000000..6279cc4 --- /dev/null +++ b/Tizen.Applications/Tizen.Applications.MessagePort/RemoteValues.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tizen.Applications.MessagePort +{ + /// + /// Contains AppId, Port Name, Trusted + /// + public struct RemoteValues + { + /// + /// The ID of the remote application that sent this message + /// + public string AppId; + /// + /// The name of the remote message port + /// + public string PortName; + /// + /// If true the remote port is a trusted port, otherwise if false it is not + /// + public bool Trusted; + } +} \ No newline at end of file