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