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