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