Add IPC sync result for SerialPort::Write()
[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 <FBaseByteBuffer.h>
31
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         int ret = 0;
235         bool contain = false;
236
237         unique_ptr<char[]> pLocal(_StringConverter::CopyToCharArrayN(localPort));
238
239         if (!isTrusted)
240         {
241                 ret = messageport_register_local_port(pLocal.get(), OnMessageReceived);
242                 SysTryReturnResult(NID_IO, ret >= 0, E_SYSTEM, "Failed to register the local message port. %d", ret);
243
244                 __listeners.ContainsKey(localPort, contain);
245
246                 if (!contain)
247                 {
248                         __listeners.Add(localPort, const_cast<_IMessagePortListener*>(&listener));
249                         __ids.Add(localPort, ret);
250                 }
251                 else
252                 {
253                         __listeners.SetValue(localPort, const_cast<_IMessagePortListener*>(&listener));
254                         __ids.SetValue(localPort, ret);
255                 }
256
257         }
258         else
259         {
260                 ret = messageport_register_trusted_local_port(pLocal.get(), OnTrustedMessageReceived);
261                 SysTryReturnResult(NID_IO, ret >= 0, E_SYSTEM, "Failed to register the trusted local message port. %d", ret);
262
263                 __trustedListeners.ContainsKey(localPort, contain);
264
265                 if (!contain)
266                 {
267                         __trustedListeners.Add(localPort, const_cast<_IMessagePortListener*>(&listener));
268                         __trustedIds.Add(localPort, ret);
269                 }
270                 else
271                 {
272                         __trustedListeners.SetValue(localPort, const_cast<_IMessagePortListener*>(&listener));
273                         __trustedIds.SetValue(localPort, ret);
274                 }
275
276         }
277
278         return E_SUCCESS;
279 }
280
281 result
282 _MessagePortProxy::RequestRemotePort(const AppId& remoteAppId,
283                                                                         const String& remotePort,
284                                                                         bool isTrusted)
285 {
286         SysSecureLog(NID_IO, "Request a remote message port [%ls:%ls]", remoteAppId.GetPointer(), remotePort.GetPointer());
287
288         result r = E_SUCCESS;
289         int ret = 0;
290         bool exist = false;
291
292         unique_ptr<char[]> pAppId(_StringConverter::CopyToCharArrayN(remoteAppId));
293         unique_ptr<char[]> pPort(_StringConverter::CopyToCharArrayN(remotePort));
294
295         if (!isTrusted)
296         {
297                 ret = messageport_check_remote_port(pAppId.get(), pPort.get(), &exist);
298         }
299         else
300         {
301                 ret = messageport_check_trusted_remote_port(pAppId.get(), pPort.get(), &exist);
302         }
303
304         if (ret < 0)
305         {
306                 r = ConvertToResult(ret);
307
308                 SysTryReturnResult(NID_IO, r != E_CERTIFICATE_VERIFICATION_FAILED, E_CERTIFICATE_VERIFICATION_FAILED, "The target application is not signed with the same certificate.");
309
310                 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to request the remote message port.");
311
312                 return r;
313         }
314
315         SysTryReturnResult(NID_IO, exist, E_OBJ_NOT_FOUND, "The remote message port is not found.");
316
317         return E_SUCCESS;
318 }
319
320 result
321 _MessagePortProxy::SendMessage(const AppId& remoteAppId, const String& remotePort, bool isTrusted, const HashMap* pMap)
322 {
323         SysSecureLog(NID_IO, "Send a unidirectional message to remote port [%ls:%ls]", remoteAppId.GetPointer(), remotePort.GetPointer());
324
325         int ret = 0;
326         int size = 0;
327
328         // Convert Map to bundle
329         bundle* b = ConvertMapToBundleN(pMap, &size);
330         SysTryReturnResult(NID_IO, b != null, E_INVALID_ARG, "The argument is invalid.");
331         //SysTryReturnResult(NID_IO, size <= MAX_MESSAGE_SIZE, E_MAX_EXCEEDED, "The size of the message has exceeded the maximum limit.");
332
333         unique_ptr<char[]> pRemoteAppId(_StringConverter::CopyToCharArrayN(remoteAppId));
334         unique_ptr<char[]> pRemotePort(_StringConverter::CopyToCharArrayN(remotePort));
335
336         if (!isTrusted)
337         {
338                 ret = messageport_send_message(pRemoteAppId.get(), pRemotePort.get(), b);
339         }
340         else
341         {
342                 ret = messageport_send_trusted_message(pRemoteAppId.get(), pRemotePort.get(), b);
343         }
344
345         bundle_free(b);
346
347         if (ret < 0)
348         {
349                 result r = ConvertToResult(ret);
350
351                 SysTryReturnResult(NID_IO, r != E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND, "The remote message port is not found.");
352                 SysTryReturnResult(NID_IO, r != E_CERTIFICATE_VERIFICATION_FAILED, E_CERTIFICATE_VERIFICATION_FAILED, "The target application is not signed with the same certificate.");
353                 SysTryReturnResult(NID_IO, r != E_MAX_EXCEEDED, E_MAX_EXCEEDED, "The size of the message has exceeded the maximum limit.");
354
355                 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to request the remote message port.");
356
357                 return r;
358         }
359
360         return E_SUCCESS;
361 }
362
363 result
364 _MessagePortProxy::SendMessage(const String& localPort, bool isTrustedLocal, const AppId& remoteAppId, const String& remotePort, bool isTrustedRemote, const HashMap* pMap)
365 {
366         SysSecureLog(NID_IO, "Send a bidirectional message from [%ls:%ls] to [%ls:%ls]", __appId.GetPointer(), localPort.GetPointer(), remoteAppId.GetPointer(), remotePort.GetPointer());
367
368         result r = E_SUCCESS;
369         int id = 0;
370
371         if (!isTrustedLocal)
372         {
373                 r = __ids.GetValue(localPort, id);
374         }
375         else
376         {
377                 r = __trustedIds.GetValue(localPort, id);
378         }
379
380         SysTryReturnResult(NID_IO, r == E_SUCCESS, E_SYSTEM, "Internal system errors.");
381
382         int size = 0;
383
384         // Convert Map to bundle
385         bundle* b = ConvertMapToBundleN(pMap, &size);
386         SysTryReturnResult(NID_IO, b != null, E_INVALID_ARG, "The argument is invalid.");
387         //SysTryReturnResult(NID_IO, size <= MAX_MESSAGE_SIZE, E_MAX_EXCEEDED, "The size of the message has exceeded the maximum limit.");
388
389         unique_ptr<char[]> pRemoteAppId(_StringConverter::CopyToCharArrayN(remoteAppId));
390         unique_ptr<char[]> pRemotePort(_StringConverter::CopyToCharArrayN(remotePort));
391
392         int ret = 0;
393         if (!isTrustedRemote)
394         {
395                 ret = messageport_send_bidirectional_message(id, pRemoteAppId.get(), pRemotePort.get(), b);
396         }
397         else
398         {
399                 ret = messageport_send_bidirectional_trusted_message(id, pRemoteAppId.get(), pRemotePort.get(), b);
400         }
401
402         bundle_free(b);
403
404         if (ret < 0)
405         {
406                 result r = ConvertToResult(ret);
407
408                 SysTryReturnResult(NID_IO, r != E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND, "The remote message port is not found.");
409                 SysTryReturnResult(NID_IO, r != E_CERTIFICATE_VERIFICATION_FAILED, E_CERTIFICATE_VERIFICATION_FAILED, "The target application is not signed with the same certificate.");
410                 SysTryReturnResult(NID_IO, r != E_MAX_EXCEEDED, E_MAX_EXCEEDED, "The size of the message has exceeded the maximum limit.");
411
412                 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to request the remote message port.");
413
414                 return r;
415         }
416
417         return E_SUCCESS;
418 }
419
420 _MessagePortProxy*
421 _MessagePortProxy::GetProxy(void)
422 {
423         static _MessagePortProxy* pProxy = null;
424
425         if (pProxy == null)
426         {
427                 unique_ptr<_MessagePortProxy> p(new (std::nothrow) _MessagePortProxy);
428                 SysTryReturn(NID_IO, p != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
429
430                 result r = p->Construct();
431                 SysTryReturn(NID_IO, r == E_SUCCESS, null, E_SYSTEM, "[E_SYSTEM] Failed to initialize a  message port proxy.");
432
433                 pProxy = p.release();
434         }
435
436         SetLastResult(E_SUCCESS);
437         return pProxy;
438 }
439
440 result
441 _MessagePortProxy::ConvertToResult(int error)
442 {
443         SysLog(NID_IO, "Native error = %d", error);
444
445         switch (error)
446         {
447                 case MESSAGEPORT_ERROR_IO_ERROR:
448                         return E_SYSTEM;
449
450                 case MESSAGEPORT_ERROR_OUT_OF_MEMORY:
451                         return E_OUT_OF_MEMORY;
452
453                 case MESSAGEPORT_ERROR_INVALID_PARAMETER:
454                         return E_INVALID_ARG;
455
456                 case MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND:
457                         return E_OBJ_NOT_FOUND;
458
459                 case MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH:
460                         return E_CERTIFICATE_VERIFICATION_FAILED;
461
462                 case MESSAGEPORT_ERROR_MAX_EXCEEDED:
463                         return E_MAX_EXCEEDED;
464
465                 default:
466                         return E_SYSTEM;
467         }
468
469         return E_SYSTEM;
470 }
471
472 bundle*
473 _MessagePortProxy::ConvertMapToBundleN(const HashMap* pMap, int* pSize)
474 {
475         bundle *b = bundle_create();
476         int size = 0;
477
478         std::unique_ptr<IMapEnumerator> pEnum (pMap->GetMapEnumeratorN());
479         while(pEnum->MoveNext() == E_SUCCESS)
480         {
481                 const String* pKey = dynamic_cast<const String*>(pEnum->GetKey());
482                 const Object* pValue = pEnum->GetValue();
483
484                 if (pKey && pValue)
485                 {
486                         unique_ptr<char[]> pKeyData(_StringConverter::CopyToCharArrayN(*pKey));
487
488                         if (typeid(*pValue) == typeid(const String)) // String
489                         {
490                                 const String* pStr = static_cast<const String*>(pValue);
491                                 size += pStr->GetLength() * sizeof(wchar_t);
492
493                                 unique_ptr<char[]> pValueData(_StringConverter::CopyToCharArrayN(*pStr));
494
495                                 //SysLog(NID_IO, "key: %s, value: %s", pKeyData.get(), pValueData.get());
496
497                                 bundle_add(b, pKeyData.get(), pValueData.get());
498                         }
499                         else // ByteBuffer
500                         {
501                                 if (typeid(*pValue) == typeid(const ByteBuffer)) // ByteBuffer
502                                 {
503                                         const ByteBuffer* pBuffer = static_cast<const ByteBuffer*>(pValue);
504                                         size += pBuffer->GetLimit();
505
506                                         //SysLog(NID_IO, "Add a string key: %s, byte value: %s", pKeyData.get(), pBuffer->GetPointer());
507
508                                         bundle_add_byte(b, pKeyData.get(), pBuffer->GetPointer(), pBuffer->GetLimit());
509                                 }
510                                 else
511                                 {
512                                         SysLog(NID_IO, "The value type is not supported.");
513
514                                         bundle_free(b);
515                                         return null;
516                                 }
517                         }
518                 }
519                 else
520                 {
521                         SysLog(NID_IO, "The key type is not supported.");
522
523                         bundle_free(b);
524                         return null;
525                 }
526         }
527
528         *pSize = size;
529         return b;
530 }
531
532 }}