Get socket fd through AUL
[platform/core/appfw/message-port.git] / src / message-port.c
1
2 /*
3  Message Port
4  Copyright (c) 2015 Samsung Electronics Co., Ltd.
5
6  Licensed under the Apache License, Version 2.0 (the License);
7  you may not use this file except in compliance with the License.
8  You may obtain a copy of the License at
9
10      http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  See the License for the specific language governing permissions and
16  limitations under the License.
17 */
18
19 /**
20  * @file        message-port.cpp
21  * @brief       This is the implementation file for the MessagePort.
22  */
23
24 #include <sys/socket.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <glib.h>
28 #include <gio/gio.h>
29 #include <aul/aul.h>
30 #include <openssl/md5.h>
31 #include <bundle.h>
32 #include <bundle_internal.h>
33 #include <pkgmgr-info.h>
34 #include <aul.h>
35 #include <gio/gio.h>
36 #include <gio/gunixfdlist.h>
37
38 #include "message-port.h"
39 #include "message-port-log.h"
40
41 #define MAX_PACKAGE_STR_SIZE 512
42 #define MESSAGEPORT_BUS_NAME_PREFIX "org.tizen.messageport._"
43 #define MESSAGEPORT_OBJECT_PATH "/org/tizen/messageport"
44 #define MESSAGEPORT_INTERFACE_PREFIX "org.tizen.messageport._"
45
46 #define DBUS_SERVICE_DBUS "org.freedesktop.DBus"
47 #define DBUS_PATH_DBUS "/org/freedesktop/DBus"
48 #define DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
49
50 #define DBUS_RELEASE_NAME_REPLY_RELEASED        1 /* *< Service was released from the given name */
51 #define DBUS_RELEASE_NAME_REPLY_NON_EXISTENT    2 /* *< The given name does not exist on the bus */
52 #define DBUS_RELEASE_NAME_REPLY_NOT_OWNER       3 /* *< Service is not an owner of the given name */
53 #define HEADER_LEN 8
54 #define MAX_RETRY_CNT 2
55
56 #define retvm_if(expr, val, fmt, arg...) do { \
57         if (expr) { \
58                 _LOGE(fmt, ##arg); \
59                 _LOGE("(%s) -> %s() return", #expr, __func__); \
60                 return val; \
61         } \
62 } while (0)
63
64 #define retv_if(expr, val) do { \
65         if (expr) { \
66                 _LOGE("(%s) -> %s() return", #expr, __func__); \
67                 return val; \
68         } \
69 } while (0)
70
71 #define FREE_AND_NULL(ptr) do { \
72         if (ptr) { \
73                 free((void *)ptr); \
74                 ptr = NULL; \
75         } \
76 } while (0)
77
78 static bool _initialized = false;
79 static GDBusConnection *__gdbus_conn = NULL;
80 static char *__app_id;
81 static GHashTable *__local_port_info = NULL;
82 static GHashTable *__remote_port_info = NULL;;
83 static GHashTable *__sender_appid_hash = NULL;;
84 static GHashTable *__trusted_app_list_hash = NULL;
85 static const int MAX_MESSAGE_SIZE = 16 * 1024;
86
87 enum __certificate_info_type {
88         UNKNOWN = 0,
89         CERTIFICATE_MATCH,
90         CERTIFICATE_NOT_MATCH,
91 };
92
93 typedef struct message_port_pkt {
94         int len;
95         bool is_bidirection;
96         unsigned char data[1];
97 } message_port_pkt_s;
98
99 typedef struct message_port_callback_info {
100         messageport_message_cb callback;
101         int local_id;
102         char *remote_app_id;
103         char *remote_port;
104         bool is_trusted;
105 } message_port_callback_info_s;
106
107 typedef struct message_port_local_port_info {
108         messageport_message_cb callback;
109         bool is_trusted;
110         char *port_name;
111         int local_id;
112 } message_port_local_port_info_s;
113
114 typedef struct message_port_remote_port_info {
115         char *sender_id;
116         char *remote_app_id;
117         int certificate_info;
118         GList *port_list;
119 } message_port_remote_app_info_s;
120
121 typedef struct port_list_info {
122         char *port_name;
123         char *encoded_bus_name;
124         bool is_trusted;
125         int sock_pair[2];
126         int watcher_id;
127         bool exist;
128 } port_list_info_s;
129
130 static char *__get_encoded_name(const char *remote_app_id, const char *port_name, bool is_trusted)
131 {
132
133         int prefix_len = strlen(MESSAGEPORT_BUS_NAME_PREFIX);
134         int postfix_len = 1;
135         char *postfix = is_trusted ? "1" : "0";
136
137         unsigned char c[MD5_DIGEST_LENGTH] = {0};
138         char *md5_interface = NULL;
139         char *temp;
140         int index = 0;
141         MD5_CTX mdContext;
142         int encoded_bus_name_len = prefix_len + postfix_len + (MD5_DIGEST_LENGTH * 2) + 2;
143         int bus_name_len = strlen(remote_app_id) + strlen(port_name) + 2;
144         char *bus_name = (char *)calloc(bus_name_len, sizeof(char));
145         if (bus_name == NULL) {
146                 _LOGE("bus_name calloc failed");
147                 return 0;
148         }
149
150         snprintf(bus_name, bus_name_len, "%s_%s", remote_app_id, port_name);
151
152         MD5_Init(&mdContext);
153         MD5_Update(&mdContext, bus_name, bus_name_len);
154         MD5_Final(c, &mdContext);
155
156         md5_interface = (char *)calloc(encoded_bus_name_len , sizeof(char));
157         if (md5_interface == NULL) {
158                 if (bus_name)
159                         free(bus_name);
160
161                 _LOGE("md5_interface calloc failed!!");
162                 return 0;
163         }
164
165         snprintf(md5_interface, encoded_bus_name_len, "%s", MESSAGEPORT_BUS_NAME_PREFIX);
166         temp = md5_interface;
167         temp += prefix_len;
168
169         for (index = 0; index < MD5_DIGEST_LENGTH; index++) {
170                 snprintf(temp, 3, "%02x", c[index]);
171                 temp += 2;
172         }
173
174         if (postfix && postfix_len > 0)
175                 snprintf(temp, encoded_bus_name_len - (temp - md5_interface), "%s", postfix);
176         if (bus_name)
177                 free(bus_name);
178
179         _LOGI("encoded_bus_name : %s ", md5_interface);
180
181         return md5_interface;
182 }
183
184 static int __remote_port_compare_cb(gconstpointer a, gconstpointer b)
185 {
186         port_list_info_s *key1 = (port_list_info_s *)a;
187         port_list_info_s *key2 = (port_list_info_s *)b;
188
189         if (key1->is_trusted == key2->is_trusted)
190                 return strcmp(key1->port_name, key2->port_name);
191
192         return 1;
193 }
194
195
196 static bool __is_preloaded(const char *local_appid, const char *remote_appid)
197 {
198         _LOGI("IsPreloaded");
199
200         bool preload_local = false;
201         bool preload_remote = false;
202
203         pkgmgrinfo_appinfo_h handle = NULL;
204         int ret = pkgmgrinfo_appinfo_get_usr_appinfo(local_appid, getuid(), &handle);
205         if (ret != PMINFO_R_OK) {
206                 _LOGE("Failed to get the appinfo. %d", ret);
207                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
208                 return false;
209         }
210         ret = pkgmgrinfo_appinfo_is_preload(handle, &preload_local);
211         if (ret != PMINFO_R_OK) {
212                 _LOGE("Failed to check the preloaded application. %d", ret);
213                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
214                 return false;
215         }
216         ret = pkgmgrinfo_appinfo_get_usr_appinfo(remote_appid, getuid(), &handle);
217         if (ret != PMINFO_R_OK) {
218                 _LOGE("Failed to get the appinfo. %d", ret);
219                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
220                 return false;
221         }
222         ret = pkgmgrinfo_appinfo_is_preload(handle, &preload_remote);
223         if (ret != PMINFO_R_OK) {
224                 _LOGE("Failed to check the preloaded application. %d", ret);
225                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
226                 return false;
227         }
228
229         if (preload_local && preload_remote) {
230                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
231                 return true;
232         }
233         pkgmgrinfo_appinfo_destroy_appinfo(handle);
234         return false;
235 }
236
237 static int __check_certificate(const char *local_appid, const char *remote_appid)
238 {
239         _LOGI("CheckCertificate");
240
241         pkgmgrinfo_cert_compare_result_type_e res;
242         int ret = pkgmgrinfo_pkginfo_compare_usr_app_cert_info(local_appid, remote_appid, getuid(), &res);
243         if (ret < 0) {
244                 _LOGE(":CheckCertificate() Failed");
245                 return MESSAGEPORT_ERROR_IO_ERROR;
246         }
247         if (res != PMINFO_CERT_COMPARE_MATCH) {
248                 _LOGE("CheckCertificate() Failed : MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH");
249                 return MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH;
250         }
251
252         return MESSAGEPORT_ERROR_NONE;
253 }
254
255 static void on_name_appeared(GDBusConnection *connection,
256                 const gchar     *name,
257                 const gchar     *name_owner,
258                 gpointer         user_data)
259 {
260         _LOGI("name appeared : %s %s", __app_id, name);
261 }
262
263 static void on_name_vanished(GDBusConnection *connection,
264                 const gchar     *name,
265                 gpointer         user_data)
266 {
267         _LOGI("name vanished : %s", name);
268         port_list_info_s *pli = (port_list_info_s *)user_data;
269         g_bus_unwatch_name(pli->watcher_id);
270         pli->exist = false;
271 }
272
273 static int __get_local_port_info(int id, message_port_local_port_info_s **info)
274 {
275         message_port_local_port_info_s *mi = (message_port_local_port_info_s *)g_hash_table_lookup(__local_port_info, GINT_TO_POINTER(id));
276
277         if (mi == NULL)
278                 return MESSAGEPORT_ERROR_INVALID_PARAMETER;
279         *info = mi;
280
281         return MESSAGEPORT_ERROR_NONE;
282 }
283
284 static port_list_info_s *__set_remote_port_info(const char *remote_app_id, const char *remote_port, bool is_trusted)
285 {
286         int ret_val = MESSAGEPORT_ERROR_NONE;
287         port_list_info_s *port_info = (port_list_info_s *)calloc(1, sizeof(port_list_info_s));
288
289         if (!port_info) {
290                 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
291                 goto out;
292         }
293         port_info->port_name = strdup(remote_port);
294         if (!port_info->port_name) {
295                 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
296                 goto out;
297         }
298         port_info->is_trusted = is_trusted;
299
300         port_info->encoded_bus_name = __get_encoded_name(remote_app_id, remote_port, is_trusted);
301         if (port_info->encoded_bus_name == NULL) {
302                 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
303                 goto out;
304         }
305
306         port_info->sock_pair[0] = 0;
307         port_info->sock_pair[1] = 0;
308
309 out:
310         if (ret_val != MESSAGEPORT_ERROR_NONE) {
311                 if (port_info) {
312                         FREE_AND_NULL(port_info->port_name);
313                         FREE_AND_NULL(port_info->encoded_bus_name);
314                         free(port_info);
315                 }
316                 return NULL;
317         }
318         return port_info;
319 }
320
321 static message_port_remote_app_info_s *__set_remote_app_info(const char *remote_app_id, const char *remote_port, bool is_trusted)
322 {
323         port_list_info_s *port_info = NULL;
324         message_port_remote_app_info_s *remote_app_info = NULL;
325         int ret_val = MESSAGEPORT_ERROR_NONE;
326
327         remote_app_info = (message_port_remote_app_info_s *)calloc(1, sizeof(message_port_remote_app_info_s));
328         if (!remote_app_info) {
329                 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
330                 goto out;
331         }
332
333         remote_app_info->remote_app_id = strdup(remote_app_id);
334         if (remote_app_info->remote_app_id == NULL) {
335                 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;;
336                 goto out;
337         }
338
339         port_info = __set_remote_port_info(remote_app_id, remote_port, is_trusted);
340         if (port_info == NULL) {
341                 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
342                 goto out;
343         }
344
345         remote_app_info->port_list = g_list_append(remote_app_info->port_list, port_info);
346
347 out:
348         if (ret_val != MESSAGEPORT_ERROR_NONE) {
349                 if (remote_app_info) {
350                         FREE_AND_NULL(remote_app_info->remote_app_id);
351                         FREE_AND_NULL(remote_app_info);
352                 }
353                 return NULL;
354         }
355         return remote_app_info;
356 }
357
358 static int __get_remote_port_info(const char *remote_app_id, const char *remote_port, bool is_trusted,
359                 message_port_remote_app_info_s **mri, port_list_info_s **pli)
360 {
361         message_port_remote_app_info_s *remote_app_info = NULL;
362         port_list_info_s port_info;
363         GList *cb_list = NULL;
364         int ret_val = MESSAGEPORT_ERROR_NONE;
365
366         remote_app_info = (message_port_remote_app_info_s *)g_hash_table_lookup(__remote_port_info, remote_app_id);
367
368         if (remote_app_info == NULL) {
369                 remote_app_info = __set_remote_app_info(remote_app_id, remote_port, is_trusted);
370
371                 if (remote_app_info == NULL) {
372                         ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
373                         goto out;
374                 }
375                 g_hash_table_insert(__remote_port_info, remote_app_info->remote_app_id, remote_app_info);
376
377         }
378         *mri = remote_app_info;
379
380         port_info.port_name = strdup(remote_port);
381         port_info.is_trusted = is_trusted;
382         cb_list = g_list_find_custom(remote_app_info->port_list, &port_info,
383                                         (GCompareFunc)__remote_port_compare_cb);
384         if (port_info.port_name)
385                 free(port_info.port_name);
386         if (cb_list == NULL) {
387                 port_list_info_s *tmp = __set_remote_port_info(remote_app_id, remote_port, is_trusted);
388
389                 if (tmp == NULL) {
390                         ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
391                         goto out;
392                 }
393                 remote_app_info->port_list = g_list_append(remote_app_info->port_list, tmp);
394                 *pli = tmp;
395                 g_hash_table_insert(__remote_port_info, (*pli)->encoded_bus_name, *pli);
396         } else {
397                 *pli = (port_list_info_s *)cb_list->data;
398         }
399
400 out:
401
402         return ret_val;
403 }
404
405 static bool __is_local_port_registed(const char *local_port, bool trusted, int *local_id, message_port_local_port_info_s **lpi)
406 {
407         GHashTableIter iter;
408         gpointer key, value;
409
410         g_hash_table_iter_init(&iter, __local_port_info);
411
412         while (g_hash_table_iter_next(&iter, &key, &value)) {
413                 message_port_local_port_info_s *mi = (message_port_local_port_info_s *)value;
414
415                 if ((mi->is_trusted == trusted) && strcmp(mi->port_name, local_port) == 0) {
416                         *local_id = mi->local_id;
417                         if (lpi != NULL)
418                                 *lpi = mi;
419                         return true;
420                 }
421         }
422         return false;
423 }
424
425 static int __get_sender_pid(GDBusConnection *conn, const char *sender_name)
426 {
427         GDBusMessage *msg = NULL;
428         GDBusMessage *reply = NULL;
429         GError *err = NULL;
430         GVariant *body;
431         int pid = 0;
432
433         msg = g_dbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
434                         "org.freedesktop.DBus", "GetConnectionUnixProcessID");
435         if (!msg) {
436                 _LOGE("Can't allocate new method call");
437                 goto out;
438         }
439
440         g_dbus_message_set_body(msg, g_variant_new("(s)", sender_name));
441         reply = g_dbus_connection_send_message_with_reply_sync(conn, msg,
442                                                         G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err);
443
444         if (!reply) {
445                 if (err != NULL) {
446                         _LOGE("Failed to get pid [%s]", err->message);
447                         g_error_free(err);
448                 }
449                 goto out;
450         }
451
452         body = g_dbus_message_get_body(reply);
453         g_variant_get(body, "(u)", &pid);
454
455 out:
456         if (msg)
457                 g_object_unref(msg);
458         if (reply)
459                 g_object_unref(reply);
460
461         return pid;
462 }
463
464 message_port_pkt_s *__message_port_recv_raw(int fd)
465 {
466         int len;
467         int ret;
468         message_port_pkt_s *pkt = NULL;
469
470         pkt = (message_port_pkt_s *)calloc(sizeof(char) * MAX_MESSAGE_SIZE, 1);
471         if (pkt == NULL) {
472                 close(fd);
473                 return NULL;
474         }
475
476 retry_recv:
477         /*  receive single packet from socket */
478         len = recv(fd, pkt, MAX_MESSAGE_SIZE, 0);
479         if (len < 0) {
480                 _LOGE("recv error: %d[%s]", errno, strerror(errno));
481                 if (errno == EINTR)
482                         goto retry_recv;
483         }
484
485         if (len < HEADER_LEN) {
486                 _LOGE("recv error %d %d", len, pkt->len);
487                 free(pkt);
488                 close(fd);
489                 return NULL;
490         }
491         while (len < (pkt->len + HEADER_LEN)) {
492 retry_recv1:
493                 ret = recv(fd, &pkt->data[len - 8], MAX_MESSAGE_SIZE, 0);
494                 if (ret < 0) {
495                         SECURE_LOGE("recv error: %d %d %d", errno, len, pkt->len);
496                         if (errno == EINTR)
497                                 goto retry_recv1;
498                         free(pkt);
499                         close(fd);
500                         return NULL;
501                 }
502                 len += ret;
503         }
504         return pkt;
505 }
506
507 static gboolean __socket_request_handler(GIOChannel *gio,
508                 GIOCondition cond,
509                 gpointer data)
510 {
511         int fd = 0;
512         message_port_callback_info_s *mi;
513         message_port_pkt_s *pkt;
514         bundle *kb = NULL;
515         bool is_bidirection;
516         GError *error = NULL;
517
518         if (cond == G_IO_HUP) {
519
520                 _LOGI("socket G_IO_HUP");
521                 g_io_channel_shutdown(gio, FALSE, &error);
522                 if (error) {
523                         _LOGE("g_io_channel_shutdown error : %s", error->message);
524                         g_error_free(error);
525                 }
526                 g_io_channel_unref(gio);
527                 if (data)
528                         g_free(data);
529         } else {
530
531                 if ((fd = g_io_channel_unix_get_fd(gio)) < 0) {
532                         _LOGE("fail to get fd from io channel");
533                         return TRUE;
534                 }
535
536                 mi = (message_port_callback_info_s *)data;
537
538                 if ((pkt = __message_port_recv_raw(fd)) == NULL) {
539                         _LOGE("recv error on SOCKET");
540                         close(fd);
541                         return FALSE;
542                 }
543                 kb = bundle_decode(pkt->data, pkt->len);
544                 is_bidirection = pkt->is_bidirection;
545
546                 if (is_bidirection)
547                         mi->callback(mi->local_id, mi->remote_app_id, mi->remote_port, mi->is_trusted, kb, NULL);
548                 else
549                         mi->callback(mi->local_id, mi->remote_app_id, NULL, mi->is_trusted, kb, NULL);
550
551                 if (pkt)
552                         free(pkt);
553         }
554
555         return TRUE;
556 }
557
558 static bool send_message(GVariant *parameters, GDBusMethodInvocation *invocation)
559 {
560         char *local_port = NULL;
561         char *local_appid = NULL;
562         char *remote_appid = NULL;
563         char *remote_port = NULL;
564         gboolean local_trusted = false;
565         gboolean remote_trusted = false;
566         gboolean bi_dir = false;
567         int len = 0;
568
569         bundle *data = NULL;
570         bundle_raw *raw = NULL;
571         message_port_local_port_info_s *mi;
572         message_port_callback_info_s *callback_info;
573         int local_reg_id = 0;
574
575         g_variant_get(parameters, "(ssbbssbus)", &local_appid, &local_port, &local_trusted, &bi_dir,
576                         &remote_appid, &remote_port, &remote_trusted, &len, &raw);
577
578         if (!remote_port) {
579                 _LOGE("Invalid argument : remote_port is NULL");
580                 goto out;
581         }
582         if (!remote_appid) {
583                 _LOGE("Invalid argument : remote_appid is NULL");
584                 goto out;
585         }
586         if (!__is_local_port_registed(remote_port, remote_trusted, &local_reg_id, &mi)) {
587                 _LOGE("Invalid argument : remote_port:(%s) trusted(%d)", remote_port, remote_trusted);
588                 goto out;
589         }
590         if (!local_appid) {
591                 _LOGE("Invalid argument : local_appid");
592                 goto out;
593         }
594         if (!local_port) {
595                 _LOGE("Invalid argument : local_port");
596                 goto out;
597         }
598         if (strcmp(remote_appid, __app_id) != 0) {
599                 _LOGE("Invalid argument : remote_appid (%s)", remote_appid);
600                 goto out;
601         }
602         if (strcmp(remote_port, mi->port_name) != 0) {
603                 _LOGE("Invalid argument : remote_port (%s)", remote_port);
604                 goto out;
605         }
606         if (!len) {
607                 _LOGE("Invalid argument : data_len");
608                 goto out;
609         }
610         if (remote_trusted) {
611                 if (g_hash_table_lookup(__trusted_app_list_hash, (gpointer)local_appid) == NULL) {
612                         if (!__is_preloaded(local_appid, remote_appid)) {
613                                 /* Check the certificate */
614                                 int ret = __check_certificate(local_appid, remote_appid);
615                                 if (ret == MESSAGEPORT_ERROR_NONE)
616                                         g_hash_table_insert(__trusted_app_list_hash, local_appid, "TRUE");
617                                 else {
618                                         _LOGE("The application (%s) is not signed with the same certificate",
619                                                         local_appid);
620                                         goto out;
621                                 }
622                         }
623                 }
624         }
625
626         callback_info = (message_port_callback_info_s *)calloc(1, sizeof(message_port_callback_info_s));
627         if (callback_info == NULL)
628                 goto out;
629
630         callback_info->local_id = mi->local_id;
631         callback_info->remote_app_id = strdup(local_appid);
632         callback_info->remote_port = strdup(local_port);
633         callback_info->is_trusted = local_trusted;
634         callback_info->callback = mi->callback;
635
636
637         GError *error = NULL;
638         GDBusMessage *msg = g_dbus_method_invocation_get_message(invocation);
639
640         GUnixFDList *fd_list = g_dbus_message_get_unix_fd_list(msg);
641         int fd = g_unix_fd_list_get(fd_list, 0, &error);
642         if (error) {
643                 LOGE("g_unix_fd_list_get fail : %s", error->message);
644                 g_error_free(error);
645         }
646
647         LOGI("g_unix_fd_list_get fd: [%d]", fd);
648
649         if (fd > 0) {
650
651                 GIOChannel *gio_read = NULL;
652                 gio_read = g_io_channel_unix_new(fd);
653                 if (!gio_read) {
654                         _LOGE("Error is %s\n", strerror(errno));
655                         return -1;
656                 }
657
658                 int g_src_id = g_io_add_watch(gio_read, G_IO_IN | G_IO_HUP,
659                                 __socket_request_handler, (gpointer)callback_info);
660                 if (g_src_id == 0) {
661                         _LOGE("fail to add watch on socket");
662                         return -1;
663                 }
664
665         }
666
667         data = bundle_decode(raw, len);
668         bundle_free_encoded_rawdata(&raw);
669
670         if (!data) {
671                 _LOGE("Invalid argument : message");
672                 goto out;
673         }
674
675         LOGI("call calback %s", local_appid);
676         if (bi_dir)
677                 mi->callback(mi->local_id, local_appid, local_port, local_trusted, data, NULL);
678         else
679                 mi->callback(mi->local_id, local_appid, NULL, false, data, NULL);
680
681
682 out:
683
684         return true;
685 }
686
687 static int __check_remote_port(const char *remote_app_id, const char *remote_port, bool is_trusted, bool *exist)
688 {
689         _LOGI("Check a remote port : [%s:%s]", remote_app_id, remote_port);
690
691         GVariant *result = NULL;
692         GError *err = NULL;
693         int ret_val = MESSAGEPORT_ERROR_NONE;
694         char *bus_name = NULL;
695         message_port_remote_app_info_s *remote_app_info = NULL;
696         port_list_info_s *port_info = NULL;
697         int local_reg_id = 0;
698         message_port_local_port_info_s *mi = NULL;
699         gboolean name_exist = false;
700
701         _LOGI("remote_app_id, app_id :[%s : %s] ", remote_app_id, __app_id);
702
703         ret_val = __get_remote_port_info(remote_app_id, remote_port, is_trusted, &remote_app_info, &port_info);
704         if (ret_val != MESSAGEPORT_ERROR_NONE)
705                 return ret_val;
706
707
708         /* self check */
709         if (strcmp(remote_app_id, __app_id) == 0) {
710
711                 _LOGI("__is_local_port_registed ");
712                 if (!__is_local_port_registed(remote_port, is_trusted, &local_reg_id, &mi))
713                         *exist = false;
714                 else
715                         *exist = true;
716
717                 _LOGI("__is_local_port_registed : %d ", *exist);
718                 return MESSAGEPORT_ERROR_NONE;
719         }
720
721         port_info->exist = false;
722         bus_name = port_info->encoded_bus_name;
723
724         result = g_dbus_connection_call_sync(
725                         __gdbus_conn,
726                         DBUS_SERVICE_DBUS,
727                         DBUS_PATH_DBUS,
728                         DBUS_INTERFACE_DBUS,
729                         "NameHasOwner",
730                         g_variant_new("(s)", bus_name),
731                         G_VARIANT_TYPE("(b)"),
732                         G_DBUS_CALL_FLAGS_NONE,
733                         -1,
734                         NULL,
735                         &err);
736
737         if (err || (result == NULL)) {
738                 if (err) {
739                         _LOGE("No reply. error = %s", err->message);
740                         g_error_free(err);
741                 }
742                 ret_val = MESSAGEPORT_ERROR_RESOURCE_UNAVAILABLE;
743         } else {
744                 g_variant_get(result, "(b)", &name_exist);
745
746                 if (!name_exist) {
747                         LOGE("Name not exist %s", bus_name);
748                         *exist = false;
749                         ret_val = MESSAGEPORT_ERROR_NONE;
750                 } else {
751
752                         if (is_trusted) {
753                                 if (remote_app_info->certificate_info != CERTIFICATE_MATCH) {
754                                         if (!__is_preloaded(__app_id, remote_app_id)) {
755                                                 if (__check_certificate(__app_id, remote_app_id) != MESSAGEPORT_ERROR_NONE) {
756                                                         ret_val = MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH;
757                                                         goto out;
758                                                 }
759                                         }
760                                         remote_app_info->certificate_info = CERTIFICATE_MATCH;
761                                 }
762                         }
763
764                         port_info->watcher_id = g_bus_watch_name_on_connection(
765                                         __gdbus_conn,
766                                         port_info->encoded_bus_name,
767                                         G_BUS_NAME_WATCHER_FLAGS_NONE,
768                                         on_name_appeared,
769                                         on_name_vanished,
770                                         port_info,
771                                         NULL);
772
773                         port_info->exist = true;
774                         *exist = true;
775                         ret_val = MESSAGEPORT_ERROR_NONE;
776                         _LOGI("Exist port: %s", bus_name);
777                 }
778
779         }
780 out:
781         if (result)
782                 g_variant_unref(result);
783
784         return ret_val;
785 }
786
787 static bool __check_sender_validation(GVariant *parameters, const char *sender, GDBusConnection *conn)
788 {
789         int ret = 0;
790         char buffer[MAX_PACKAGE_STR_SIZE] = {0, };
791         char *local_appid = NULL;
792         int pid = __get_sender_pid(conn, sender);
793
794         ret = aul_app_get_appid_bypid(pid, buffer, sizeof(buffer));
795         retvm_if(ret != AUL_R_OK, false, "Failed to get the sender ID: (%s) (%d)", sender, pid);
796
797         g_variant_get_child(parameters, 0, "s", &local_appid);
798         retvm_if(!local_appid, false, "remote_appid is NULL (%s) (%d)", sender, pid);
799
800         if (strncmp(buffer, local_appid, MAX_PACKAGE_STR_SIZE) == 0) {
801                 g_hash_table_insert(__sender_appid_hash, strdup(sender), GINT_TO_POINTER(pid));
802                 g_free(local_appid);
803         } else {
804                 g_free(local_appid);
805                 return false;
806         }
807         return true;
808 }
809
810 static void __dbus_method_call_handler(GDBusConnection *conn,
811                                 const gchar *sender, const gchar *object_path,
812                                 const gchar *iface_name, const gchar *method_name,
813                                 GVariant *parameters, GDBusMethodInvocation *invocation,
814                                 gpointer user_data)
815 {
816         _LOGI("method_name: %s", method_name);
817         gpointer sender_pid = g_hash_table_lookup(__sender_appid_hash, sender);
818         if (sender_pid == NULL) {
819                 if (!__check_sender_validation(parameters, sender, conn))
820                         return;
821         }
822
823         if (g_strcmp0(method_name, "send_message") == 0)
824                 send_message(parameters, invocation);
825
826 }
827
828 static const GDBusInterfaceVTable interface_vtable = {
829         __dbus_method_call_handler,
830         NULL,
831         NULL
832 };
833
834 static int __dbus_init(void)
835 {
836         bool ret = false;
837         GError *error = NULL;
838
839         __gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
840         if (__gdbus_conn == NULL) {
841                 if (error != NULL) {
842                         _LOGE("Failed to get dbus [%s]", error->message);
843                         g_error_free(error);
844                 }
845                 goto out;
846         }
847
848         ret = true;
849
850 out:
851         if (!__gdbus_conn)
852                 g_object_unref(__gdbus_conn);
853
854         return ret;
855
856 }
857
858
859 int __register_dbus_interface(const char *port_name, bool is_trusted)
860 {
861
862         GDBusNodeInfo *introspection_data = NULL;
863         int registration_id = 0;
864
865         static gchar introspection_prefix[] =
866                 "<node>"
867                 "  <interface name='";
868
869         static gchar introspection_postfix[] =
870                 "'>"
871                 "        <method name='send_message'>"
872                 "          <arg type='s' name='local_appid' direction='in'/>"
873                 "          <arg type='s' name='local_port' direction='in'/>"
874                 "          <arg type='b' name='local_trusted' direction='in'/>"
875                 "          <arg type='b' name='bi_dir' direction='in'/>"
876                 "          <arg type='s' name='remote_appid' direction='in'/>"
877                 "          <arg type='s' name='remote_port' direction='in'/>"
878                 "          <arg type='b' name='remote_trusted' direction='in'/>"
879                 "          <arg type='u' name='data_len' direction='in'/>"
880                 "          <arg type='s' name='data' direction='in'/>"
881                 "        </method>"
882                 "  </interface>"
883                 "</node>";
884
885         char *introspection_xml = NULL;
886         int introspection_xml_len = 0;
887
888
889         int owner_id = 0;
890         GError *error = NULL;
891         char *bus_name = NULL;
892         char *interface_name = NULL;
893         GVariant *result = NULL;
894
895         bus_name = __get_encoded_name(__app_id, port_name, is_trusted);
896         if (!bus_name) {
897                 _LOGE("Fail to get bus name");
898                 goto out;
899         }
900         interface_name = bus_name;
901
902         introspection_xml_len = strlen(introspection_prefix) + strlen(interface_name) +
903                 strlen(introspection_postfix) + 1;
904
905         introspection_xml = (char *)calloc(introspection_xml_len, sizeof(char));
906         if (!introspection_xml) {
907                 _LOGE("out of memory");
908                 goto out;
909         }
910
911
912         result = g_dbus_connection_call_sync(
913                         __gdbus_conn,
914                         DBUS_SERVICE_DBUS,
915                         DBUS_PATH_DBUS,
916                         DBUS_INTERFACE_DBUS,
917                         "RequestName",
918                         g_variant_new("(su)", bus_name, G_BUS_NAME_OWNER_FLAGS_NONE),
919                         G_VARIANT_TYPE("(u)"),
920                         G_DBUS_CALL_FLAGS_NONE,
921                         -1,
922                         NULL,
923                         &error);
924         if (error) {
925                 _LOGE("RequestName fail : %s", error->message);
926                 goto out;
927         }
928         if (result == NULL) {
929                 _LOGE("fail to get name NULL");
930                 goto out;
931         }
932         g_variant_get(result, "(u)", &owner_id);
933         if (owner_id == 0) {
934                 _LOGE("Acquiring the own name is failed");
935                 goto out;
936         }
937
938         _LOGI("Acquiring the own name : %d", owner_id);
939
940         snprintf(introspection_xml, introspection_xml_len, "%s%s%s", introspection_prefix, interface_name, introspection_postfix);
941
942         introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
943         if (!introspection_data) {
944                 _LOGE("g_dbus_node_info_new_for_xml() is failed.");
945                 goto out;
946         }
947
948         registration_id = g_dbus_connection_register_object(__gdbus_conn,
949                                                 MESSAGEPORT_OBJECT_PATH, introspection_data->interfaces[0],
950                                                 &interface_vtable, NULL, NULL, NULL);
951
952         _LOGI("registration_id %d", registration_id);
953
954         if (registration_id == 0) {
955                 _LOGE("Failed to g_dbus_connection_register_object");
956                 goto out;
957         }
958
959 out:
960         if (introspection_data)
961                 g_dbus_node_info_unref(introspection_data);
962         if (introspection_xml)
963                 free(introspection_xml);
964         if (bus_name)
965                 free(bus_name);
966         if (result)
967                 g_variant_unref(result);
968
969
970         return registration_id;
971 }
972
973
974 void __list_free_port_list(gpointer data)
975 {
976         port_list_info_s *n = (port_list_info_s *)data;
977
978         FREE_AND_NULL(n->encoded_bus_name);
979         FREE_AND_NULL(n->port_name);
980         FREE_AND_NULL(n);
981 }
982
983 static void __hash_destory_local_value(gpointer data)
984 {
985         message_port_local_port_info_s *mli = (message_port_local_port_info_s *)data;
986         if (mli->port_name)
987                 free(mli->port_name);
988 }
989 static void __hash_destory_remote_value(gpointer data)
990 {
991         message_port_remote_app_info_s *mri = (message_port_remote_app_info_s *)data;
992
993         if (mri) {
994                 FREE_AND_NULL(mri->sender_id);
995                 FREE_AND_NULL(mri->remote_app_id);
996                 if (mri->port_list)
997                         g_list_free_full(mri->port_list, __list_free_port_list);
998         }
999 }
1000
1001 static bool __initialize(void)
1002 {
1003
1004 #if !GLIB_CHECK_VERSION(2, 35, 0)
1005         g_type_init();
1006 #endif
1007
1008         int pid = getpid();
1009         int ret = 0;
1010         char buffer[MAX_PACKAGE_STR_SIZE] = {0, };
1011
1012         _LOGI("initialize");
1013         ret = aul_app_get_appid_bypid(pid, buffer, sizeof(buffer));
1014         retvm_if(ret != AUL_R_OK, false, "Failed to get the application ID: %d", ret);
1015
1016         __app_id = strdup(buffer);
1017         retvm_if(!__app_id, false, "Malloc failed");
1018         _LOGI("init : %s", __app_id);
1019
1020         if (__local_port_info == NULL) {
1021                 __local_port_info = g_hash_table_new_full(g_direct_hash,  g_direct_equal, NULL, __hash_destory_local_value);
1022                 retvm_if(!__local_port_info, false, "fail to create __local_port_info");
1023         }
1024
1025         if (__remote_port_info == NULL) {
1026                 __remote_port_info = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, __hash_destory_remote_value);
1027                 retvm_if(!__remote_port_info, false, "fail to create __remote_port_info");
1028         }
1029
1030         if (__sender_appid_hash == NULL) {
1031                 __sender_appid_hash = g_hash_table_new(g_str_hash, g_str_equal);
1032                 retvm_if(!__sender_appid_hash, false, "fail to create __sender_appid_hash");
1033         }
1034
1035         if (__trusted_app_list_hash == NULL) {
1036                 __trusted_app_list_hash = g_hash_table_new(g_str_hash, g_str_equal);
1037                 retvm_if(!__trusted_app_list_hash, false, "fail to create __trusted_app_list_hash");
1038         }
1039
1040         if (!__dbus_init())
1041                 return false;
1042         _initialized = true;
1043
1044         return true;
1045 }
1046
1047
1048 static bool __message_port_register_port(const int local_id, const char *local_port, bool is_trusted, messageport_message_cb callback)
1049 {
1050         message_port_local_port_info_s *mi = (message_port_local_port_info_s *)calloc(1, sizeof(message_port_local_port_info_s));
1051         retvm_if(!mi, false, "Malloc failed");
1052
1053         mi->callback = callback;
1054         mi->is_trusted = is_trusted;
1055         mi->port_name = strdup(local_port);
1056         if (mi->port_name == NULL) {
1057                 _LOGE("Malloc failed (%s)", local_port);
1058                 free(mi);
1059                 return false;
1060         }
1061         mi->local_id = local_id;
1062
1063         g_hash_table_insert(__local_port_info, GINT_TO_POINTER(mi->local_id), mi);
1064         return true;
1065 }
1066
1067 static int __register_message_port(const char *local_port, bool is_trusted, messageport_message_cb callback)
1068 {
1069         _SECURE_LOGI("Register a message port : [%s:%s]", __app_id, local_port);
1070
1071         int local_id = 0;
1072
1073         /* Check the message port is already registed */
1074         if (__is_local_port_registed(local_port, is_trusted, &local_id, NULL))
1075                 return local_id;
1076
1077         local_id = __register_dbus_interface(local_port, is_trusted);
1078         if (local_id < 1) {
1079                 _LOGE("register_dbus_interface fail !!");
1080                 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1081         }
1082
1083         if (!__message_port_register_port(local_id, local_port, is_trusted, callback))
1084                 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1085
1086         return local_id;
1087 }
1088
1089 int __message_port_send_async(int sockfd, bundle *kb, const char *app_id, const char *local_port,
1090                 bool local_trusted, bool is_bidirection)
1091 {
1092
1093         int len;
1094         int ret = 0;
1095         message_port_pkt_s *pkt = NULL;
1096         int pkt_size;
1097
1098         int datalen;
1099         bundle_raw *kb_data = NULL;
1100
1101         bundle_encode(kb, &kb_data, &datalen);
1102         if (kb_data == NULL) {
1103                 _LOGE("bundle encode fail");
1104                 ret = MESSAGEPORT_ERROR_IO_ERROR;
1105                 goto out;
1106         }
1107
1108         if (datalen > MAX_MESSAGE_SIZE - HEADER_LEN) {
1109                 _LOGE("bigger than max size\n");
1110                 ret = MESSAGEPORT_ERROR_MAX_EXCEEDED;
1111                 goto out;
1112         }
1113
1114         pkt_size = datalen + 9;
1115         pkt = (message_port_pkt_s *) malloc(sizeof(char) * pkt_size);
1116
1117         if (NULL == pkt) {
1118                 _LOGE("Malloc Failed!");
1119                 ret = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1120                 goto out;
1121         }
1122         memset(pkt, 0, pkt_size);
1123
1124         pkt->len = datalen;
1125         pkt->is_bidirection = is_bidirection;
1126
1127         memcpy(pkt->data, kb_data, datalen);
1128
1129         int retry_ctr = MAX_RETRY_CNT;
1130
1131 retry_send:
1132         if ((len = send(sockfd, pkt, pkt_size, 0)) != pkt_size) {
1133                 SECURE_LOGE("send() failed - len[%d] pkt_size[%d] (errno %d[%s])", len, pkt_size,
1134                                 errno, strerror(errno));
1135                 if (errno == EPIPE)
1136                         _LOGE("fd:%d\n", sockfd);
1137
1138                 if (errno == EINTR) {
1139                         if (retry_ctr > 0) {
1140                                 _LOGI("Retrying send on fd[%d]", sockfd);
1141                                 usleep(30 * 1000);
1142
1143                                 retry_ctr--;
1144                                 goto retry_send;
1145                         }
1146                 }
1147                 ret = MESSAGEPORT_ERROR_IO_ERROR;
1148                 goto out;
1149         }
1150 out:
1151         if (pkt)
1152                 free(pkt);
1153         if (kb_data)
1154                 free(kb_data);
1155
1156         return ret;
1157 }
1158
1159 static int __message_port_send_message(const char *remote_appid, const char *remote_port,
1160                 const char *local_port, bool trusted_message, bool local_trusted, bool bi_dir, bundle *message)
1161 {
1162
1163         int ret = MESSAGEPORT_ERROR_NONE;
1164         GUnixFDList *fd_list = NULL;
1165         GError *error = NULL;
1166
1167         int len = 0;
1168         bundle_raw *raw = NULL;
1169         char *bus_name = NULL;
1170         char *interface_name = NULL;
1171
1172         message_port_remote_app_info_s *remote_app_info = NULL;
1173         port_list_info_s *port_info = NULL;
1174         GDBusMessage *msg = NULL;
1175         GError *err = NULL;
1176         GVariant *body = NULL;
1177
1178         ret = __get_remote_port_info(remote_appid, remote_port, trusted_message, &remote_app_info, &port_info);
1179         if (ret != MESSAGEPORT_ERROR_NONE)
1180                 return ret;
1181
1182         if (port_info->exist == false) {
1183                 bool exist = false;
1184                 _LOGI("port exist check !!");
1185                 ret =  __check_remote_port(remote_appid, remote_port, trusted_message, &exist);
1186                 if (ret != MESSAGEPORT_ERROR_NONE) {
1187                         goto out;
1188                 } else if (!exist) {
1189                         ret = MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1190                         goto out;
1191                 }
1192         }
1193
1194         if (port_info->sock_pair[0] > 0) {
1195                 ret = __message_port_send_async(port_info->sock_pair[0], message,
1196                                 __app_id, (local_port) ? local_port : "", local_trusted, bi_dir);
1197         } else {
1198
1199                 bus_name = port_info->encoded_bus_name;
1200                 interface_name = bus_name;
1201
1202                 if (bundle_encode(message, &raw, &len) != BUNDLE_ERROR_NONE) {
1203                         ret = MESSAGEPORT_ERROR_INVALID_PARAMETER;
1204                         goto out;
1205                 }
1206
1207                 if (MAX_MESSAGE_SIZE < len) {
1208                         _LOGE("The size of message (%d) has exceeded the maximum limit.", len);
1209                         ret = MESSAGEPORT_ERROR_MAX_EXCEEDED;
1210                 }
1211
1212                 body = g_variant_new("(ssbbssbus)", __app_id, (local_port) ? local_port : "", local_trusted, bi_dir,
1213                                 remote_appid, remote_port, trusted_message, len, raw);
1214
1215
1216                 if (strcmp(remote_appid, __app_id) != 0) { /* self send */
1217
1218                         /*  if message-port fail to get socket pair, communicate using GDBus */
1219                         if (aul_request_message_port_socket_pair(port_info->sock_pair) != AUL_R_OK) {
1220                                 _LOGE("error create socket pair");
1221                         } else {
1222
1223                                 _LOGI("sock pair : %d, %d", port_info->sock_pair[0], port_info->sock_pair[1]);
1224
1225                                 fd_list = g_unix_fd_list_new();
1226                                 g_unix_fd_list_append(fd_list, port_info->sock_pair[1], &err);
1227                                 g_unix_fd_list_append(fd_list, port_info->sock_pair[0], &err);
1228
1229                                 if (err != NULL) {
1230                                         _LOGE("g_unix_fd_list_append [%s]", error->message);
1231                                         ret = MESSAGEPORT_ERROR_IO_ERROR;
1232                                         g_error_free(err);
1233                                         goto out;
1234                                 }
1235                         }
1236
1237                 }
1238
1239                 msg = g_dbus_message_new_method_call(bus_name, MESSAGEPORT_OBJECT_PATH, interface_name, "send_message");
1240                 if (!msg) {
1241                         _LOGE("Can't allocate new method call");
1242                         ret = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1243                         goto out;
1244                 }
1245
1246                 g_dbus_message_set_unix_fd_list(msg, fd_list);
1247                 g_dbus_message_set_body(msg, body);
1248                 g_dbus_message_set_flags(msg, G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED);
1249                 g_dbus_connection_send_message(__gdbus_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &err);
1250                 if (err != NULL) {
1251                         _LOGE("No reply. error = %s", err->message);
1252                         g_error_free(err);
1253                         ret = MESSAGEPORT_ERROR_IO_ERROR;
1254                         goto out;
1255                 }
1256
1257
1258         }
1259
1260 out:
1261         if (msg)
1262                 g_object_unref(msg);
1263         if (raw)
1264                 bundle_free_encoded_rawdata(&raw);
1265         if (fd_list)
1266                 g_object_unref(fd_list);
1267
1268
1269         return ret;
1270 }
1271
1272 int __message_send_bidirectional_message(int id, const char *remote_app_id, const char *remote_port,  bool trusted_message, bundle *message)
1273 {
1274         message_port_local_port_info_s *local_info;
1275         int ret = __get_local_port_info(id, &local_info);
1276         if (ret != MESSAGEPORT_ERROR_NONE)
1277                 return ret;
1278
1279         _LOGI("bidirectional_message %s", local_info->port_name);
1280         return __message_port_send_message(remote_app_id, remote_port,
1281                         local_info->port_name, trusted_message, local_info->is_trusted, true, message);
1282 }
1283
1284 int messageport_unregister_local_port(int local_port_id, bool trusted_port)
1285 {
1286
1287         GVariant *result;
1288         char *bus_name = NULL;
1289         GError *err = NULL;
1290         int ret = 0;
1291
1292         _LOGI("unregister : %d", local_port_id);
1293
1294         message_port_local_port_info_s *mi =
1295                 (message_port_local_port_info_s *)
1296                 g_hash_table_lookup(__local_port_info, GINT_TO_POINTER(local_port_id));
1297         if (mi == NULL)
1298                 return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1299
1300         if (mi->is_trusted != trusted_port)
1301                 return MESSAGEPORT_ERROR_INVALID_PARAMETER;
1302
1303         bus_name = __get_encoded_name(__app_id, mi->port_name, mi->is_trusted);
1304         if (bus_name == NULL)
1305                 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1306
1307         g_dbus_connection_unregister_object(__gdbus_conn, local_port_id);
1308
1309         result = g_dbus_connection_call_sync(
1310                         __gdbus_conn,
1311                         DBUS_SERVICE_DBUS,
1312                         DBUS_PATH_DBUS,
1313                         DBUS_INTERFACE_DBUS,
1314                         "ReleaseName",
1315                         g_variant_new("(s)", bus_name),
1316                         G_VARIANT_TYPE("(u)"),
1317                         G_DBUS_CALL_FLAGS_NONE,
1318                         -1,
1319                         NULL,
1320                         &err);
1321
1322         if (bus_name)
1323                 free(bus_name);
1324
1325         if (err) {
1326                 _LOGE("RequestName fail : %s", err->message);
1327                 g_error_free(err);
1328                 return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1329         }
1330         g_variant_get(result, "(u)", &ret);
1331
1332         if (result)
1333                 g_variant_unref(result);
1334
1335         if (ret != DBUS_RELEASE_NAME_REPLY_RELEASED) {
1336
1337                 if (ret == DBUS_RELEASE_NAME_REPLY_NON_EXISTENT) {
1338                         _LOGE("Port Not exist");
1339                         return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1340                 } else if (ret == DBUS_RELEASE_NAME_REPLY_NOT_OWNER) {
1341                         _LOGE("Try to release not owned name. MESSAGEPORT_ERROR_INVALID_PARAMETER");
1342                         return MESSAGEPORT_ERROR_INVALID_PARAMETER;
1343                 }
1344         }
1345
1346
1347         g_hash_table_remove(__local_port_info, GINT_TO_POINTER(local_port_id));
1348
1349         return MESSAGEPORT_ERROR_NONE;
1350 }
1351
1352 int messageport_register_local_port(const char *local_port, messageport_message_cb callback)
1353 {
1354         if (!_initialized) {
1355                 if (!__initialize())
1356                         return MESSAGEPORT_ERROR_IO_ERROR;
1357         }
1358
1359         return __register_message_port(local_port, false, callback);
1360 }
1361
1362 int messageport_register_trusted_local_port(const char *local_port, messageport_message_cb callback)
1363 {
1364         if (!_initialized) {
1365                 if (!__initialize())
1366                         return MESSAGEPORT_ERROR_IO_ERROR;
1367         }
1368
1369         return __register_message_port(local_port, true, callback);
1370
1371 }
1372
1373 int messageport_check_remote_port(const char *remote_app_id, const char *remote_port, bool *exist)
1374 {
1375         if (!_initialized) {
1376                 if (!__initialize())
1377                         return MESSAGEPORT_ERROR_IO_ERROR;
1378         }
1379
1380         int ret = __check_remote_port(remote_app_id, remote_port, false, exist);
1381         if (ret == MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND) {
1382                 *exist = false;
1383                 ret = MESSAGEPORT_ERROR_NONE;
1384         }
1385
1386         return ret;
1387 }
1388
1389 int messageport_check_trusted_remote_port(const char *remote_app_id, const char *remote_port, bool *exist)
1390 {
1391         if (!_initialized) {
1392                 if (!__initialize())
1393                         return MESSAGEPORT_ERROR_IO_ERROR;
1394         }
1395
1396         int ret = __check_remote_port(remote_app_id, remote_port, true, exist);
1397         if (ret == MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND) {
1398                 *exist = false;
1399                 ret = MESSAGEPORT_ERROR_NONE;
1400         }
1401
1402         return ret;
1403 }
1404
1405 int messageport_send_message(const char *remote_app_id, const char *remote_port, bundle *message)
1406 {
1407         if (!_initialized) {
1408                 if (!__initialize())
1409                         return MESSAGEPORT_ERROR_IO_ERROR;
1410         }
1411
1412         return __message_port_send_message(remote_app_id, remote_port, NULL, false, false, false, message);
1413 }
1414
1415 int messageport_send_trusted_message(const char *remote_app_id, const char *remote_port, bundle *message)
1416 {
1417         if (!_initialized) {
1418                 if (!__initialize())
1419                         return MESSAGEPORT_ERROR_IO_ERROR;
1420         }
1421
1422         return __message_port_send_message(remote_app_id, remote_port, NULL, true, false, false, message);
1423 }
1424
1425 int messageport_send_bidirectional_message(int id, const char *remote_app_id, const char *remote_port,
1426                 bundle *message)
1427 {
1428         if (!_initialized) {
1429                 if (!__initialize())
1430                         return MESSAGEPORT_ERROR_IO_ERROR;
1431         }
1432
1433         return __message_send_bidirectional_message(id, remote_app_id, remote_port, false, message);
1434 }
1435
1436 int messageport_send_bidirectional_trusted_message(int id, const char *remote_app_id, const char *remote_port,
1437                 bundle *message)
1438 {
1439         if (!_initialized) {
1440                 if (!__initialize())
1441                         return MESSAGEPORT_ERROR_IO_ERROR;
1442         }
1443         return __message_send_bidirectional_message(id, remote_app_id, remote_port, true, message);
1444 }
1445
1446 int messageport_get_local_port_name(int id, char **name)
1447 {
1448         message_port_local_port_info_s *local_info;
1449         int ret = __get_local_port_info(id, &local_info);
1450
1451         if (ret != MESSAGEPORT_ERROR_NONE)
1452                 return ret;
1453
1454         *name = strdup(local_info->port_name);
1455
1456         if (*name == NULL)
1457                 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1458
1459         return MESSAGEPORT_ERROR_NONE;
1460 }
1461
1462 int messageport_check_trusted_local_port(int id, bool *trusted)
1463 {
1464         message_port_local_port_info_s *local_info;
1465         int ret = __get_local_port_info(id, &local_info);
1466
1467         if (ret != MESSAGEPORT_ERROR_NONE)
1468                 return ret;
1469
1470         *trusted = local_info->is_trusted;
1471
1472         return MESSAGEPORT_ERROR_NONE;;
1473 }
1474