remove message_port_unregister
[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 <app_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 = 16 * 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                 _LOGE("Out of memory");
71                 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
72         }
73
74         int ret = pIpcClient->Construct("message-port-server", this);
75         if (ret != 0)
76         {
77                 delete pIpcClient;
78
79                 _LOGE("Failed to create ipc client: %d.", ret);
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                 _LOGE("Out of memory");
87                 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
88         }
89
90         pthread_mutex_init(pMutex, NULL);
91
92         __pMutex = pMutex;
93         __pIpcClient = pIpcClient;
94
95         int pid = getpid();
96         char* pAppId = NULL;
97         ret = app_manager_get_app_id(pid, &pAppId);
98         if (ret < 0)
99         {
100                 _LOGE("Failed to get_app_id: %d", ret);
101
102                 return MESSAGEPORT_ERROR_IO_ERROR;
103         }
104
105         __appId = pAppId;
106
107         free(pAppId);
108
109         return 0;
110 }
111
112 void
113 MessagePortProxy::OnIpcResponseReceived(IpcClient& client, const IPC::Message& message)
114 {
115         IPC_BEGIN_MESSAGE_MAP(MessagePortProxy, message)
116         IPC_MESSAGE_HANDLER_EX(MessagePort_sendMessageAsync, &client, OnSendMessageInternal)
117         IPC_END_MESSAGE_MAP_EX()
118 }
119
120 int
121 MessagePortProxy::RegisterMessagePort(const string& localPort, bool isTrusted,  messageport_message_cb callback)
122 {
123         _LOGD("Register a message port : [%s:%s]", __appId.c_str(), localPort.c_str());
124
125         int id = 0;
126
127         // Check the message port is already registed
128         if (IsLocalPortRegisted(localPort, isTrusted, id))
129         {
130                 if (!isTrusted)
131                 {
132                         __listeners[localPort] = callback;
133                 }
134                 else
135                 {
136                         __trustedListeners[localPort] = callback;
137                 }
138
139                 return id;
140         }
141
142         bundle *b = bundle_create();
143
144         if (!isTrusted)
145         {
146                 bundle_add(b, TRUSTED_LOCAL, "FALSE");
147         }
148         else
149         {
150                 bundle_add(b, TRUSTED_LOCAL, "TRUE");
151         }
152
153         bundle_add(b, LOCAL_APPID, __appId.c_str());
154         bundle_add(b, LOCAL_PORT, localPort.c_str());
155
156
157         // Create Bundle Buffer from bundle
158         BundleBuffer buffer;
159         buffer.b = b;
160
161         int ret = 0;
162         int return_value = 0;
163
164         IPC::Message* pMsg = new MessagePort_registerPort(buffer, &return_value);
165         if (pMsg == NULL)
166         {
167                 bundle_free(b);
168
169                 _LOGE("Out of memory");
170                 return  MESSAGEPORT_ERROR_OUT_OF_MEMORY;
171         }
172
173         ret = __pIpcClient->SendRequest(pMsg);
174
175         delete pMsg;
176
177         bundle_free(b);
178
179         if (ret != 0)
180         {
181                 _LOGE("Failed to send a request: %d.", ret);
182
183                 return MESSAGEPORT_ERROR_IO_ERROR;
184         }
185
186         // Add a listener
187         if (!isTrusted)
188         {
189                 // Local port id
190                 id = GetNextId();
191
192                 __listeners[localPort] = callback;
193                 __idFromString[localPort] = id;
194                 __ids[id] = localPort;
195         }
196         else
197         {
198                 id = GetNextId();
199
200                 __trustedListeners[localPort] = callback;
201                 __trustedIdFromString[localPort] = id;
202                 __trustedIds[id] = localPort;
203         }
204
205         return id;
206 }
207
208 int
209 MessagePortProxy::CheckRemotePort(const string& remoteAppId, const string& remotePort,  bool isTrusted, bool *exist)
210 {
211         _LOGD("Check a remote port : [%s:%s]", remoteAppId.c_str(), remotePort.c_str());
212
213         bundle *b = bundle_create();
214
215         bundle_add(b, LOCAL_APPID, __appId.c_str());
216
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                 _LOGE("Out of memory");
240                 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
241         }
242
243         int ret = __pIpcClient->SendRequest(pMsg);
244
245         delete pMsg;
246
247         bundle_free(b);
248
249         if (ret < 0)
250         {
251                 _LOGE("Failed to send a request: %d.", ret);
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                         _LOGE("The remote message port (%s) is not found.", remotePort.c_str());
260
261                         *exist = false;
262                         return 0;
263                 }
264                 else if (return_value == MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH)
265                 {
266                         _LOGE("The remote application (%s) is not signed with the same certificate", remoteAppId.c_str());
267
268                         *exist = true;
269                         return MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH;
270                 }
271                 else
272                 {
273                         _LOGE("Failed to check the remote messge port: %d.", return_value);
274                         return MESSAGEPORT_ERROR_IO_ERROR;
275                 }
276         }
277
278         *exist = true;
279         return 0;
280 }
281
282 int
283 MessagePortProxy::SendMessage(const string& remoteAppId, const string& remotePort, bool trustedMessage, bundle* data)
284 {
285         _LOGD("Send a message to : [%s:%s]", remoteAppId.c_str(), remotePort.c_str());
286
287         int ret = 0;
288
289         bundle *b = bundle_create();
290         bundle_add(b, MESSAGE_TYPE, "UNI-DIR");
291
292         bundle_add(b, LOCAL_APPID, __appId.c_str());
293
294         bundle_add(b, REMOTE_APPID, remoteAppId.c_str());
295         bundle_add(b, REMOTE_PORT, remotePort.c_str());
296
297         if (!trustedMessage)
298         {
299                 bundle_add(b, TRUSTED_MESSAGE, "FALSE");
300         }
301         else
302         {
303                 bundle_add(b, TRUSTED_MESSAGE, "TRUE");
304         }
305
306         BundleBuffer metadata;
307         metadata.b = b;
308
309         BundleBuffer buffer;
310         buffer.b = data;
311
312         ret = SendMessageInternal(metadata, buffer);
313
314         bundle_free(b);
315
316         return ret;
317 }
318
319 int
320 MessagePortProxy::SendMessage(const string& localPort, bool trustedPort, const string& remoteAppId, const string& remotePort, bool trustedMessage, bundle* data)
321 {
322         _LOGD("Send a bidirectional message from [%s:%s] to [%s:%s]", __appId.c_str(), localPort.c_str(), remoteAppId.c_str(), remotePort.c_str());
323
324         int ret = 0;
325
326         bundle *b = bundle_create();
327         bundle_add(b, MESSAGE_TYPE, "BI-DIR");
328
329         bundle_add(b, LOCAL_APPID, __appId.c_str());
330         bundle_add(b, LOCAL_PORT, localPort.c_str());
331
332         if (!trustedPort)
333         {
334                 bundle_add(b, TRUSTED_LOCAL, "FALSE");
335         }
336         else
337         {
338                 bundle_add(b, TRUSTED_LOCAL, "TRUE");
339         }
340
341         bundle_add(b, REMOTE_APPID, remoteAppId.c_str());
342         bundle_add(b, REMOTE_PORT, remotePort.c_str());
343
344         if (!trustedMessage)
345         {
346                 bundle_add(b, TRUSTED_MESSAGE, "FALSE");
347         }
348         else
349         {
350                 bundle_add(b, TRUSTED_MESSAGE, "TRUE");
351         }
352
353         BundleBuffer metadata;
354         metadata.b = b;
355
356         BundleBuffer buffer;
357         buffer.b = data;
358
359         ret = SendMessageInternal(metadata, buffer);
360
361         bundle_free(b);
362
363         return ret;
364 }
365
366 int
367 MessagePortProxy::SendMessageInternal(const BundleBuffer& metadata, const BundleBuffer& buffer)
368 {
369         int return_value = 0;
370         IPC::Message* pMsg = new MessagePort_sendMessage(metadata, buffer, &return_value);
371         if (pMsg == NULL)
372         {
373                 _LOGE("Out of memory");
374                 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
375         }
376
377         // Check the message size
378         int len = 0;
379         bundle_raw* raw = NULL;
380         bundle_encode(buffer.b, &raw, &len);
381
382         bundle_free_encoded_rawdata(&raw);
383
384         if (len > MAX_MESSAGE_SIZE)
385         {
386                 _LOGE("The size of message (%d) has exceeded the maximum limit.", len);
387                 return MESSAGEPORT_ERROR_MAX_EXCEEDED;
388         }
389
390         int ret = __pIpcClient->SendRequest(pMsg);
391         delete pMsg;
392
393         if (ret < 0)
394         {
395                 _LOGE("Failed to send a request: %d.", ret);
396                 return MESSAGEPORT_ERROR_IO_ERROR;
397         }
398
399         if (return_value < 0)
400         {
401                 if (return_value == MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND)
402                 {
403                         _LOGE("The remote message port is not found.");
404
405                         return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
406                 }
407                 else if (return_value == MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH)
408                 {
409                         _LOGE("The remote application is not signed with the same certificate.");
410
411                         return MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH;
412                 }
413                 else
414                 {
415                         _LOGE("Failed to check the remote messge port: %d.", return_value);
416
417                         return MESSAGEPORT_ERROR_IO_ERROR;
418                 }
419         }
420
421         return 0;
422 }
423
424 char*
425 MessagePortProxy::GetLocalPortNameN(int id)
426 {
427         string value;
428
429         map<int, std::string>::iterator it;
430
431         it = __ids.find(id);
432         if (it == __ids.end())
433         {
434                 it = __trustedIds.find(id);
435                 if (it == __ids.end())
436                 {
437                         _LOGE("Invalid value %d", id);
438                         return NULL;
439                 }
440                 else
441                 {
442                         value = __trustedIds[id];
443                         return strdup(value.c_str());
444                 }
445         }
446         else
447         {
448                 value = __ids[id];
449                 return strdup(value.c_str());
450         }
451
452         return NULL;
453 }
454
455 int
456 MessagePortProxy::CheckTrustedLocalPort(int id, bool* trusted)
457 {
458         map<int, std::string>::iterator it;
459
460         it = __ids.find(id);
461         if (it == __ids.end())
462         {
463                 it = __trustedIds.find(id);
464                 if (it == __ids.end())
465                 {
466                         _LOGE("Invalid value %d", id);
467                         return MESSAGEPORT_ERROR_INVALID_PARAMETER;
468                 }
469                 else
470                 {
471                         *trusted = true;
472                         return 0;
473                 }
474         }
475         else
476         {
477                 *trusted = false;
478                 return 0;
479         }
480
481         return MESSAGEPORT_ERROR_INVALID_PARAMETER;
482 }
483
484 MessagePortProxy*
485 MessagePortProxy::GetProxy(void)
486 {
487         static MessagePortProxy* pProxy = NULL;
488
489         if (pProxy == NULL)
490         {
491                 MessagePortProxy* p = new MessagePortProxy();
492                 if (p == NULL)
493                 {
494                         _LOGE("Out of memory");
495                         return NULL;
496                 }
497
498                 int ret = p->Construct();
499                 if (ret < 0)
500                 {
501                         return NULL;
502                 }
503
504                 pProxy = p;
505         }
506
507         return pProxy;
508 }
509
510 int
511 MessagePortProxy::GetNextId(void)
512 {
513         static int count = 0;
514
515         pthread_mutex_lock(__pMutex);
516         ++count;
517         pthread_mutex_unlock(__pMutex);
518
519         return count;
520 }
521
522 bool
523 MessagePortProxy::IsLocalPortRegisted(const string& localPort, bool trusted, int &id)
524 {
525         if (!trusted)
526         {
527                 map<string, messageport_message_cb>::iterator port_it = __listeners.find(localPort);
528                 if (port_it == __listeners.end())
529                 {
530                         return false;
531                 }
532                 else
533                 {
534                         for (map<int, string>::iterator it = __ids.begin(); it != __ids.end(); ++it)
535                         {
536                                 if (localPort.compare(it->second) == 0)
537                                 {
538                                         id = it->first;
539                                         return true;
540                                 }
541                         }
542                 }
543         }
544         else
545         {
546                 map<string, messageport_message_cb>::iterator port_it = __trustedListeners.find(localPort);
547                 if (port_it == __trustedListeners.end())
548                 {
549                         return false;
550                 }
551                 else
552                 {
553                         for (map<int, string>::iterator it = __ids.begin(); it != __trustedIds.end(); ++it)
554                         {
555                                 if (localPort.compare(it->second) == 0)
556                                 {
557                                         id = it->first;
558                                         return true;
559                                 }
560                         }
561                 }
562         }
563
564         return false;
565 }
566
567 bool
568 MessagePortProxy::OnSendMessageInternal(const BundleBuffer& metadata, const BundleBuffer& buffer)
569 {
570         bundle* b = metadata.b;
571
572         const char* pRemoteAppId = bundle_get_val(b, REMOTE_APPID);
573         const char* pRemotePort = bundle_get_val(b, REMOTE_PORT);
574         string trustedMessage = bundle_get_val(b, TRUSTED_MESSAGE);
575
576         string messageType = bundle_get_val(b, MESSAGE_TYPE);
577
578         _LOGD("Message received to App: %s, Port: %s, Trusted: %s", pRemoteAppId, pRemotePort, trustedMessage.c_str());
579
580         int id = 0;
581         messageport_message_cb callback;
582
583         if (trustedMessage.compare("FALSE") == 0)
584         {
585                 callback = __listeners[pRemotePort];
586                 id = __idFromString[pRemotePort];
587         }
588         else
589         {
590                 callback = __trustedListeners[pRemotePort];
591                 id = __trustedIdFromString[pRemotePort];
592         }
593
594
595         if (callback)
596         {
597                 if (messageType.compare("UNI-DIR") == 0)
598                 {
599                         callback(id, NULL, NULL, false, buffer.b);
600                 }
601                 else
602                 {
603                         string localAppId = bundle_get_val(b, LOCAL_APPID);
604                         string localPort = bundle_get_val(b, LOCAL_PORT);
605                         string trustedLocal = bundle_get_val(b, TRUSTED_LOCAL);
606
607                         _LOGD("From App: %s, Port: %s, TrustedLocal: %s", localAppId.c_str(), localPort.c_str(), trustedLocal.c_str());
608
609                         bool trustedPort = (trustedLocal.compare("TRUE") == 0);
610
611                         callback(id, localAppId.c_str(), localPort.c_str(), trustedPort, buffer.b);
612                 }
613
614         }
615         else
616         {
617                 _LOGD("No callback");
618         }
619
620         bundle_free(b);
621
622         return true;
623 }
624