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