3d9563bad95e5ea35d4e5d9f85bb7b7168923772
[platform/core/csapi/tizenfx.git] / Tizen.Applications / Tizen.Applications.Messages / MessagePort.cs
1 using System;
2 using System.Collections.Generic;
3 using System.IO;
4 using System.Linq;
5 using System.Runtime.InteropServices;
6 using System.Text;
7 using System.Threading.Tasks;
8 using Tizen.Internals;
9
10 namespace Tizen.Applications.Messages
11 {
12     /// <summary>
13     /// The Message Port API provides functions to send and receive messages between applications.
14     /// </summary>
15     /// <remarks>
16     /// 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.
17     /// If a remote application sends a message, the registered callback function of the local port is called.
18     /// The trusted message-port API allows communications between applications that are signed by the same developer(author) certificate.
19     /// </remarks>
20     public class MessagePort : IDisposable
21     {
22         private static object s_lock = new object();
23         private static HashSet<string> s_portMap = new HashSet<string>();
24
25         /// <summary>
26         /// Constructor
27         /// </summary>
28         /// <param name="portName">The name of the local message port</param>
29         /// <param name="trusted">If true is the trusted message port of application, otherwise false</param>
30         public MessagePort(string portName, bool trusted)
31         {
32             if (String.IsNullOrEmpty(portName))
33             {
34                 MessagePortErrorFactory.ThrowException((int)MessagePortError.InvalidParameter, "Invalid PortName", "PortName");
35             }
36             _portName = portName;
37             _trusted = trusted;
38         }
39
40         ~MessagePort()
41         {
42             if (_listening)
43             {
44                 StopListening();
45             }
46             Dispose(false);
47         }
48
49         /// <summary>
50         /// Called when a message is received.
51         /// </summary>
52         public event EventHandler<MessageReceivedEventArgs> MessageReceived;
53
54         /// <summary>
55         /// The name of the local message port
56         /// </summary>
57         public string PortName
58         {
59             get
60             {
61                 return _portName;
62             }
63         }
64         /// <summary>
65         /// If true the message port is a trusted port, otherwise false it is not
66         /// </summary>
67         public bool Trusted
68         {
69             get
70             {
71                 return _trusted;
72             }
73         }
74
75         /// <summary>
76         /// If true the message port is listening, otherwise false it is not
77         /// </summary>
78         public bool Listening
79         {
80             get
81             {
82                 return _listening;
83             }
84         }
85
86         /// <summary>
87         /// The local message port ID
88         /// </summary>
89         private int _portId = 0;
90
91         /// <summary>
92         /// The name of the local message port
93         /// </summary>
94         private string _portName = null;
95
96         /// <summary>
97         /// If true the message port is a trusted port, otherwise false it is not
98         /// </summary>
99         private bool _trusted = false;
100
101         /// <summary>
102         /// If true the message port is listening, otherwise false it is not
103         /// </summary>
104         private bool _listening = false;
105
106         private Interop.MessagePort.message_port_message_cb _messageCallBack;
107
108         /// <summary>
109         /// Register the local message port.
110         /// </summary>
111         public void Listen()
112         {
113             lock (s_lock)
114             {
115                 if (s_portMap.Contains(_portName))
116                 {
117                     throw new InvalidOperationException(_portName + " is already used");
118                 }
119                 _messageCallBack = (int localPortId, string remoteAppId, string remotePortName, bool trusted, IntPtr message, IntPtr userData) =>
120                 {
121                     MessageReceivedEventArgs args = new MessageReceivedEventArgs() {
122                         Message = Bundle.MakeRetainedBundle(message)
123                     };
124
125                     if (!String.IsNullOrEmpty(remotePortName) && !String.IsNullOrEmpty(remoteAppId))
126                     {
127                         args.Remote = new RemoteValues()
128                         {
129                             AppId = remoteAppId,
130                             PortName = remotePortName,
131                             Trusted = trusted
132                         };
133                     }
134                     RaiseMessageReceivedEvent(MessageReceived, args);
135                 };
136
137                 _portId = _trusted ?
138                             Interop.MessagePort.RegisterTrustedPort(_portName, _messageCallBack, IntPtr.Zero) :
139                             Interop.MessagePort.RegisterPort(_portName, _messageCallBack, IntPtr.Zero);
140
141                 if (_portId <= 0)
142                     throw new InvalidOperationException("Can't Listening with " + _portName);
143
144                 s_portMap.Add(_portName);
145                 _listening = true;
146             }
147         }
148
149         /// <summary>
150         /// Unregisters the local message port.
151         /// </summary>
152         public void StopListening()
153         {
154             if (!_listening)
155             {
156                 throw new InvalidOperationException("Already stopped");
157             }
158
159             int ret = _trusted ?
160                         Interop.MessagePort.UnregisterTrustedPort(_portId) :
161                         Interop.MessagePort.UnregisterPort(_portId);
162
163             if (ret != (int)MessagePortError.None)
164             {
165                 MessagePortErrorFactory.ThrowException(ret);
166             }
167
168             lock (s_lock)
169             {
170                 s_portMap.Remove(_portName);
171             }
172             _portId = 0;
173             _listening = false;
174         }
175
176         /// <summary>
177         /// Sends a message to the message port of a remote application.
178         /// </summary>
179         /// <param name="message">The message to be passed to the remote application, the recommended message size is under 4KB</param>
180         /// <param name="remoteAppId">The ID of the remote application</param>
181         /// <param name="remotePortName">The name of the remote message port</param>
182         /// <param name="trusted">If true the trusted message port of remote application otherwise false</param>
183         public void Send(Bundle message, string remoteAppId, string remotePortName, bool trusted = false)
184         {
185             if (!_listening)
186             {
187                 throw new InvalidOperationException("Sould start listen before send");
188             }
189             int ret = trusted ?
190                         Interop.MessagePort.SendTrustedMessageWithLocalPort(remoteAppId, remotePortName, message.Handle, _portId) :
191                         Interop.MessagePort.SendMessageWithLocalPort(remoteAppId, remotePortName, message.Handle, _portId);
192
193             if (ret != (int)MessagePortError.None)
194             {
195                 if (ret == (int)MessagePortError.MaxExceeded)
196                 {
197                     MessagePortErrorFactory.ThrowException(ret, "Message has exceeded the maximum limit(4KB)", "Message");
198                 }
199                 MessagePortErrorFactory.ThrowException(ret, "Can't send message");
200             }
201         }
202
203         private void RaiseMessageReceivedEvent(EventHandler<MessageReceivedEventArgs> evt, MessageReceivedEventArgs args)
204         {
205             if (evt != null)
206             {
207                 evt(this, args);
208             }
209         }
210
211         protected virtual void Dispose(bool disposing)
212         {
213             if (_listening)
214             {
215                 StopListening();
216             }
217         }
218
219         public void Dispose()
220         {
221             Dispose(true);
222             GC.SuppressFinalize(this);
223         }
224     }
225 }