2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @file FIo_MessagePortProxy.cpp
19 * @brief This is the implementation file for the _MessagePortProxy class.
25 #include <unique_ptr.h>
27 #include <message-port.h>
29 #include <FBaseSysLog.h>
30 #include <FBase_StringConverter.h>
31 #include <FApp_AppInfo.h>
33 #include "FIo_MessagePortProxy.h"
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;
43 namespace Tizen { namespace Io
46 static const int MAX_MESSAGE_SIZE = 16 * 1024;
49 ConvertBundleToMap(const char *pKey, const int type, const bundle_keyval_t *pVal, void *pData)
51 //SysLog(NID_IO, "CB key = %s", pKey);
53 HashMap* pMap = static_cast<HashMap*>(pData);
55 if (pKey && pVal && pMap)
62 bundle_keyval_get_basic_val(const_cast<bundle_keyval_t*>(pVal), reinterpret_cast<void**>(&pStr), &size);
65 pMap->Add(new (std::nothrow) String(pKey), new (std::nothrow) String(pStr));
69 case BUNDLE_TYPE_BYTE:
70 bundle_keyval_get_basic_val(const_cast<bundle_keyval_t*>(pVal), reinterpret_cast<void**>(&pStr), &size);
72 //SysLog(NID_IO, "Bundle byte value = %s, size = %d", pStr, size);
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.");
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.");
86 pMap->Add(new (std::nothrow) String(pKey), pBuffer);
91 SysLog(NID_APP, "Invalid type for %s : %d", pKey, type);
101 OnMessageReceived(int id, const char* remote_app_id, const char* remote_port, bool trusted_port, bundle* data)
103 SysLog(NID_IO, "Message received");
105 _MessagePortProxy* p = _MessagePortProxy::GetProxy();
108 char* pLocalPort = null;
110 ret = messageport_get_local_port_name(id, &pLocalPort);
111 if (pLocalPort == null)
113 SysSecureLog(NID_IO, "No local port for id: %d", id);
119 //SysLog(NID_IO, "local port name: %s", pLocalPort);
121 _IMessagePortListener* pListener = null;
122 p->__listeners.GetValue(pLocalPort, pListener);
126 if (pListener != null)
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.");
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.");
134 bundle_foreach(data, ConvertBundleToMap, pMap);
136 if (remote_app_id == null) // Uni-directional
138 pListener->OnMessageReceivedN(pMap);
140 else // Bi-directional
142 SysSecureLog(NID_IO, "Message received from [%s:%s], trusted: %d", remote_app_id, remote_port, trusted_port);
144 pListener->OnMessageReceivedN(remote_app_id, remote_port, trusted_port, pMap);
153 OnTrustedMessageReceived(int id, const char* remote_app_id, const char* remote_port, bool trusted_port, bundle* data)
155 SysLog(NID_IO, "Trusted message received");
157 _MessagePortProxy* p = _MessagePortProxy::GetProxy();
160 char* pLocalPort = null;
161 ret = messageport_get_local_port_name(id, &pLocalPort);
162 if (pLocalPort == null)
164 SysSecureLog(NID_IO, "No local port for id: %d", id);
170 _IMessagePortListener* pListener = null;
171 p->__trustedListeners.GetValue(pLocalPort, pListener);
175 if (pListener != null)
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.");
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.");
183 bundle_foreach(data, ConvertBundleToMap, pMap);
185 if (remote_app_id == null) // Uni-directional
187 pListener->OnMessageReceivedN(pMap);
189 else // Bi-directional
191 SysSecureLog(NID_IO, "Trusted message received from [%s:%s], trusted: %d", remote_app_id, remote_port, trusted_port);
193 pListener->OnMessageReceivedN(remote_app_id, remote_port, trusted_port, pMap);
201 _MessagePortProxy::_MessagePortProxy(void)
205 _MessagePortProxy::~_MessagePortProxy(void)
210 _MessagePortProxy::Construct(void)
212 static _StringHashProvider hashProvider;
213 static _StringComparer stringComparer;
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);
220 __appId = _AppInfo::GetApplicationId();
227 _MessagePortProxy::RegisterMessagePort(const String& localPort, bool isTrusted,
228 const _IMessagePortListener& listener)
230 SysSecureLog(NID_IO, "Register a message port : [%ls:%ls]", __appId.GetPointer(), localPort.GetPointer());
232 result r = E_SUCCESS;
234 bool contain = false;
236 unique_ptr<char[]> pLocal(_StringConverter::CopyToCharArrayN(localPort));
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);
243 __listeners.ContainsKey(localPort, contain);
247 __listeners.Add(localPort, const_cast<_IMessagePortListener*>(&listener));
248 __ids.Add(localPort, ret);
252 __listeners.SetValue(localPort, const_cast<_IMessagePortListener*>(&listener));
253 __ids.SetValue(localPort, ret);
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);
262 __trustedListeners.ContainsKey(localPort, contain);
266 __trustedListeners.Add(localPort, const_cast<_IMessagePortListener*>(&listener));
267 __trustedIds.Add(localPort, ret);
271 __trustedListeners.SetValue(localPort, const_cast<_IMessagePortListener*>(&listener));
272 __trustedIds.SetValue(localPort, ret);
281 _MessagePortProxy::RequestRemotePort(const AppId& remoteAppId,
282 const String& remotePort,
285 SysSecureLog(NID_IO, "Request a remote message port [%ls:%ls]", remoteAppId.GetPointer(), remotePort.GetPointer());
287 result r = E_SUCCESS;
291 unique_ptr<char[]> pAppId(_StringConverter::CopyToCharArrayN(remoteAppId));
292 unique_ptr<char[]> pPort(_StringConverter::CopyToCharArrayN(remotePort));
296 ret = messageport_check_remote_port(pAppId.get(), pPort.get(), &exist);
300 ret = messageport_check_trusted_remote_port(pAppId.get(), pPort.get(), &exist);
305 r = ConvertToResult(ret);
307 SysTryReturnResult(NID_IO, r != E_CERTIFICATE_VERIFICATION_FAILED, E_CERTIFICATE_VERIFICATION_FAILED, "The target application is not signed with the same certificate.");
309 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to request the remote message port.");
314 SysTryReturnResult(NID_IO, exist, E_OBJ_NOT_FOUND, "The remote message port is not found.");
320 _MessagePortProxy::SendMessage(const AppId& remoteAppId, const String& remotePort, bool isTrusted, const HashMap* pMap)
322 SysSecureLog(NID_IO, "Send a unidirectional message to remote port [%ls:%ls]", remoteAppId.GetPointer(), remotePort.GetPointer());
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.");
332 unique_ptr<char[]> pRemoteAppId(_StringConverter::CopyToCharArrayN(remoteAppId));
333 unique_ptr<char[]> pRemotePort(_StringConverter::CopyToCharArrayN(remotePort));
337 ret = messageport_send_message(pRemoteAppId.get(), pRemotePort.get(), b);
341 ret = messageport_send_trusted_message(pRemoteAppId.get(), pRemotePort.get(), b);
348 result r = ConvertToResult(ret);
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.");
354 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to request the remote message port.");
363 _MessagePortProxy::SendMessage(const String& localPort, bool isTrustedLocal, const AppId& remoteAppId, const String& remotePort, bool isTrustedRemote, const HashMap* pMap)
365 SysSecureLog(NID_IO, "Send a bidirectional message from [%ls:%ls] to [%ls:%ls]", __appId.GetPointer(), localPort.GetPointer(), remoteAppId.GetPointer(), remotePort.GetPointer());
367 result r = E_SUCCESS;
372 r = __ids.GetValue(localPort, id);
376 r = __trustedIds.GetValue(localPort, id);
379 SysTryReturnResult(NID_IO, r == E_SUCCESS, E_SYSTEM, "Internal system errors.");
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.");
388 unique_ptr<char[]> pRemoteAppId(_StringConverter::CopyToCharArrayN(remoteAppId));
389 unique_ptr<char[]> pRemotePort(_StringConverter::CopyToCharArrayN(remotePort));
392 if (!isTrustedRemote)
394 ret = messageport_send_bidirectional_message(id, pRemoteAppId.get(), pRemotePort.get(), b);
398 ret = messageport_send_bidirectional_trusted_message(id, pRemoteAppId.get(), pRemotePort.get(), b);
405 result r = ConvertToResult(ret);
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.");
411 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to request the remote message port.");
420 _MessagePortProxy::GetProxy(void)
422 static _MessagePortProxy* pProxy = null;
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.");
429 result r = p->Construct();
430 SysTryReturn(NID_IO, r == E_SUCCESS, null, E_SYSTEM, "[E_SYSTEM] Failed to initialize a message port proxy.");
432 pProxy = p.release();
435 SetLastResult(E_SUCCESS);
440 _MessagePortProxy::ConvertToResult(int error)
442 SysLog(NID_IO, "Native error = %d", error);
446 case MESSAGEPORT_ERROR_IO_ERROR:
449 case MESSAGEPORT_ERROR_OUT_OF_MEMORY:
450 return E_OUT_OF_MEMORY;
452 case MESSAGEPORT_ERROR_INVALID_PARAMETER:
453 return E_INVALID_ARG;
455 case MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND:
456 return E_OBJ_NOT_FOUND;
458 case MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH:
459 return E_CERTIFICATE_VERIFICATION_FAILED;
461 case MESSAGEPORT_ERROR_MAX_EXCEEDED:
462 return E_MAX_EXCEEDED;
472 _MessagePortProxy::ConvertMapToBundleN(const HashMap* pMap, int* pSize)
474 bundle *b = bundle_create();
477 std::unique_ptr<IMapEnumerator> pEnum (pMap->GetMapEnumeratorN());
478 while(pEnum->MoveNext() == E_SUCCESS)
480 const String* pKey = dynamic_cast<const String*>(pEnum->GetKey());
481 const Object* pValue = pEnum->GetValue();
485 unique_ptr<char[]> pKeyData(_StringConverter::CopyToCharArrayN(*pKey));
487 if (typeid(*pValue) == typeid(const String)) // String
489 const String* pStr = static_cast<const String*>(pValue);
490 size += pStr->GetLength() * sizeof(wchar_t);
492 unique_ptr<char[]> pValueData(_StringConverter::CopyToCharArrayN(*pStr));
494 //SysLog(NID_IO, "key: %s, value: %s", pKeyData.get(), pValueData.get());
496 bundle_add(b, pKeyData.get(), pValueData.get());
500 if (typeid(*pValue) == typeid(const ByteBuffer)) // ByteBuffer
502 const ByteBuffer* pBuffer = static_cast<const ByteBuffer*>(pValue);
503 size += pBuffer->GetLimit();
505 //SysLog(NID_IO, "Add a string key: %s, byte value: %s", pKeyData.get(), pBuffer->GetPointer());
507 bundle_add_byte(b, pKeyData.get(), pBuffer->GetPointer(), pBuffer->GetLimit());
511 SysLog(NID_IO, "The value type is not supported.");
520 SysLog(NID_IO, "The key type is not supported.");