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