sync with master
[platform/core/appfw/message-port.git] / src / 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        MessagePortProxy.cpp
20  * @brief       This is the implementation file for the MessagePortProxy class.
21  *
22  */
23
24
25 #include <sys/types.h>
26 #include <unistd.h>
27 #include <sstream>
28
29 #include <package_manager.h>
30
31 #include "message-port.h"
32 #include "message-port-messages.h"
33 #include "message-port-log.h"
34
35 #include "IpcClient.h"
36 #include "MessagePortProxy.h"
37
38 using namespace std;
39
40 static const char MESSAGE_TYPE[] = "MESSAGE_TYPE";
41
42 static const char LOCAL_APPID[] = "LOCAL_APPID";
43 static const char LOCAL_PORT[] = "LOCAL_PORT";
44 static const char TRUSTED_LOCAL[] = "TRUSTED_LOCAL";
45
46 static const char REMOTE_APPID[] = "REMOTE_APPID";
47 static const char REMOTE_PORT[] = "REMOTE_PORT";
48 static const char TRUSTED_REMOTE[] = "TRUSTED_REMOTE";
49 static const char TRUSTED_MESSAGE[] = "TRUSTED_MESSAGE";
50
51 static const int MAX_MESSAGE_SIZE = 8 * 1024;
52
53 MessagePortProxy::MessagePortProxy(void)
54         : __pIpcClient(NULL)
55         , __pMutex(NULL)
56 {
57 }
58
59 MessagePortProxy::~MessagePortProxy(void)
60 {
61         pthread_mutex_destroy(__pMutex);
62 }
63
64 int
65 MessagePortProxy::Construct(void)
66 {
67         IpcClient* pIpcClient = new (std::nothrow) IpcClient();
68         if (pIpcClient == NULL)
69         {
70                 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
71         }
72
73         int ret = pIpcClient->Construct("message-port-server", this);
74         if (ret != 0)
75         {
76                 delete pIpcClient;
77
78                 _LOGE("Failed to create ipc client: %d.", ret);
79
80                 return MESSAGEPORT_ERROR_IO_ERROR;
81         }
82
83         pthread_mutex_t* pMutex = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));
84         if (pMutex == NULL)
85         {
86                 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
87         }
88
89         pthread_mutex_init(pMutex, NULL);
90
91         __pMutex = pMutex;
92         __pIpcClient = pIpcClient;
93         __appId = pIpcClient->GetAppId();
94
95         return 0;
96 }
97
98 void
99 MessagePortProxy::OnIpcResponseReceived(IpcClient& client, const IPC::Message& message)
100 {
101         _LOGD("Message received, type %d", message.type());
102
103         IPC_BEGIN_MESSAGE_MAP(MessagePortProxy, message)
104         IPC_MESSAGE_HANDLER_EX(MessagePort_sendMessageAsync, &client, OnSendMessageInternal)
105         IPC_END_MESSAGE_MAP_EX()
106 }
107
108 int
109 MessagePortProxy::RegisterMessagePort(const string& localPort, bool isTrusted,  messageport_message_cb callback)
110 {
111         _LOGD("Register a message port : [%s:%s]", __appId.c_str(), localPort.c_str());
112
113         int id = 0;
114
115         // Check the message port is already registed
116         if (IsLocalPortRegisted(localPort, isTrusted, id))
117         {
118                 if (!isTrusted)
119                 {
120                         __listeners[localPort] = callback;
121                 }
122                 else
123                 {
124                         __trustedListeners[localPort] = callback;
125                 }
126
127                 return id;
128         }
129
130         bundle *b = bundle_create();
131
132         if (!isTrusted)
133         {
134                 bundle_add(b, TRUSTED_LOCAL, "FALSE");
135         }
136         else
137         {
138                 bundle_add(b, TRUSTED_LOCAL, "TRUE");
139         }
140
141         bundle_add(b, LOCAL_APPID, __appId.c_str());
142         bundle_add(b, LOCAL_PORT, localPort.c_str());
143
144
145         // Create Bundle Buffer from bundle
146         BundleBuffer buffer;
147         buffer.b = b;
148
149         int ret = 0;
150         int return_value = 0;
151
152         IPC::Message* pMsg = new MessagePort_registerPort(buffer, &return_value);
153         if (pMsg == NULL)
154         {
155                 bundle_free(b);
156                 return  MESSAGEPORT_ERROR_OUT_OF_MEMORY;
157         }
158
159         ret = __pIpcClient->SendRequest(pMsg);
160
161         delete pMsg;
162
163         bundle_free(b);
164
165         if (ret != 0)
166         {
167                 _LOGE("Failed to send a request: %d.", ret);
168
169                 return MESSAGEPORT_ERROR_IO_ERROR;
170         }
171
172
173         // Add a listener
174         if (!isTrusted)
175         {
176                 // Local port id
177                 id = GetNextId();
178
179                 __listeners[localPort] = callback;
180                 __idFromString[localPort] = id;
181                 __ids[id] = localPort;
182         }
183         else
184         {
185                 id = GetNextId();
186
187                 __trustedListeners[localPort] = callback;
188                 __trustedIdFromString[localPort] = id;
189                 __trustedIds[id] = localPort;
190         }
191
192         return id;
193 }
194
195 int
196 MessagePortProxy::CheckRemotePort(const string& remoteAppId, const string& remotePort,  bool isTrusted, bool *exist)
197 {
198         _LOGD("Check a remote port : [%s:%s]", remoteAppId.c_str(), remotePort.c_str());
199
200         int ret = 0;
201
202         // Check the certificate
203         if (isTrusted)
204         {
205                 // Check the preloaded
206                 if (!IsPreloaded(remoteAppId))
207                 {
208                         ret = CheckCertificate(remoteAppId);
209                         if (ret < 0)
210                         {
211                                 return ret;
212                         }
213                 }
214         }
215
216         bundle *b = bundle_create();
217         bundle_add(b, REMOTE_APPID, remoteAppId.c_str());
218         bundle_add(b, REMOTE_PORT, remotePort.c_str());
219
220         if (!isTrusted)
221         {
222                 bundle_add(b, TRUSTED_REMOTE, "FALSE");
223         }
224         else
225         {
226                 bundle_add(b, TRUSTED_REMOTE, "TRUE");
227         }
228
229         // To Bundle Buffer
230         BundleBuffer buffer;
231         buffer.b = b;
232
233         int return_value = 0;
234         IPC::Message* pMsg = new MessagePort_checkRemotePort(buffer, &return_value);
235         if (pMsg == NULL)
236         {
237                 bundle_free(b);
238
239                 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
240         }
241
242         ret = __pIpcClient->SendRequest(pMsg);
243
244         delete pMsg;
245
246         bundle_free(b);
247
248         if (ret < 0)
249         {
250                 _LOGE("Failed to send a request: %d.", ret);
251
252                 return MESSAGEPORT_ERROR_IO_ERROR;
253         }
254
255         if (return_value < 0)
256         {
257                 if (return_value == MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND)
258                 {
259                         *exist = false;
260                         return 0;
261                 }
262                 else
263                 {
264                         _LOGE("Failed to check the remote messge port: %d.", return_value);
265                         return MESSAGEPORT_ERROR_IO_ERROR;
266                 }
267         }
268
269         *exist = true;
270         return 0;
271 }
272
273 int
274 MessagePortProxy::SendMessage(const string& remoteAppId, const string& remotePort, bool trustedMessage, bundle* data)
275 {
276         _LOGD("Send a message to : [%s:%s]", remoteAppId.c_str(), remotePort.c_str());
277
278         int ret = 0;
279
280         // Check the certificate
281         if (trustedMessage)
282         {
283                 // Check the preloaded
284                 if (!IsPreloaded(remoteAppId))
285                 {
286                         ret = CheckCertificate(remoteAppId);
287                         if (ret < 0)
288                         {
289                                 return ret;
290                         }
291                 }
292         }
293
294         bundle_add(data, MESSAGE_TYPE, "UNI-DIR");
295
296         bundle_add(data, REMOTE_APPID, remoteAppId.c_str());
297         bundle_add(data, REMOTE_PORT, remotePort.c_str());
298
299         if (!trustedMessage)
300         {
301                 bundle_add(data, TRUSTED_MESSAGE, "FALSE");
302         }
303         else
304         {
305                 bundle_add(data, TRUSTED_MESSAGE, "TRUE");
306         }
307
308         BundleBuffer buffer;
309         buffer.b = data;
310
311         ret = SendMessageInternal(buffer);
312
313         return ret;
314 }
315
316 int
317 MessagePortProxy::SendMessage(const string& localPort, bool trustedPort, const string& remoteAppId, const string& remotePort, bool trustedMessage, bundle* data)
318 {
319         _LOGD("Send a bidirectional message from [%s:%s] to [%s:%s]", __appId.c_str(), localPort.c_str(), remoteAppId.c_str(), remotePort.c_str());
320
321         int ret = 0;
322
323         // Check the certificate
324         if (trustedMessage)
325         {
326                 // Check the preloaded
327                 if (!IsPreloaded(remoteAppId))
328                 {
329                         ret = CheckCertificate(remoteAppId);
330                         if (ret < 0)
331                         {
332                                 return ret;
333                         }
334                 }
335         }
336
337         bundle_add(data, MESSAGE_TYPE, "BI-DIR");
338
339         bundle_add(data, LOCAL_APPID, __appId.c_str());
340         bundle_add(data, LOCAL_PORT, localPort.c_str());
341
342         if (!trustedPort)
343         {
344                 bundle_add(data, TRUSTED_LOCAL, "FALSE");
345         }
346         else
347         {
348                 bundle_add(data, TRUSTED_LOCAL, "TRUE");
349         }
350
351         bundle_add(data, REMOTE_APPID, remoteAppId.c_str());
352         bundle_add(data, REMOTE_PORT, remotePort.c_str());
353
354         if (!trustedMessage)
355         {
356                 bundle_add(data, TRUSTED_MESSAGE, "FALSE");
357         }
358         else
359         {
360                 bundle_add(data, TRUSTED_MESSAGE, "TRUE");
361         }
362
363         BundleBuffer buffer;
364         buffer.b = data;
365
366         ret = SendMessageInternal(buffer);
367
368         return ret;
369 }
370
371 int
372 MessagePortProxy::SendMessageInternal(const BundleBuffer& buffer)
373 {
374         int ret = 0;
375
376         IPC::Message* pMsg = new MessagePort_sendMessage(buffer, &ret);
377         if (pMsg == NULL)
378         {
379                 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
380         }
381
382         // Check the message size
383         int len = 0;
384         bundle_raw* raw = NULL;
385         bundle_encode(buffer.b, &raw, &len);
386
387         bundle_free_encoded_rawdata(&raw);
388
389         if (len > MAX_MESSAGE_SIZE)
390         {
391                 _LOGE("The size of message (%d) has exceeded the maximum limit.", len);
392                 return MESSAGEPORT_ERROR_MAX_EXCEEDED;
393         }
394
395         ret = __pIpcClient->SendRequest(pMsg);
396         delete pMsg;
397
398         if (ret != 0)
399         {
400                 _LOGE("Failed to send a request: %d.", ret);
401                 return MESSAGEPORT_ERROR_IO_ERROR;
402         }
403
404         return 0;
405 }
406
407 char*
408 MessagePortProxy::GetLocalPortNameN(int id)
409 {
410         string value;
411
412         map<int, std::string>::iterator it;
413
414         it = __ids.find(id);
415         if (it == __ids.end())
416         {
417                 it = __trustedIds.find(id);
418                 if (it == __ids.end())
419                 {
420                         return NULL;
421                 }
422                 else
423                 {
424                         value = __trustedIds[id];
425                         return strdup(value.c_str());
426                 }
427         }
428         else
429         {
430                 value = __ids[id];
431                 return strdup(value.c_str());
432         }
433
434         return NULL;
435 }
436
437 int
438 MessagePortProxy::CheckTrustedLocalPort(int id, bool* trusted)
439 {
440         map<int, std::string>::iterator it;
441
442         it = __ids.find(id);
443         if (it == __ids.end())
444         {
445                 it = __trustedIds.find(id);
446                 if (it == __ids.end())
447                 {
448                         return MESSAGEPORT_ERROR_INVALID_PARAMETER;
449                 }
450                 else
451                 {
452                         *trusted = true;
453                         return 0;
454                 }
455         }
456         else
457         {
458                 *trusted = false;
459                 return 0;
460         }
461
462         return MESSAGEPORT_ERROR_INVALID_PARAMETER;
463 }
464
465 MessagePortProxy*
466 MessagePortProxy::GetProxy(void)
467 {
468         static MessagePortProxy* pProxy = NULL;
469
470         if (pProxy == NULL)
471         {
472                 MessagePortProxy* p = new MessagePortProxy();
473                 if (p == NULL)
474                 {
475                         return NULL;
476                 }
477
478                 int ret = p->Construct();
479                 if (ret < 0)
480                 {
481                         return NULL;
482                 }
483
484                 pProxy = p;
485         }
486
487         return pProxy;
488 }
489
490 int
491 MessagePortProxy::GetNextId(void)
492 {
493         static int count = 0;
494
495         pthread_mutex_lock(__pMutex);
496         ++count;
497         pthread_mutex_unlock(__pMutex);
498
499         return count;
500 }
501
502 bool
503 MessagePortProxy::IsLocalPortRegisted(const string& localPort, bool trusted, int &id)
504 {
505         if (!trusted)
506         {
507                 map<string, messageport_message_cb>::iterator port_it = __listeners.find(localPort);
508                 if (port_it == __listeners.end())
509                 {
510                         return false;
511                 }
512                 else
513                 {
514                         for (map<int, string>::iterator it = __ids.begin(); it != __ids.end(); ++it)
515                         {
516                                 if (localPort.compare(it->second) == 0)
517                                 {
518                                         id = it->first;
519                                         return true;
520                                 }
521                         }
522                 }
523         }
524         else
525         {
526                 map<string, messageport_message_cb>::iterator port_it = __trustedListeners.find(localPort);
527                 if (port_it == __trustedListeners.end())
528                 {
529                         return false;
530                 }
531                 else
532                 {
533                         for (map<int, string>::iterator it = __ids.begin(); it != __trustedIds.end(); ++it)
534                         {
535                                 if (localPort.compare(it->second) == 0)
536                                 {
537                                         id = it->first;
538                                         return true;
539                                 }
540                         }
541                 }
542         }
543
544         return false;
545 }
546
547 int
548 MessagePortProxy::CheckCertificate(const std::string& remoteAppId)
549 {
550         package_manager_compare_result_type_e res;
551         int ret = package_manager_compare_app_cert_info(__appId.c_str(), remoteAppId.c_str(), &res);
552
553         if (ret == 0)
554         {
555                 if (res != PACAKGE_MANAGER_COMPARE_MATCH)
556                 {
557                         _LOGE("The remote application (%s) is not signed with the same certificate", remoteAppId.c_str());
558                         return MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH;
559                 }
560         }
561         else
562         {
563                 _LOGE("Failed to check the certificate: %d.", ret);
564                 return MESSAGEPORT_ERROR_IO_ERROR;
565         }
566
567         return 0;
568 }
569
570 bool
571 MessagePortProxy::IsPreloaded(const std::string& remoteAppId)
572 {
573         bool preload_local = false;
574         bool preload_remote = false;
575
576         if (package_manager_is_preload_package_by_app_id(__appId.c_str(), &preload_local) == 0)
577         {
578                 if (package_manager_is_preload_package_by_app_id(remoteAppId.c_str(), &preload_remote) == 0)
579                 {
580                         if (preload_local && preload_remote)
581                         {
582                                 return true;
583                         }
584                 }
585                 else
586                 {
587                         _LOGE("Failed to check the preloaded application.");
588                 }
589         }
590         else
591         {
592                 _LOGE("Failed to check the preloaded application.");
593         }
594
595         return false;
596 }
597
598 bool
599 MessagePortProxy::OnSendMessageInternal(const BundleBuffer& buffer)
600 {
601         bundle* b = buffer.b;
602
603         const char* pRemoteAppId = bundle_get_val(b, REMOTE_APPID);
604         const char* pRemotePort = bundle_get_val(b, REMOTE_PORT);
605         string trustedMessage = bundle_get_val(b, TRUSTED_MESSAGE);
606
607         string messageType = bundle_get_val(b, MESSAGE_TYPE);
608
609         _LOGD("Message received to AppId: %s, Port: %s, Trusted: %s", pRemoteAppId, pRemotePort, trustedMessage.c_str());
610
611         int id = 0;
612         messageport_message_cb callback;
613
614         if (trustedMessage.compare("FALSE") == 0)
615         {
616                 callback = __listeners[pRemotePort];
617                 id = __idFromString[pRemotePort];
618         }
619         else
620         {
621                 callback = __trustedListeners[pRemotePort];
622                 id = __trustedIdFromString[pRemotePort];
623         }
624
625
626         if (callback)
627         {
628                 // remove system data
629                 bundle_del(b, REMOTE_APPID);
630                 bundle_del(b, REMOTE_PORT);
631                 bundle_del(b, TRUSTED_MESSAGE);
632                 bundle_del(b, MESSAGE_TYPE);
633
634                 if (messageType.compare("UNI-DIR") == 0)
635                 {
636                         callback(id, NULL, NULL, false, b);
637                 }
638                 else
639                 {
640                         string localAppId = bundle_get_val(b, LOCAL_APPID);
641                         string localPort = bundle_get_val(b, LOCAL_PORT);
642                         string trustedLocal = bundle_get_val(b, TRUSTED_LOCAL);
643
644                         _LOGD("From AppId: %s, Port: %s, TrustedLocal: %s", localAppId.c_str(), localPort.c_str(), trustedLocal.c_str());
645
646                         bool trustedPort = (trustedLocal.compare("TRUE") == 0);
647
648                         // remove system data
649                         bundle_del(b, LOCAL_APPID);
650                         bundle_del(b, LOCAL_PORT);
651                         bundle_del(b, TRUSTED_LOCAL);
652
653                         callback(id, localAppId.c_str(), localPort.c_str(), trustedPort, b);
654                 }
655         }
656         else
657         {
658                 _LOGD("No callback");
659         }
660
661         return true;
662 }
663