2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using System.Collections.Generic;
19 using Tizen.Applications;
21 namespace Tizen.Applications.Messages
24 /// The message port API provides functions to send and receive messages between applications.
27 /// 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.
28 /// If a remote application sends a message, the registered callback function of the local port is called.
29 /// The trusted message-port API allows communications between applications that are signed by the same developer(author) certificate.
31 /// <since_tizen> 3 </since_tizen>
32 public class MessagePort : IDisposable
34 private static readonly object s_lock = new object();
35 private static readonly HashSet<string> s_portMap = new HashSet<string>();
36 private static string LogTag = "MessagePort";
38 // The name of the local message port
39 private readonly string _portName = null;
41 // If true the message port is a trusted port, otherwise false it is not
42 private readonly bool _trusted = false;
44 // The local message port ID
45 private int _portId = 0;
47 // If true the message port is listening, otherwise false it is not
48 private bool _listening = false;
50 private Interop.MessagePort.message_port_message_cb _messageCallBack;
53 /// Initializes the instance of the MessagePort class.
55 /// <param name="portName">The name of the local message port.</param>
56 /// <param name="trusted">If true, it is the trusted message port of application, otherwise false.</param>
57 /// <exception cref="System.ArgumentException">Thrown when portName is null or empty.</exception>
60 /// MessagePort messagePort = new MessagePort("SenderPort", true);
63 /// <since_tizen> 3 </since_tizen>
64 public MessagePort(string portName, bool trusted)
66 if (String.IsNullOrEmpty(portName))
68 MessagePortErrorFactory.ThrowException((int)MessagePortError.InvalidParameter, "Invalid PortName", "PortName");
75 /// Destructor of the MessagePort class.
83 /// Called when a message is received.
87 /// MessagePort messagePort = new MessagePort("SenderPort", true);
88 /// messagePort.MessageReceived += MessageReceivedCallback;
89 /// static void MessageReceivedCallback(object sender, MessageReceivedEventArgs e)
91 /// Console.WriteLine("Message Received ");
92 /// if (e.Remote.AppId != null) {
93 /// Console.WriteLine("from :"+e.Remote.AppId);
98 /// <since_tizen> 3 </since_tizen>
99 public event EventHandler<MessageReceivedEventArgs> MessageReceived;
102 /// The name of the local message port.
104 /// <since_tizen> 3 </since_tizen>
105 public string PortName
113 /// If true, the message port is a trusted port, otherwise false.
115 /// <since_tizen> 3 </since_tizen>
125 /// If true, the message port is listening, otherwise false.
127 /// <since_tizen> 3 </since_tizen>
128 public bool Listening
137 /// Register the local message port.
139 /// <exception cref="System.InvalidOperationException">Thrown when portName is already used, when there is an I/O error.</exception>
140 /// <exception cref="System.ArgumentException">Thrown when there is an invalid parameter.</exception>
141 /// <exception cref="System.OutOfMemoryException">Thrown when out of memory.</exception>
144 /// MessagePort messagePort = new MessagePort("SenderPort", true);
145 /// messagePort.MessageReceived += MessageReceivedCallback;
146 /// messagePort.Listen();
149 /// <since_tizen> 3 </since_tizen>
154 if (s_portMap.Contains(_portName))
156 MessagePortErrorFactory.ThrowException((int)MessagePortError.InvalidOperation, _portName + "is already used");
158 _messageCallBack = (int localPortId, string remoteAppId, string remotePortName, bool trusted, IntPtr message, IntPtr userData) =>
160 MessageReceivedEventArgs args = new MessageReceivedEventArgs();
163 args.Message = new Bundle(new SafeBundleHandle(message, false));
167 Log.Error(LogTag, "Exception(" + ex.ToString() + ")");
171 if (args.Message == null)
173 Log.Error(LogTag, "Failed to create Bundle. message({0})", (message == IntPtr.Zero) ? "null" : message.ToString());
177 args.Remote = new RemoteValues()
179 AppId = remoteAppId != null ? remoteAppId : String.Empty,
180 PortName = remotePortName != null ? remotePortName : String.Empty,
183 MessageReceived?.Invoke(this, args);
187 Interop.MessagePort.RegisterTrustedPort(_portName, _messageCallBack, IntPtr.Zero) :
188 Interop.MessagePort.RegisterPort(_portName, _messageCallBack, IntPtr.Zero);
191 MessagePortErrorFactory.ThrowException(_portId, "RegisterPort", _portName);
193 s_portMap.Add(_portName);
199 /// Unregisters the local message port.
201 /// <exception cref="System.InvalidOperationException">Thrown when messageport is already stopped, when there is an I/O error, when the port is not found.</exception>
202 /// <exception cref="System.ArgumentException">Thrown when there is an invalid parameter.</exception>
203 /// <exception cref="System.OutOfMemoryException">Thrown when out of memory.</exception>
206 /// MessagePort messagePort = new MessagePort("SenderPort", true);
207 /// messagePort.MessageReceived += MessageReceivedCallback;
208 /// messagePort.Listen();
209 /// using (var message = new Tizen.Application.Bundle())
211 /// message.AddItem("message", "a_string");
212 /// messagePort.Send(message, "ReceiverAppID", "ReceiverPort");
214 /// messagePort.StopListening();
217 /// <since_tizen> 3 </since_tizen>
218 public void StopListening()
222 MessagePortErrorFactory.ThrowException((int)MessagePortError.InvalidOperation, "Already stopped");
226 Interop.MessagePort.UnregisterTrustedPort(_portId) :
227 Interop.MessagePort.UnregisterPort(_portId);
229 if (ret != (int)MessagePortError.None)
231 MessagePortErrorFactory.ThrowException(ret, "Error Unregister port");
236 s_portMap.Remove(_portName);
243 /// Sends an untrusted message to the message port of a remote application.
245 /// <param name="message">The message to be passed to the remote application, the recommended message size is under 4KB.</param>
246 /// <param name="remoteAppId">The ID of the remote application.</param>
247 /// <param name="remotePortName">The name of the remote message port.</param>
248 /// <exception cref="System.InvalidOperationException">Thrown when there is an I/O error, when the port is not found.</exception>
249 /// <exception cref="System.ArgumentException">Thrown when there is an invalid parameter.</exception>
250 /// <exception cref="System.OutOfMemoryException">Thrown when out of memory.</exception>
251 /// <exception cref="System.ArgumentOutOfRangeException">Thrown when message has exceeded the maximum limit(4KB).</exception>
254 /// MessagePort messagePort = new MessagePort("SenderPort", true);
255 /// messagePort.MessageReceived += MessageReceivedCallback;
256 /// messagePort.Listen();
257 /// using (var message = new Tizen.Application.Bundle())
259 /// message.AddItem("message", "a_string");
260 /// messagePort.Send(message, "ReceiverAppID", "ReceiverPort");
264 /// <since_tizen> 3 </since_tizen>
265 public void Send(Bundle message, string remoteAppId, string remotePortName)
267 Send(message, remoteAppId, remotePortName, false);
271 /// Sends a message to the message port of a remote application.
273 /// <param name="message">The message to be passed to the remote application, the recommended message size is under 4KB.</param>
274 /// <param name="remoteAppId">The ID of the remote application.</param>
275 /// <param name="remotePortName">The name of the remote message port.</param>
276 /// <param name="trusted">If true, it is the trusted message port of remote application, otherwise false.</param>
277 /// <exception cref="System.InvalidOperationException">Thrown when there is an I/O error, when the port is not found.</exception>
278 /// <exception cref="System.ArgumentException">Thrown when there is an invalid parameter.</exception>
279 /// <exception cref="System.OutOfMemoryException">Thrown when out of memory.</exception>
280 /// <exception cref="System.ArgumentOutOfRangeException">Thrown when message has exceeded the maximum limit(4KB).</exception>
281 /// <exception cref="System.UnauthorizedAccessException">Thrown when the remote application is not signed with the same certificate.</exception>
284 /// MessagePort messagePort = new MessagePort("SenderPort", true);
285 /// messagePort.MessageReceived += MessageReceivedCallback;
286 /// messagePort.Listen();
287 /// using (var message = new Tizen.Application.Bundle())
289 /// message.AddItem("message", "a_string");
290 /// messagePort.Send(message, "ReceiverAppID", "ReceiverPort", true);
294 /// <since_tizen> 3 </since_tizen>
295 public void Send(Bundle message, string remoteAppId, string remotePortName, bool trusted)
299 MessagePortErrorFactory.ThrowException((int)MessagePortError.InvalidOperation, "Should start listen before send");
301 if (message == null || message.SafeBundleHandle == null || message.SafeBundleHandle.IsInvalid)
303 MessagePortErrorFactory.ThrowException((int)MessagePortError.InvalidParameter, "message is null", "Message");
306 Interop.MessagePort.SendTrustedMessageWithLocalPort(remoteAppId, remotePortName, message.SafeBundleHandle, _portId) :
307 Interop.MessagePort.SendMessageWithLocalPort(remoteAppId, remotePortName, message.SafeBundleHandle, _portId);
309 if (ret != (int)MessagePortError.None)
311 if (ret == (int)MessagePortError.MaxExceeded)
313 MessagePortErrorFactory.ThrowException(ret, "Message has exceeded the maximum limit(4KB)", "Message");
315 MessagePortErrorFactory.ThrowException(ret, "Can't send message");
320 /// Releases the unmanaged resources used by the MessagePort class specifying whether to perform a normal dispose operation.
322 /// <param name="disposing">true for a normal dispose operation; false to finalize the handle.</param>
323 /// <since_tizen> 3 </since_tizen>
324 protected virtual void Dispose(bool disposing)
334 Log.Warn(GetType().Namespace, "Exception in Dispose :" + e.Message);
340 /// Releases all resources used by the MessagePort class.
342 /// <since_tizen> 3 </since_tizen>
343 public void Dispose()
346 GC.SuppressFinalize(this);