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