57a721717236b7f11d0f64f3ab7573af22982b4e
[platform/framework/native/appfw.git] / src / io / FIo_MessagePortProxy.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file        FIo_MessagePortProxy.cpp
20  * @brief       This is the implementation file for the _MessagePortProxy class.
21  *
22  */
23
24 #include <string.h>
25 #include <typeinfo>
26 #include <unique_ptr.h>
27
28 #include <package_manager.h>
29
30 #include <message-port.h>
31
32 #include <FBaseSysLog.h>
33 #include <FBase_StringConverter.h>
34 #include <FApp_AppInfo.h>
35
36 #include "FIo_MessagePortProxy.h"
37
38 using namespace std;
39
40 using namespace Tizen::App;
41 using namespace Tizen::Io;
42 using namespace Tizen::Base;
43 using namespace Tizen::Base::Collection;
44 using namespace Tizen::Base::Runtime;
45
46 namespace Tizen { namespace Io
47 {
48
49 static void
50 ConvertBundleToMap(const char *pKey, const int type, const bundle_keyval_t *pVal, void *pData)
51 {
52         SysLog(NID_IO, "CB key = %s", pKey);
53
54         HashMap* pMap = static_cast<HashMap*>(pData);
55
56         if (pKey && pVal && pMap)
57         {
58                 size_t size = 0;
59                 char* pStr = NULL;
60                 switch (type)
61                 {
62                         case BUNDLE_TYPE_STR:
63                                 bundle_keyval_get_basic_val(const_cast<bundle_keyval_t*>(pVal), reinterpret_cast<void**>(&pStr), &size);
64                                 if (pStr)
65                                 {
66                                         pMap->Add(new (std::nothrow) String(pKey), new (std::nothrow) String(pStr));
67                                 }
68
69                                 break;
70                         case BUNDLE_TYPE_BYTE:
71                                 bundle_keyval_get_basic_val(const_cast<bundle_keyval_t*>(pVal), reinterpret_cast<void**>(&pStr), &size);
72
73                                 SysLog(NID_IO, "Bundle byte value = %s, size = %d", pStr, size);
74
75                                 if (pStr)
76                                 {
77                                         ByteBuffer* pBuffer = new (std::nothrow) ByteBuffer();
78                                         SysTryReturn(NID_IO, pMap != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
79                                         result r = pBuffer->Construct(size);
80                                         SysTryReturn(NID_IO, r == E_SUCCESS, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
81
82                                         pBuffer->SetArray((const byte*)pStr, 0, size);
83                                         pBuffer->Flip();
84
85                                         pMap->Add(new (std::nothrow) String(pKey), pBuffer);
86                                 }
87
88                                 break;
89                         default:
90                                 SysLog(NID_APP, "Invalid type for %s : %d", pKey, type);
91                                 break;
92                 }
93         }
94 }
95
96 static void
97 OnMessageReceived(int id, const char* remote_app_id, const char* remote_port, bool trusted_port, bundle* data)
98 {
99         SysLog(NID_IO, "Message received");
100
101         _MessagePortProxy* p = _MessagePortProxy::GetProxy();
102
103         int ret = 0;
104         char* pLocalPort = null;
105
106         ret = messageport_get_local_port_name(id, &pLocalPort);
107         if (pLocalPort == null)
108         {
109                 SysLog(NID_IO, "No local port for id: %d", id);
110
111                 bundle_free(data);
112                 return;
113         }
114
115         SysLog(NID_IO, "local port name: %s", pLocalPort);
116
117         _IMessagePortListener* pListener = null;
118         p->__listeners.GetValue(pLocalPort, pListener);
119
120         free(pLocalPort);
121
122         if (pListener != null)
123         {
124                 HashMap* pMap = new (std::nothrow) HashMap(SingleObjectDeleter);
125                 SysTryCatch(NID_IO, pMap != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
126
127                 result r = pMap->Construct();
128                 SysTryCatch(NID_IO, r == E_SUCCESS, delete pMap, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
129
130                 SysLog(NID_IO, "bundle to map");
131
132                 bundle_foreach(data, ConvertBundleToMap, pMap);
133
134                 if (remote_app_id == null) // Uni-directional
135                 {
136                         pListener->OnMessageReceivedN(pMap);
137                 }
138                 else // Bi-directional
139                 {
140                         SysLog(NID_IO, "Message received from [%s:%s], trusted: %d", remote_app_id, remote_port, trusted_port);
141
142                         pListener->OnMessageReceivedN(remote_app_id, remote_port, trusted_port, pMap);
143                 }
144         }
145
146 CATCH:
147         bundle_free(data);
148 }
149
150 static void
151 OnTrustedMessageReceived(int id, const char* remote_app_id, const char* remote_port, bool trusted_port, bundle* data)
152 {
153         SysLog(NID_IO, "Trusted message received");
154
155         _MessagePortProxy* p = _MessagePortProxy::GetProxy();
156
157         int ret = 0;
158         char* pLocalPort = null;
159         ret = messageport_get_local_port_name(id, &pLocalPort);
160         if (pLocalPort == null)
161         {
162                 SysLog(NID_IO, "No local port for id: %d", id);
163
164                 bundle_free(data);
165                 return;
166         }
167
168         _IMessagePortListener* pListener = null;
169         p->__trustedListeners.GetValue(pLocalPort, pListener);
170
171         free(pLocalPort);
172
173         if (pListener != null)
174         {
175                 HashMap* pMap = new (std::nothrow) HashMap(SingleObjectDeleter);
176                 SysTryCatch(NID_IO, pMap != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
177
178                 result r = pMap->Construct();
179                 SysTryCatch(NID_IO, r == E_SUCCESS, delete pMap, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
180
181                 bundle_foreach(data, ConvertBundleToMap, pMap);
182
183                 if (remote_app_id == null) // Uni-directional
184                 {
185                         pListener->OnMessageReceivedN(pMap);
186                 }
187                 else // Bi-directional
188                 {
189                         SysLog(NID_IO, "Trusted message received from [%s:%s], trusted: %d", remote_app_id, remote_port, trusted_port);
190                         pListener->OnMessageReceivedN(remote_app_id, remote_port, trusted_port, pMap);
191                 }
192         }
193
194 CATCH:
195         bundle_free(data);
196 }
197
198 _MessagePortProxy::_MessagePortProxy(void)
199 {
200 }
201
202 _MessagePortProxy::~_MessagePortProxy(void)
203 {
204 }
205
206 result
207 _MessagePortProxy::Construct(void)
208 {
209         static _StringHashProvider hashProvider;
210         static _StringComparer stringComparer;
211
212         __listeners.Construct(0, 0, hashProvider, stringComparer);
213         __trustedListeners.Construct(0, 0, hashProvider, stringComparer);
214         __ids.Construct(0, 0, hashProvider, stringComparer);
215         __trustedIds.Construct(0, 0, hashProvider, stringComparer);
216
217         __appId = _AppInfo::GetApplicationId();
218
219         return E_SUCCESS;
220 }
221
222
223 result
224 _MessagePortProxy::RegisterMessagePort(const String& localPort, bool isTrusted,
225                                                                         const _IMessagePortListener& listener)
226 {
227         SysLog(NID_IO, "Register a message port : [%ls:%ls]", __appId.GetPointer(), localPort.GetPointer());
228
229         result r = E_SUCCESS;
230         int ret = 0;
231         bool contain = false;
232
233         unique_ptr<char[]> pLocal(_StringConverter::CopyToCharArrayN(localPort));
234
235         if (!isTrusted)
236         {
237                 ret = messageport_register_local_port(pLocal.get(), OnMessageReceived);
238                 SysTryReturnResult(NID_IO, ret >= 0, E_SYSTEM, "Failed to register the local message port. %d", ret);
239
240                 __listeners.ContainsKey(localPort, contain);
241
242                 if (!contain)
243                 {
244                         __listeners.Add(localPort, const_cast<_IMessagePortListener*>(&listener));
245                         __ids.Add(localPort, ret);
246                 }
247                 else
248                 {
249                         __listeners.SetValue(localPort, const_cast<_IMessagePortListener*>(&listener));
250                         __ids.SetValue(localPort, ret);
251                 }
252
253         }
254         else
255         {
256                 ret = messageport_register_trusted_local_port(pLocal.get(), OnTrustedMessageReceived);
257                 SysTryReturnResult(NID_IO, ret >= 0, E_SYSTEM, "Failed to register the trusted local message port. %d", ret);
258
259                 __trustedListeners.ContainsKey(localPort, contain);
260
261                 if (!contain)
262                 {
263                         __trustedListeners.Add(localPort, const_cast<_IMessagePortListener*>(&listener));
264                         __trustedIds.Add(localPort, ret);
265                 }
266                 else
267                 {
268                         __trustedListeners.SetValue(localPort, const_cast<_IMessagePortListener*>(&listener));
269                         __trustedIds.SetValue(localPort, ret);
270                 }
271
272         }
273
274         return E_SUCCESS;
275 }
276
277 result
278 _MessagePortProxy::RequestRemotePort(const AppId& remoteAppId,
279                                                                         const String& remotePort,
280                                                                         bool isTrusted)
281 {
282         SysLog(NID_IO, "Request a remote message port [%ls:%ls]", remoteAppId.GetPointer(), remotePort.GetPointer());
283
284         result r = E_SUCCESS;
285         int ret = 0;
286         bool exist = false;
287
288         unique_ptr<char[]> pAppId(_StringConverter::CopyToCharArrayN(remoteAppId));
289         unique_ptr<char[]> pPort(_StringConverter::CopyToCharArrayN(remotePort));
290
291         if (!isTrusted)
292         {
293                 ret = messageport_check_remote_port(pAppId.get(), pPort.get(), &exist);
294         }
295         else
296         {
297                 ret = messageport_check_trusted_remote_port(pAppId.get(), pPort.get(), &exist);
298         }
299
300         if (ret < 0)
301         {
302                 r = ConvertToResult(ret);
303
304                 SysTryReturnResult(NID_IO, r != E_CERTIFICATE_VERIFICATION_FAILED, E_CERTIFICATE_VERIFICATION_FAILED, "The target application is not signed with the same certificate.");
305
306                 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to request the remote message port.");
307
308                 return r;
309         }
310
311         SysTryReturnResult(NID_IO, exist, E_OBJ_NOT_FOUND, "The remote message port is not found.");
312
313         return E_SUCCESS;
314 }
315
316 result
317 _MessagePortProxy::SendMessage(const AppId& remoteAppId, const String& remotePort, bool isTrusted, const HashMap* pMap)
318 {
319         SysLog(NID_IO, "Send a unidirectional message to remote port [%ls:%ls]", remoteAppId.GetPointer(), remotePort.GetPointer());
320
321         int ret = 0;
322
323         // Convert Map to bundle
324         bundle* b = ConvertMapToBundleN(pMap);
325         SysTryReturnResult(NID_IO, b != null, E_SYSTEM, "Internal system errors.");
326
327         unique_ptr<char[]> pRemoteAppId(_StringConverter::CopyToCharArrayN(remoteAppId));
328         unique_ptr<char[]> pRemotePort(_StringConverter::CopyToCharArrayN(remotePort));
329
330         if (!isTrusted)
331         {
332                 ret = messageport_send_message(pRemoteAppId.get(), pRemotePort.get(), b);
333         }
334         else
335         {
336                 ret = messageport_send_trusted_message(pRemoteAppId.get(), pRemotePort.get(), b);
337         }
338
339         bundle_free(b);
340
341         if (ret < 0)
342         {
343                 result r = ConvertToResult(ret);
344
345                 SysTryReturnResult(NID_IO, r != E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND, "The remote message port is not found.");
346                 SysTryReturnResult(NID_IO, r != E_CERTIFICATE_VERIFICATION_FAILED, E_CERTIFICATE_VERIFICATION_FAILED, "The target application is not signed with the same certificate.");
347                 SysTryReturnResult(NID_IO, r != E_MAX_EXCEEDED, E_MAX_EXCEEDED, "The size of the message has exceeded the maximum limit.");
348
349                 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to request the remote message port.");
350
351                 return r;
352         }
353
354         return E_SUCCESS;
355 }
356
357 result
358 _MessagePortProxy::SendMessage(const String& localPort, bool isTrustedLocal, const AppId& remoteAppId, const String& remotePort, bool isTrustedRemote, const HashMap* pMap)
359 {
360         SysLog(NID_IO, "Send a bidirectional message from [%ls:%ls] to [%ls:%ls]", __appId.GetPointer(), localPort.GetPointer(), remoteAppId.GetPointer(), remotePort.GetPointer());
361
362         result r = E_SUCCESS;
363         int id = 0;
364
365         if (!isTrustedLocal)
366         {
367                 r = __ids.GetValue(localPort, id);
368         }
369         else
370         {
371                 r = __trustedIds.GetValue(localPort, id);
372         }
373
374         SysTryReturnResult(NID_IO, r == E_SUCCESS, E_SYSTEM, "Internal system errors.");
375
376         // Convert Map to bundle
377         bundle* b = ConvertMapToBundleN(pMap);
378         SysTryReturnResult(NID_IO, b != null, E_SYSTEM, "Internal system errors.");
379
380         unique_ptr<char[]> pRemoteAppId(_StringConverter::CopyToCharArrayN(remoteAppId));
381         unique_ptr<char[]> pRemotePort(_StringConverter::CopyToCharArrayN(remotePort));
382
383         int ret = 0;
384         if (!isTrustedRemote)
385         {
386                 ret = messageport_send_bidirectional_message(id, pRemoteAppId.get(), pRemotePort.get(), b);
387         }
388         else
389         {
390                 ret = messageport_send_bidirectional_trusted_message(id, pRemoteAppId.get(), pRemotePort.get(), b);
391         }
392
393         bundle_free(b);
394
395         if (ret < 0)
396         {
397                 result r = ConvertToResult(ret);
398
399                 SysTryReturnResult(NID_IO, r != E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND, "The remote message port is not found.");
400                 SysTryReturnResult(NID_IO, r != E_CERTIFICATE_VERIFICATION_FAILED, E_CERTIFICATE_VERIFICATION_FAILED, "The target application is not signed with the same certificate.");
401                 SysTryReturnResult(NID_IO, r != E_MAX_EXCEEDED, E_MAX_EXCEEDED, "The size of the message has exceeded the maximum limit.");
402
403                 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to request the remote message port.");
404
405                 return r;
406         }
407
408         return E_SUCCESS;
409 }
410
411 _MessagePortProxy*
412 _MessagePortProxy::GetProxy(void)
413 {
414         static _MessagePortProxy* pProxy = null;
415
416         if (pProxy == null)
417         {
418                 unique_ptr<_MessagePortProxy> p(new (std::nothrow) _MessagePortProxy);
419                 SysTryReturn(NID_IO, p != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
420
421                 result r = p->Construct();
422                 SysTryReturn(NID_IO, r == E_SUCCESS, null, E_SYSTEM, "[E_SYSTEM] Failed to initialize a  message port proxy.");
423
424                 pProxy = p.release();
425         }
426
427         SetLastResult(E_SUCCESS);
428         return pProxy;
429 }
430
431 result
432 _MessagePortProxy::ConvertToResult(int error)
433 {
434         SysLog(NID_IO, "Native error = %d", error);
435
436         switch (error)
437         {
438                 case MESSAGEPORT_ERROR_IO_ERROR:
439                         return E_SYSTEM;
440
441                 case MESSAGEPORT_ERROR_OUT_OF_MEMORY:
442                         return E_OUT_OF_MEMORY;
443
444                 case MESSAGEPORT_ERROR_INVALID_PARAMETER:
445                         return E_INVALID_ARG;
446
447                 case MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND:
448                         return E_OBJ_NOT_FOUND;
449
450                 case MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH:
451                         return E_CERTIFICATE_VERIFICATION_FAILED;
452
453                 case MESSAGEPORT_ERROR_MAX_EXCEEDED:
454                         return E_MAX_EXCEEDED;
455
456                 default:
457                         return E_SYSTEM;
458         }
459
460         return E_SYSTEM;
461 }
462
463 bundle*
464 _MessagePortProxy::ConvertMapToBundleN(const HashMap* pMap)
465 {
466         bundle *b = bundle_create();
467
468         std::unique_ptr<IMapEnumerator> pEnum (pMap->GetMapEnumeratorN());
469         while(pEnum->MoveNext() == E_SUCCESS)
470         {
471                 const String* pKey = dynamic_cast<const String*>(pEnum->GetKey());
472                 const Object* pValue = pEnum->GetValue();
473
474                 if (pKey && pValue)
475                 {
476                         unique_ptr<char[]> pKeyData(_StringConverter::CopyToCharArrayN(*pKey));
477
478                         if (typeid(*pValue) == typeid(const String)) // String
479                         {
480                                 unique_ptr<char[]> pValueData(_StringConverter::CopyToCharArrayN(*(static_cast<const String*>(pValue))));
481
482                                 //SysLog(NID_IO, "key: %s, value: %s", pKeyData.get(), pValueData.get());
483
484                                 bundle_add(b, pKeyData.get(), pValueData.get());
485                         }
486                         else // ByteBuffer
487                         {
488                                 if (typeid(*pValue) == typeid(const ByteBuffer)) // ByteBuffer
489                                 {
490                                         const ByteBuffer* pBuffer = static_cast<const ByteBuffer*>(pValue);
491
492                                         // Add a byte data to bundle
493                                         SysLog(NID_IO, "Add a string key: %s, byte value: %s", pKeyData.get(), pBuffer->GetPointer());
494
495                                         bundle_add_byte(b, pKeyData.get(), pBuffer->GetPointer(), pBuffer->GetLimit());
496                                 }
497                                 else
498                                 {
499                                         SysLog(NID_IO, "Not supported");
500
501                                         bundle_free(b);
502                                         return null;
503                                 }
504                         }
505                 }
506                 else
507                 {
508                         SysLog(NID_IO, "Not supported");
509
510                         bundle_free(b);
511                         return null;
512                 }
513         }
514
515         return b;
516 }
517
518 }}