Fix memory leak
[platform/core/appfw/message-port.git] / src / message_port_remote.c
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #define _GNU_SOURCE
18
19 #include <bundle.h>
20 #include <bundle_internal.h>
21 #include <aul.h>
22
23 #include <sys/socket.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26
27 #include <glib.h>
28 #include <gio/gio.h>
29 #include <gio/gunixfdlist.h>
30 #include <glib-unix.h>
31
32 #include "message_port_log.h"
33 #include "message_port_common.h"
34 #include "message_port_remote.h"
35
36
37 #define MAX_PACKAGE_STR_SIZE 512
38
39 #define DBUS_RELEASE_NAME_REPLY_RELEASED        1 /* *< Service was released from the given name */
40 #define DBUS_RELEASE_NAME_REPLY_NON_EXISTENT    2 /* *< The given name does not exist on the bus */
41 #define DBUS_RELEASE_NAME_REPLY_NOT_OWNER       3 /* *< Service is not an owner of the given name */
42
43 #define MAX_RETRY_CNT 10
44 #define SOCK_PAIR_SENDER 0
45 #define SOCK_PAIR_RECEIVER 1
46
47 static bool _initialized = false;
48 static GHashTable *__local_port_info;
49 static GHashTable *__trusted_app_list_hash;
50 static GHashTable *__callback_info_hash;
51 static GHashTable *__sender_appid_hash;
52
53 typedef struct message_port_pkt {
54         int remote_port_name_len;
55         char *remote_port_name;
56         bool is_bidirection;
57         bool is_trusted;
58         int data_len;
59         unsigned char *data;
60 } message_port_pkt_s;
61
62 typedef struct message_port_callback_info {
63         message_port_local_port_info_s *local_info;
64         int local_id;
65         char *remote_app_id;
66         GIOChannel *gio_read;
67         int g_src_id;
68 } message_port_callback_info_s;
69
70 typedef struct callback_key_info {
71         int local_id;
72         message_port_callback_info_s *callback_info;
73 } callback_key_info_s;
74
75 static void __callback_info_free(gpointer data)
76 {
77         message_port_callback_info_s *callback_info = (message_port_callback_info_s *)data;
78         GError *error = NULL;
79         if (callback_info == NULL)
80                 return;
81
82         if (callback_info->remote_app_id)
83                 FREE_AND_NULL(callback_info->remote_app_id);
84
85         if (callback_info->local_info) {
86                 if (callback_info->local_info->port_name)
87                                 FREE_AND_NULL(callback_info->local_info->port_name);
88
89                 FREE_AND_NULL(callback_info->local_info);
90         }
91
92         if (callback_info->gio_read != NULL) {
93                 g_io_channel_shutdown(callback_info->gio_read, TRUE, &error);
94                 if (error) {
95                         _LOGE("g_io_channel_shutdown error : %s", error->message);
96                         g_error_free(error);
97                 }
98                 g_io_channel_unref(callback_info->gio_read);
99                 callback_info->gio_read = NULL;
100         }
101
102         if (callback_info->g_src_id != 0) {
103                 g_source_remove(callback_info->g_src_id);
104                 callback_info->g_src_id = 0;
105         }
106
107         FREE_AND_NULL(callback_info);
108 }
109
110 /* LCOV_EXCL_START */
111 static void __callback_info_free_by_info(message_port_callback_info_s *callback_info)
112 {
113         GList *callback_info_list = g_hash_table_lookup(__callback_info_hash, GUINT_TO_POINTER(callback_info->local_id));
114         GList *find_list;
115
116         if (callback_info_list == NULL)
117                 return;
118
119         find_list = g_list_find(callback_info_list, callback_info);
120         if (find_list == NULL)
121                 return;
122
123         callback_info_list = g_list_remove_link(callback_info_list, find_list);
124         __callback_info_free(callback_info);
125         g_list_free(find_list);
126 }
127 /* LCOV_EXCL_STOP */
128
129 static void __hash_destroy_callback_info(gpointer data)
130 {
131         GList *callback_list = (GList *)data;
132
133         if (callback_list != NULL)
134                 g_list_free_full(callback_list, __callback_info_free);
135 }
136
137 /* LCOV_EXCL_START */
138 static void __hash_destory_local_value(gpointer data)
139 {
140         message_port_local_port_info_s *mli = (message_port_local_port_info_s *)data;
141         if (mli) {
142                 if (mli->port_name)
143                         free(mli->port_name);
144                 free(mli);
145         }
146 }
147 /* LCOV_EXCL_STOP */
148
149 static bool __initialize(void)
150 {
151         if (!initialized_common) {
152                 if (!initialize_common())
153                         return false;
154         }
155
156         if (__local_port_info == NULL) {
157                 __local_port_info = g_hash_table_new_full(g_direct_hash,  g_direct_equal, NULL, __hash_destory_local_value);
158                 retvm_if(!__local_port_info, false, "fail to create __local_port_info");
159         }
160
161         if (__sender_appid_hash == NULL) {
162                 __sender_appid_hash = g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
163                 retvm_if(!__sender_appid_hash, false, "fail to create __sender_appid_hash");
164         }
165
166         if (__trusted_app_list_hash == NULL) {
167                 __trusted_app_list_hash = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
168                 retvm_if(!__trusted_app_list_hash, false, "fail to create __trusted_app_list_hash");
169         }
170
171         if (__callback_info_hash == NULL) {
172                 __callback_info_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, __hash_destroy_callback_info);
173                 retvm_if(!__callback_info_hash, false, "fail to create __callback_info_hash");
174         }
175
176         _initialized = true;
177
178         return true;
179 }
180
181 bool is_local_port_registed(const char *local_port, bool trusted, int *local_id, message_port_local_port_info_s **lpi)
182 {
183         GHashTableIter iter;
184         gpointer key, value;
185
186         g_hash_table_iter_init(&iter, __local_port_info);
187         while (g_hash_table_iter_next(&iter, &key, &value)) {
188                 message_port_local_port_info_s *mi = (message_port_local_port_info_s *)value;
189
190                 if ((mi->is_trusted == trusted) && strcmp(mi->port_name, local_port) == 0) {
191                         *local_id = mi->local_id;
192                         if (lpi != NULL)
193                                 *lpi = mi;
194                         return true;
195                 }
196         }
197         return false;
198 }
199
200 static int __get_sender_pid(GDBusConnection *conn, const char *sender_name)
201 {
202         GDBusMessage *msg = NULL;
203         GDBusMessage *reply = NULL;
204         GError *err = NULL;
205         GVariant *body;
206         int pid = 0;
207
208         msg = g_dbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
209                         "org.freedesktop.DBus", "GetConnectionUnixProcessID");
210         if (!msg) {
211                 _LOGE("Can't allocate new method call");
212                 goto out;
213         }
214
215         g_dbus_message_set_body(msg, g_variant_new("(s)", sender_name));
216         reply = g_dbus_connection_send_message_with_reply_sync(conn, msg,
217                                                         G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err);
218
219         if (!reply) {
220                 if (err != NULL) {
221                         _LOGE("Failed to get pid [%s]", err->message);
222                         g_error_free(err);
223                 }
224                 goto out;
225         }
226
227         body = g_dbus_message_get_body(reply);
228         g_variant_get(body, "(u)", &pid);
229
230 out:
231         if (msg)
232                 g_object_unref(msg);
233         if (reply)
234                 g_object_unref(reply);
235
236         return pid;
237 }
238
239 static message_port_pkt_s *__message_port_recv_raw(int fd)
240 {
241         message_port_pkt_s *pkt = NULL;
242         unsigned int nb;
243
244         pkt = (message_port_pkt_s *)calloc(sizeof(message_port_pkt_s), 1);
245         if (pkt == NULL) {
246                 close(fd);
247                 return NULL;
248         }
249
250         if (read_string_from_socket(fd, (char **)&pkt->remote_port_name, &pkt->remote_port_name_len) != MESSAGE_PORT_ERROR_NONE) {
251 /* LCOV_EXCL_START */
252                 LOGE("read socket fail: port_name");
253                 free(pkt->remote_port_name);
254                 free(pkt);
255                 return NULL;
256 /* LCOV_EXCL_STOP */
257         }
258
259         if (read_socket(fd, (char *)&pkt->is_bidirection, sizeof(pkt->is_bidirection), &nb) != MESSAGE_PORT_ERROR_NONE) {
260 /* LCOV_EXCL_START */
261                 LOGE("read socket fail: is_bidirection");
262                 free(pkt->remote_port_name);
263                 free(pkt);
264                 return NULL;
265 /* LCOV_EXCL_STOP */
266         }
267
268         if (read_socket(fd, (char *)&pkt->is_trusted, sizeof(pkt->is_trusted), &nb) != MESSAGE_PORT_ERROR_NONE) {
269 /* LCOV_EXCL_START */
270                 LOGE("read socket fail: is_trusted");
271                 free(pkt->remote_port_name);
272                 free(pkt);
273                 return NULL;
274 /* LCOV_EXCL_STOP */
275         }
276
277         if (read_string_from_socket(fd, (char **)&pkt->data, &pkt->data_len) != MESSAGE_PORT_ERROR_NONE) {
278 /* LCOV_EXCL_START */
279                 LOGE("read socket fail: data");
280                 if (pkt->data)
281                         free(pkt->data);
282                 free(pkt->remote_port_name);
283                 free(pkt);
284                 return NULL;
285 /* LCOV_EXCL_STOP */
286         }
287
288         return pkt;
289 }
290
291 static bool __validate_callback_info(callback_key_info_s *key_info)
292 {
293         GList *cb_list;
294
295         cb_list = g_hash_table_lookup(__callback_info_hash,
296                         GUINT_TO_POINTER(key_info->local_id));
297         if (cb_list == NULL) {
298                 _LOGI("local_info : %d is already released", key_info->local_id);
299                 return false;
300         }
301
302         cb_list = g_list_find(cb_list, key_info->callback_info);
303         if (cb_list == NULL) {
304                 _LOGI("local_info : %d is already released", key_info->local_id);
305                 return false;
306         }
307
308         return true;
309 }
310
311 static bool __validate_local_info(callback_key_info_s *key_info)
312 {
313         GList *cb_list;
314
315         cb_list = g_hash_table_lookup(__local_port_info,
316                         GUINT_TO_POINTER(key_info->local_id));
317         if (cb_list == NULL) {
318                 _LOGI("local_info : %d is already released", key_info->local_id);
319                 return false;
320         }
321
322         return true;
323 }
324
325 static gboolean __socket_request_handler(GIOChannel *gio,
326                 GIOCondition cond,
327                 gpointer data)
328 {
329         int fd = 0;
330         message_port_callback_info_s *mi = NULL;
331         callback_key_info_s *key_info;
332         message_port_pkt_s *pkt = NULL;
333         message_port_local_port_info_s *local_port_info;
334         bundle *kb = NULL;
335         bool ret = true;
336         bool existed = true;
337
338         key_info = (callback_key_info_s *)data;
339         if (key_info == NULL)
340                 return FALSE;
341
342         message_port_lock_mutex();
343         if (__validate_callback_info(key_info) == false) {
344                 ret = FALSE;
345                 existed = FALSE;
346                 message_port_unlock_mutex();
347                 goto out;
348         }
349
350         if (__validate_local_info(key_info) == false) {
351                 ret = FALSE;
352                 message_port_unlock_mutex();
353                 goto out;
354         }
355         message_port_unlock_mutex();
356
357         mi = key_info->callback_info;
358
359         local_port_info = mi->local_info;
360         if (local_port_info == NULL || local_port_info->callback == NULL) {
361                 _LOGE("Failed to get callback info");
362                 ret = FALSE;
363                 goto out;
364         }
365
366         if (cond == G_IO_HUP) {
367                 _LOGI("socket G_IO_HUP");
368                 ret = FALSE;
369                 goto out;
370         }
371
372         fd = g_io_channel_unix_get_fd(gio);
373         if (fd < 0) {
374                 _LOGE("fail to get fd from io channel");
375                 ret = FALSE;
376                 goto out;
377         }
378
379         pkt = __message_port_recv_raw(fd);
380         if (pkt == NULL) {
381                 _LOGE("recv error on SOCKET");
382                 ret = FALSE;
383                 goto out;
384         }
385
386         kb = bundle_decode(pkt->data, pkt->data_len);
387         if (!kb) {
388                 _LOGE("Invalid argument : message");
389                 ret = FALSE;
390                 goto out;
391         }
392
393         if (pkt->is_bidirection)
394                 local_port_info->callback(mi->local_id, mi->remote_app_id,
395                         pkt->remote_port_name, pkt->is_trusted, kb, local_port_info->user_data);
396         else
397                 local_port_info->callback(mi->local_id, mi->remote_app_id,
398                         NULL, pkt->is_trusted, kb, local_port_info->user_data);
399
400         bundle_free(kb);
401
402 out:
403         if (pkt) {
404                 if (pkt->remote_port_name)
405                         free(pkt->remote_port_name);
406                 if (pkt->data)
407                         free(pkt->data);
408                 free(pkt);
409         }
410
411         if (mi && ret == FALSE && existed == TRUE) {
412                 message_port_lock_mutex();
413                 __callback_info_free_by_info(mi);
414                 message_port_unlock_mutex();
415         }
416
417         return ret;
418 }
419
420
421 static void __socket_destroy_handler(gpointer data)
422 {
423         _LOGI("__socket_destroy_handler");
424         callback_key_info_s *key_info = (callback_key_info_s *)data;
425         free(key_info);
426 }
427
428 static callback_key_info_s *__create_callback_key_info(message_port_callback_info_s *callback_info)
429 {
430         callback_key_info_s *_key_info = (callback_key_info_s *)
431                 calloc(1, sizeof(callback_key_info_s));
432
433         if (_key_info == NULL) {
434                 _LOGE("out of memory");
435                 return NULL;
436         }
437
438         _key_info->local_id = callback_info->local_id;
439         _key_info->callback_info = callback_info;
440
441         return _key_info;
442 }
443
444 static message_port_callback_info_s *__create_callback_info(message_port_local_port_info_s *mi, char *local_appid)
445 {
446         message_port_local_port_info_s *local_info = NULL;
447         message_port_callback_info_s *callback_info = NULL;
448         bool ret = true;
449
450         callback_info = (message_port_callback_info_s *)calloc(1, sizeof(message_port_callback_info_s));
451         if (callback_info == NULL) {
452                 _LOGE("out of memory");
453                 return NULL;
454         }
455
456         local_info = (message_port_local_port_info_s *)calloc(1, sizeof(message_port_local_port_info_s));
457         if (local_info == NULL) {
458                 ret = false;
459                 _LOGE("out of memory");
460                 goto out;
461         }
462
463         callback_info->local_id = mi->local_id;
464         callback_info->local_info = local_info;
465         callback_info->remote_app_id = strdup(local_appid);
466         if (callback_info->remote_app_id == NULL) {
467                 ret = false;
468                 _LOGE("out of memory");
469                 goto out;
470         }
471
472         local_info->port_name = strdup(mi->port_name);
473         if (local_info->port_name == NULL) {
474                 ret = false;
475                 _LOGE("out of memory");
476                 goto out;
477         }
478
479         local_info->callback = mi->callback;
480         local_info->is_trusted = mi->is_trusted;
481         local_info->local_id = mi->local_id;
482         local_info->user_data = mi->user_data;
483
484 out:
485         if (ret == false) {
486                 __callback_info_free(callback_info);
487                 return NULL;
488         }
489
490         return callback_info;
491 }
492
493 static bool __callback_info_append(message_port_callback_info_s *callback_info)
494 {
495         GList *callback_info_list = NULL;
496         message_port_callback_info_s *head_callback_info;
497
498         callback_info_list = g_hash_table_lookup(__callback_info_hash, GUINT_TO_POINTER(callback_info->local_id));
499         if (callback_info_list == NULL) {
500                 head_callback_info = (message_port_callback_info_s *)calloc(1, sizeof(message_port_callback_info_s));
501                 if (head_callback_info == NULL) {
502                         _LOGE("fail to alloc head_callback_info");
503                         return false;
504                 }
505                 head_callback_info->local_id = 0;
506                 head_callback_info->remote_app_id = NULL;
507                 head_callback_info->local_info = NULL;
508                 head_callback_info->gio_read = NULL;
509                 head_callback_info->g_src_id = 0;
510                 callback_info_list = g_list_append(callback_info_list, head_callback_info);
511                 callback_info_list = g_list_append(callback_info_list, callback_info);
512                 g_hash_table_insert(__callback_info_hash, GUINT_TO_POINTER(callback_info->local_id), callback_info_list);
513         } else {
514                 callback_info_list = g_list_append(callback_info_list, callback_info);
515         }
516
517         return true;
518 }
519
520 static void __callback_info_update_user_data(int local_id, message_port_message_cb callback, void *user_data)
521 {
522         GList *callback_info_list;
523         GList *iter;
524         message_port_callback_info_s *callback_info;
525
526         callback_info_list = g_hash_table_lookup(__callback_info_hash, GUINT_TO_POINTER(local_id));
527         if (callback_info_list != NULL) {
528                 for (iter = callback_info_list; iter != NULL; iter = iter->next) {
529                         callback_info = (message_port_callback_info_s *)iter->data;
530                         if (callback_info->local_info != NULL) {
531                                 callback_info->local_info->callback = callback;
532                                 callback_info->local_info->user_data = user_data;
533                         }
534                 }
535         } else {
536                 _LOGE("fail to find local_id %d ", local_id);
537         }
538 }
539
540 static bool __receive_message(GVariant *parameters, GDBusMethodInvocation *invocation)
541 {
542         char *local_port = NULL;
543         char *local_appid = NULL;
544         char *remote_appid = NULL;
545         char *remote_port = NULL;
546         gboolean local_trusted = false;
547         gboolean remote_trusted = false;
548         gboolean bi_dir = false;
549         int len = 0;
550
551         bundle *data = NULL;
552         bundle_raw *raw = NULL;
553         message_port_local_port_info_s *mi;
554         int local_reg_id = 0;
555         message_port_callback_info_s *callback_info = NULL;
556         callback_key_info_s *key_info;
557
558         char buf[1024];
559         GDBusMessage *msg;
560         GUnixFDList *fd_list;
561         int fd_len;
562         int *returned_fds = NULL;
563         int fd;
564         bool ret = false;
565         char *key_appid;
566
567         g_variant_get(parameters, "(&s&sbb&s&sbu&s)", &local_appid, &local_port, &local_trusted, &bi_dir,
568                         &remote_appid, &remote_port, &remote_trusted, &len, &raw);
569
570         if (!remote_port) {
571                 _LOGE("Invalid argument : remote_port is NULL");
572                 goto out;
573         }
574         if (!remote_appid) {
575                 _LOGE("Invalid argument : remote_appid is NULL");
576                 goto out;
577         }
578
579         if (!local_appid) {
580                 _LOGE("Invalid argument : local_appid");
581                 goto out;
582         }
583
584         message_port_lock_mutex();
585         if (!is_local_port_registed(remote_port, remote_trusted, &local_reg_id, &mi)) {
586                 _LOGE("Invalid argument : remote_port:(%s) trusted(%d)", remote_port, remote_trusted);
587                 message_port_unlock_mutex();
588                 goto out;
589         }
590
591         callback_info = __create_callback_info(mi, local_appid);
592         if (callback_info == NULL) {
593                 message_port_unlock_mutex();
594                 goto out;
595         }
596         message_port_unlock_mutex();
597
598         if (!local_port) {
599                 _LOGE("Invalid argument : local_port");
600                 goto out;
601         }
602         if (strcmp(remote_appid, app_id) != 0) {
603                 _LOGE("Invalid argument : remote_appid (%s)", remote_appid);
604                 goto out;
605         }
606         if (strcmp(remote_port, callback_info->local_info->port_name) != 0) {
607                 _LOGE("Invalid argument : remote_port (%s)", remote_port);
608                 goto out;
609         }
610         if (!len) {
611                 _LOGE("Invalid argument : data_len");
612                 goto out;
613         }
614         if (remote_trusted) {
615                 if (g_hash_table_lookup(__trusted_app_list_hash, (gpointer)local_appid) == NULL) {
616                         if (!is_preloaded(local_appid, remote_appid)) {
617                                 int ret = check_certificate(local_appid, remote_appid);
618                                 if (ret == MESSAGE_PORT_ERROR_NONE) {
619                                         key_appid = strdup(local_appid);
620                                         if (key_appid)
621                                                 g_hash_table_insert(__trusted_app_list_hash, key_appid, "TRUE");
622                                 } else {
623                                         _LOGE("The application (%s) is not signed with the same certificate",
624                                                         local_appid);
625                                         goto out;
626                                 }
627                         }
628                 }
629         }
630
631         data = bundle_decode(raw, len);
632         if (!data) {
633                 _LOGE("Invalid argument : message");
634                 goto out;
635         }
636
637         LOGD("call calback %s", local_appid);
638         if (bi_dir)
639                 callback_info->local_info->callback(callback_info->local_info->local_id,
640                         local_appid, local_port, local_trusted, data, callback_info->local_info->user_data);
641         else
642                 callback_info->local_info->callback(callback_info->local_info->local_id,
643                         local_appid, NULL, false, data, callback_info->local_info->user_data);
644         bundle_free(data);
645
646         ret = true;
647
648         msg = g_dbus_method_invocation_get_message(invocation);
649         fd_list = g_dbus_message_get_unix_fd_list(msg);
650
651         /* When application send message to self fd_list is NULL */
652         if (fd_list != NULL) {
653                 returned_fds = g_unix_fd_list_steal_fds(fd_list, &fd_len);
654                 if (returned_fds == NULL) {
655                         _LOGE("fail to get fds");
656                         ret = false;
657                         goto out;
658                 }
659                 fd = returned_fds[0];
660
661                 LOGI("g_unix_fd_list_get %d fd: [%d]", fd_len, fd);
662                 if (fd > 0) {
663                         callback_info->gio_read = g_io_channel_unix_new(fd);
664                         if (!callback_info->gio_read) {
665                                 _LOGE("Error is %s\n", strerror_r(errno, buf, sizeof(buf)));
666                                 ret = false;
667                                 goto out;
668                         }
669
670                         key_info = __create_callback_key_info(callback_info);
671                         if (key_info == NULL) {
672                                 _LOGE("out of memory");
673                                 ret = false;
674                                 goto out;
675                         }
676
677                         callback_info->g_src_id = g_io_add_watch_full(
678                                         callback_info->gio_read,
679                                         G_PRIORITY_DEFAULT,
680                                         G_IO_IN | G_IO_HUP,
681                                         __socket_request_handler,
682                                         (gpointer)key_info,
683                                         __socket_destroy_handler);
684                         if (callback_info->g_src_id == 0) {
685                                 _LOGE("fail to add watch on socket");
686                                 free(key_info);
687                                 ret = false;
688                                 goto out;
689                         }
690
691                         message_port_lock_mutex();
692                         if (__callback_info_append(callback_info) == false) {
693                                 _LOGE("fail to append callback_info");
694                                 ret = false;
695                         }
696                         message_port_unlock_mutex();
697                 }
698         }
699
700 out:
701         if (ret == false)
702                 __callback_info_free(callback_info);
703
704         if (returned_fds)
705                 free(returned_fds);
706
707         return ret;
708 }
709
710 static void __on_sender_name_appeared(GDBusConnection *connection,
711                 const gchar     *name,
712                 const gchar     *name_owner,
713                 gpointer         user_data)
714 {
715         _LOGI("sender name appeared : %s", name);
716 }
717
718 static void __on_sender_name_vanished(GDBusConnection *connection,
719                 const gchar     *name,
720                 gpointer         user_data)
721 {
722         int *watcher_id = (int *)user_data;
723         char *local_appid;
724
725         local_appid = (char *)g_hash_table_lookup(__sender_appid_hash, name);
726         if (local_appid) {
727                 g_hash_table_remove(__trusted_app_list_hash, (gpointer)local_appid);
728                 g_hash_table_remove(__sender_appid_hash, (gpointer)name);
729         }
730
731         if (watcher_id) {
732                 if (*watcher_id > 0)
733                         g_bus_unwatch_name(*watcher_id);
734                 else
735                         LOGE("Invalid watcher_id %d", *watcher_id);
736                 free(watcher_id);
737         } else {
738                 LOGE("watcher_id is NULL");
739         }
740 }
741
742 static bool __check_sender_validation(GVariant *parameters, const char *sender, GDBusConnection *conn)
743 {
744         int ret = 0;
745         char buffer[MAX_PACKAGE_STR_SIZE] = {0, };
746         char *local_appid = NULL;
747         int pid = __get_sender_pid(conn, sender);
748         int *watcher_id = (int *)calloc(1, sizeof(int));
749         char *_sender;
750         char *_appid;
751         retvm_if(!watcher_id, false, "Malloc failed");
752
753         ret = aul_app_get_appid_bypid(pid, buffer, sizeof(buffer));
754         if (ret != AUL_R_OK) {
755                 _LOGE("Failed to get the sender ID: (%s) (%d)", sender, pid);
756                 free(watcher_id);
757                 return false;
758         }
759
760         g_variant_get_child(parameters, 0, "&s", &local_appid);
761         if (local_appid == NULL) {
762                 _LOGE("appid is NULL : (%s) (%d)", sender, pid);
763                 free(watcher_id);
764                 return false;
765         }
766
767         if (strncmp(buffer, local_appid, MAX_PACKAGE_STR_SIZE) == 0) {
768                 _LOGD("insert sender !!!!! %s", sender);
769                 _sender = strdup(sender);
770                 if (_sender == NULL) {
771                         _LOGE("out of memory");
772                         free(watcher_id);
773                         return false;
774                 }
775
776                 _appid = strdup(local_appid);
777                 if (_appid == NULL) {
778                         _LOGE("out of memory");
779                         free(watcher_id);
780                         free(_sender);
781                         return false;
782                 }
783
784                 g_hash_table_insert(__sender_appid_hash, (gpointer)_sender, (gpointer)_appid);
785                 *watcher_id = g_bus_watch_name_on_connection(
786                                         gdbus_conn,
787                                         sender,
788                                         G_BUS_NAME_WATCHER_FLAGS_NONE,
789                                         __on_sender_name_appeared,
790                                         __on_sender_name_vanished,
791                                         watcher_id,
792                                         NULL);
793         } else {
794                 free(watcher_id);
795                 return false;
796         }
797         return true;
798 }
799
800 static void __dbus_method_call_handler(GDBusConnection *conn,
801                                 const gchar *sender, const gchar *object_path,
802                                 const gchar *iface_name, const gchar *method_name,
803                                 GVariant *parameters, GDBusMethodInvocation *invocation,
804                                 gpointer user_data)
805 {
806         _LOGI("method_name: %s, sender: %s", method_name, sender);
807         gpointer sender_appid = g_hash_table_lookup(__sender_appid_hash, sender);
808         if (sender_appid == NULL) {
809                 if (!__check_sender_validation(parameters, sender, conn))
810                         goto out;
811         }
812         if (g_strcmp0(method_name, "send_message") == 0)
813                 __receive_message(parameters, invocation);
814 out:
815         g_dbus_method_invocation_return_value(invocation, NULL);
816 }
817
818 static const GDBusInterfaceVTable interface_vtable = {
819         __dbus_method_call_handler,
820         NULL,
821         NULL
822 };
823
824 static int __register_dbus_interface(const char *port_name, bool is_trusted)
825 {
826
827         GDBusNodeInfo *introspection_data = NULL;
828         int registration_id = 0;
829
830         static gchar introspection_prefix[] =
831                 "<node>"
832                 "  <interface name='";
833
834         static gchar introspection_postfix[] =
835                 "'>"
836                 "        <method name='send_message'>"
837                 "          <arg type='s' name='local_appid' direction='in'/>"
838                 "          <arg type='s' name='local_port' direction='in'/>"
839                 "          <arg type='b' name='local_trusted' direction='in'/>"
840                 "          <arg type='b' name='bi_dir' direction='in'/>"
841                 "          <arg type='s' name='remote_appid' direction='in'/>"
842                 "          <arg type='s' name='remote_port' direction='in'/>"
843                 "          <arg type='b' name='remote_trusted' direction='in'/>"
844                 "          <arg type='u' name='data_len' direction='in'/>"
845                 "          <arg type='s' name='data' direction='in'/>"
846                 "        </method>"
847                 "  </interface>"
848                 "</node>";
849
850         char *introspection_xml = NULL;
851         int introspection_xml_len = 0;
852
853
854         int owner_id = 0;
855         GError *error = NULL;
856         char *bus_name = NULL;
857         char *interface_name = NULL;
858         GVariant *result = NULL;
859
860         bus_name = get_encoded_name(app_id, port_name, is_trusted);
861         if (!bus_name) {
862                 _LOGE("Fail to get bus name");
863                 goto out;
864         }
865         interface_name = bus_name;
866
867         introspection_xml_len = strlen(introspection_prefix) + strlen(interface_name) +
868                 strlen(introspection_postfix) + 1;
869
870         introspection_xml = (char *)calloc(introspection_xml_len, sizeof(char));
871         if (!introspection_xml) {
872                 _LOGE("out of memory");
873                 goto out;
874         }
875
876
877         result = g_dbus_connection_call_sync(
878                         gdbus_conn,
879                         DBUS_SERVICE_DBUS,
880                         DBUS_PATH_DBUS,
881                         DBUS_INTERFACE_DBUS,
882                         "RequestName",
883                         g_variant_new("(su)", bus_name, G_BUS_NAME_OWNER_FLAGS_NONE),
884                         G_VARIANT_TYPE("(u)"),
885                         G_DBUS_CALL_FLAGS_NONE,
886                         -1,
887                         NULL,
888                         &error);
889         if (error) {
890                 _LOGE("RequestName fail : %s", error->message);
891                 g_error_free(error);
892                 goto out;
893         }
894         if (result == NULL) {
895                 _LOGE("fail to get name NULL");
896                 goto out;
897         }
898         g_variant_get(result, "(u)", &owner_id);
899         if (owner_id == 0) {
900                 _LOGE("Acquiring the own name is failed");
901                 goto out;
902         }
903
904         _LOGD("Acquiring the own name : %d", owner_id);
905
906         snprintf(introspection_xml, introspection_xml_len, "%s%s%s", introspection_prefix, interface_name, introspection_postfix);
907
908         introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
909         if (!introspection_data) {
910                 _LOGE("g_dbus_node_info_new_for_xml() is failed.");
911                 goto out;
912         }
913
914         registration_id = g_dbus_connection_register_object(gdbus_conn,
915                                                 MESSAGEPORT_OBJECT_PATH, introspection_data->interfaces[0],
916                                                 &interface_vtable, NULL, NULL, NULL);
917
918         _LOGD("registration_id %d", registration_id);
919
920         if (registration_id == 0) {
921                 _LOGE("Failed to g_dbus_connection_register_object");
922                 goto out;
923         }
924
925 out:
926         if (introspection_data)
927                 g_dbus_node_info_unref(introspection_data);
928         if (introspection_xml)
929                 free(introspection_xml);
930         if (bus_name)
931                 free(bus_name);
932         if (result)
933                 g_variant_unref(result);
934
935
936         return registration_id;
937 }
938
939 static bool __message_port_register_port(const int local_id, const char *local_port, bool is_trusted, message_port_message_cb callback, void *user_data)
940 {
941         message_port_local_port_info_s *mi = (message_port_local_port_info_s *)calloc(1, sizeof(message_port_local_port_info_s));
942         retvm_if(!mi, false, "Malloc failed");
943
944         mi->callback = callback;
945         mi->is_trusted = is_trusted;
946         mi->port_name = strdup(local_port);
947         if (mi->port_name == NULL) {
948                 _LOGE("Malloc failed (%s)", local_port);
949                 free(mi);
950                 return false;
951         }
952         mi->local_id = local_id;
953         mi->user_data = user_data;
954
955         g_hash_table_insert(__local_port_info, GINT_TO_POINTER(mi->local_id), mi);
956         return true;
957 }
958
959 int get_local_port_info(int id, message_port_local_port_info_s **info)
960 {
961         message_port_local_port_info_s *mi = (message_port_local_port_info_s *)g_hash_table_lookup(__local_port_info, GINT_TO_POINTER(id));
962
963         if (mi == NULL)
964                 return MESSAGE_PORT_ERROR_PORT_NOT_FOUND;
965         *info = mi;
966
967         return MESSAGE_PORT_ERROR_NONE;
968 }
969
970 int register_message_port(const char *local_port, bool is_trusted, message_port_message_cb callback, void *user_data)
971 {
972         _SECURE_LOGI("local_port : [%s:%s]", local_port, is_trusted ? "trusted" : "non-trusted");
973
974         int local_id = 0;
975         message_port_local_port_info_s *port_info;
976         if (!_initialized) {
977                 if (!__initialize())
978                         return MESSAGE_PORT_ERROR_IO_ERROR;
979         }
980
981         /* Check the message port is already registed */
982         if (is_local_port_registed(local_port, is_trusted, &local_id, &port_info)) {
983                 port_info->callback = callback;
984                 port_info->user_data = user_data;
985                 __callback_info_update_user_data(local_id, callback, user_data);
986                 return local_id;
987         }
988
989         local_id = __register_dbus_interface(local_port, is_trusted);
990         if (local_id < 1) {
991                 _LOGE("register_dbus_interface fail !!");
992                 return MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
993         }
994
995         if (!__message_port_register_port(local_id, local_port, is_trusted, callback, user_data))
996                 return MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
997
998         return local_id;
999 }
1000
1001 int unregister_local_port(int local_port_id, bool trusted_port)
1002 {
1003
1004         GVariant *result;
1005         char *bus_name = NULL;
1006         GError *err = NULL;
1007         int ret = 0;
1008         message_port_local_port_info_s *mi;
1009
1010         _LOGI("unregister : %d", local_port_id);
1011
1012         if (!_initialized) {
1013                 if (!__initialize())
1014                         return MESSAGE_PORT_ERROR_IO_ERROR;
1015         }
1016
1017         mi = (message_port_local_port_info_s *)
1018                 g_hash_table_lookup(__local_port_info, GINT_TO_POINTER(local_port_id));
1019         if (mi == NULL)
1020                 return MESSAGE_PORT_ERROR_PORT_NOT_FOUND;
1021
1022         if (mi->is_trusted != trusted_port)
1023                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
1024
1025         g_hash_table_remove(__callback_info_hash, GUINT_TO_POINTER(local_port_id));
1026
1027         bus_name = get_encoded_name(app_id, mi->port_name, mi->is_trusted);
1028         if (bus_name == NULL)
1029                 return MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
1030
1031         g_dbus_connection_unregister_object(gdbus_conn, local_port_id);
1032
1033         result = g_dbus_connection_call_sync(
1034                         gdbus_conn,
1035                         DBUS_SERVICE_DBUS,
1036                         DBUS_PATH_DBUS,
1037                         DBUS_INTERFACE_DBUS,
1038                         "ReleaseName",
1039                         g_variant_new("(s)", bus_name),
1040                         G_VARIANT_TYPE("(u)"),
1041                         G_DBUS_CALL_FLAGS_NONE,
1042                         -1,
1043                         NULL,
1044                         &err);
1045
1046         if (bus_name)
1047                 free(bus_name);
1048
1049         if (err) {
1050                 _LOGE("RequestName fail : %s", err->message);
1051                 g_error_free(err);
1052                 return MESSAGE_PORT_ERROR_PORT_NOT_FOUND;
1053         }
1054         g_variant_get(result, "(u)", &ret);
1055
1056         if (result)
1057                 g_variant_unref(result);
1058
1059         if (ret != DBUS_RELEASE_NAME_REPLY_RELEASED) {
1060
1061                 if (ret == DBUS_RELEASE_NAME_REPLY_NON_EXISTENT) {
1062                         _LOGE("Port Not exist");
1063                         return MESSAGE_PORT_ERROR_PORT_NOT_FOUND;
1064                 } else if (ret == DBUS_RELEASE_NAME_REPLY_NOT_OWNER) {
1065                         _LOGE("Try to release not owned name. MESSAGE_PORT_ERROR_INVALID_PARAMETER");
1066                         return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
1067                 }
1068         }
1069         g_hash_table_remove(__local_port_info, GINT_TO_POINTER(local_port_id));
1070
1071         return MESSAGE_PORT_ERROR_NONE;
1072 }