a4d83cb8fe44af67f81c4028dcf13c34f3d6375e
[platform/core/appfw/message-port.git] / src / message_port_local.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 #include <pthread.h>
27
28 #include <glib.h>
29 #include <gio/gio.h>
30 #include <gio/gunixfdlist.h>
31 #include <glib-unix.h>
32
33 #include "message_port_log.h"
34 #include "message_port.h"
35 #include "message_port_remote.h"
36 #include "message_port_common.h"
37
38 #define MAX_RETRY_CNT 10
39 #define SOCK_PAIR_SENDER 0
40 #define SOCK_PAIR_RECEIVER 1
41
42 static bool _initialized = false;
43 static GHashTable *__remote_app_info;
44 static GHashTable *__registered_callback_info_hash;
45 static const int MAX_MESSAGE_SIZE = 16 * 1024;
46
47 enum __certificate_info_type {
48         UNKNOWN = 0,
49         CERTIFICATE_MATCH,
50         CERTIFICATE_NOT_MATCH,
51 };
52
53 typedef struct message_port_remote_port_info {
54         char *remote_app_id;
55         int certificate_info;
56         GList *port_list;
57 } message_port_remote_app_info_s;
58
59 typedef struct port_list_info {
60         message_port_remote_app_info_s *remote_app_info;
61         char *port_name;
62         char *encoded_bus_name;
63         bool is_trusted;
64         int send_sock_fd;
65         bool exist;
66         GIOChannel *gio_read;
67         int g_src_id;
68         GList *delayed_message_list;
69         unsigned int delayed_message_size;
70         int delay_src_id;
71 } port_list_info_s;
72
73 typedef struct port_key_info {
74         char *remote_app_id;
75         char *port_name;
76         bool is_trusted;
77 } port_key_info_s;
78
79 typedef struct delay_port_info {
80         port_key_info_s *key_info;
81         port_list_info_s *port_info;
82 } delay_port_info;
83
84 typedef struct registered_callback_info {
85         char *remote_app_id;
86         char *remote_port;
87         bool is_trusted;
88         int watcher_id;
89         void *user_data;
90         message_port_registration_event_cb registered_cb;
91         message_port_registration_event_cb unregistered_cb;
92 } registered_callback_info_s;
93
94 enum transmission_sequence {
95         SEQUENCE_START = 0,
96         SEQUENCE_PORT_LEN,
97         SEQUENCE_PORT_NAME,
98         SEQUENCE_BIDIRECTION,
99         SEQUENCE_TRUSTED,
100         SEQUENCE_DTAT_LEN,
101         SEQUENCE_DATA,
102         SEQUENCE_END
103 };
104
105 typedef struct delay_message {
106         unsigned int size;
107         unsigned int sent_bytes;
108         int sequence;
109         int local_port_len;
110         char *local_port_name;
111         bool is_bidirection;
112         bool local_trusted;
113         int data_len;
114         bundle_raw *data;
115 } delay_message_info_s;
116
117 /* LCOV_EXCL_START */
118 static void __free_delay_message_info(delay_message_info_s *message)
119 {
120         if (message != NULL) {
121                 FREE_AND_NULL(message->local_port_name);
122                 FREE_AND_NULL(message->data);
123                 FREE_AND_NULL(message);
124         }
125 }
126 /* LCOV_EXCL_STOP */
127
128 /* LCOV_EXCL_START */
129 static void __free_list_delay_message_info(gpointer data)
130 {
131         delay_message_info_s *message = (delay_message_info_s *)data;
132
133         if (message != NULL)
134                 __free_delay_message_info(message);
135 }
136 /* LCOV_EXCL_STOP */
137
138 /* LCOV_EXCL_START */
139 static void __clear_disconnect_socket(port_list_info_s *port_info)
140 {
141         GError *error = NULL;
142
143         if (port_info == NULL)
144                 return;
145
146         if (port_info->gio_read != NULL) {
147                 g_io_channel_shutdown(port_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(port_info->gio_read);
153                 port_info->gio_read = NULL;
154         }
155
156         if (port_info->g_src_id != 0) {
157                 g_source_remove(port_info->g_src_id);
158                 port_info->g_src_id = 0;
159         }
160
161         if (port_info->delay_src_id != 0) {
162                 g_source_remove(port_info->delay_src_id);
163                 port_info->delay_src_id = 0;
164         }
165
166         if (port_info->delayed_message_list != NULL) {
167                 g_list_free_full(port_info->delayed_message_list, __free_list_delay_message_info);
168                 /* can be reused */
169                 port_info->delayed_message_list = NULL;
170         }
171
172         port_info->delayed_message_size = 0;
173         port_info->send_sock_fd = 0;
174 }
175 /* LCOV_EXCL_STOP */
176
177 /* LCOV_EXCL_START */
178 static void __free_port_info(gpointer data)
179 {
180         port_list_info_s *port_info = (port_list_info_s *)data;
181         message_port_remote_app_info_s *remote_app_info;
182
183         if (port_info == NULL)
184                 return;
185
186         remote_app_info = port_info->remote_app_info;
187
188         _LOGI("__free_port_info : remote_app_id : %s port_name : %s",
189                         remote_app_info->remote_app_id,
190                         port_info->port_name);
191
192         remote_app_info->port_list = g_list_remove(remote_app_info->port_list,
193                         port_info);
194
195         __clear_disconnect_socket(port_info);
196
197         if (port_info->encoded_bus_name)
198                 free(port_info->encoded_bus_name);
199         if (port_info->port_name)
200                 free(port_info->port_name);
201
202         free(port_info);
203
204         if (g_list_length(remote_app_info->port_list) == 0) {
205                 g_hash_table_remove(__remote_app_info,
206                                 remote_app_info->remote_app_id);
207         }
208 }
209 /* LCOV_EXCL_STOP */
210
211 /* LCOV_EXCL_START */
212 static void __hash_destory_remote_value(gpointer data)
213 {
214         message_port_remote_app_info_s *mri = (message_port_remote_app_info_s *)data;
215         if (mri) {
216                 FREE_AND_NULL(mri->remote_app_id);
217                 if (mri->port_list)
218                         g_list_free_full(mri->port_list, __free_port_info);
219
220                 free(mri);
221         }
222 }
223 /* LCOV_EXCL_STOP */
224
225 static void __registered_callback_info_free(gpointer data)
226 {
227         registered_callback_info_s *callback_info = (registered_callback_info_s *)data;
228         if (callback_info == NULL)
229                 return;
230
231         if (callback_info->remote_app_id)
232                 free(callback_info->remote_app_id);
233
234         if (callback_info->remote_port)
235                 free(callback_info->remote_port);
236
237         free(callback_info);
238 }
239
240 static bool __initialize(void)
241 {
242         if (!initialized_common) {
243                 if (!initialize_common())
244                         return false;
245         }
246
247         if (__remote_app_info == NULL) {
248                 __remote_app_info = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, __hash_destory_remote_value);
249                 retvm_if(!__remote_app_info, false, "fail to create __remote_app_info");
250         }
251
252         if (__registered_callback_info_hash == NULL) {
253                 __registered_callback_info_hash = g_hash_table_new_full(g_direct_hash,  g_direct_equal, NULL, __registered_callback_info_free);
254                 retvm_if(!__registered_callback_info_hash, false, "fail to create __registered_callback_info_hash");
255         }
256
257         _initialized = true;
258
259         return true;
260 }
261
262 static int __remote_port_compare_cb(gconstpointer a, gconstpointer b)
263 {
264         port_list_info_s *key1 = (port_list_info_s *)a;
265         port_list_info_s *key2 = (port_list_info_s *)b;
266
267         if (key1->is_trusted == key2->is_trusted)
268                 return strcmp(key1->port_name, key2->port_name);
269
270         return 1;
271 }
272
273 static int __key_compare_cb(gconstpointer a, gconstpointer b)
274 {
275         port_list_info_s *key1 = (port_list_info_s *)a;
276         port_key_info_s *key2 = (port_key_info_s *)b;
277
278         if (key1->is_trusted == key2->is_trusted)
279                 return strcmp(key1->port_name, key2->port_name);
280
281         return 1;
282 }
283
284 static port_list_info_s *__set_remote_port_info(const char *remote_app_id, const char *remote_port, bool is_trusted)
285 {
286         int ret_val = MESSAGE_PORT_ERROR_NONE;
287         port_list_info_s *port_info = (port_list_info_s *)calloc(1, sizeof(port_list_info_s));
288
289         if (!port_info) {
290                 ret_val = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
291                 goto out;
292         }
293         port_info->port_name = strdup(remote_port);
294         if (!port_info->port_name) {
295                 ret_val = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
296                 goto out;
297         }
298         port_info->is_trusted = is_trusted;
299         port_info->encoded_bus_name = get_encoded_name(remote_app_id, remote_port, is_trusted);
300         if (port_info->encoded_bus_name == NULL) {
301                 ret_val = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
302                 goto out;
303         }
304         port_info->send_sock_fd = 0;
305 out:
306         if (ret_val != MESSAGE_PORT_ERROR_NONE) {
307                 if (port_info) {
308                         FREE_AND_NULL(port_info->port_name);
309                         FREE_AND_NULL(port_info->encoded_bus_name);
310                         free(port_info);
311                 }
312                 return NULL;
313         }
314         return port_info;
315 }
316
317 static message_port_remote_app_info_s *__set_remote_app_info(const char *remote_app_id, const char *remote_port, bool is_trusted)
318 {
319         message_port_remote_app_info_s *remote_app_info = NULL;
320         int ret_val = MESSAGE_PORT_ERROR_NONE;
321
322         remote_app_info = (message_port_remote_app_info_s *)calloc(1, sizeof(message_port_remote_app_info_s));
323         if (!remote_app_info) {
324                 ret_val = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
325                 goto out;
326         }
327
328         remote_app_info->remote_app_id = strdup(remote_app_id);
329         if (remote_app_info->remote_app_id == NULL) {
330                 ret_val = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
331                 goto out;
332         }
333
334 out:
335         if (ret_val != MESSAGE_PORT_ERROR_NONE) {
336                 if (remote_app_info) {
337                         FREE_AND_NULL(remote_app_info->remote_app_id);
338                         FREE_AND_NULL(remote_app_info);
339                 }
340                 return NULL;
341         }
342         return remote_app_info;
343 }
344
345
346 static void __free_port_info_by_key(port_key_info_s *key_info)
347 {
348         port_list_info_s *found_port_info;
349         message_port_remote_app_info_s *found_remote_port_info;
350         GList *cb_list;
351
352         found_remote_port_info =
353                 (message_port_remote_app_info_s *)g_hash_table_lookup(
354                                 __remote_app_info, key_info->remote_app_id);
355         if (found_remote_port_info == NULL)
356                 goto release;
357
358         cb_list = g_list_find_custom(found_remote_port_info->port_list, key_info,
359                                         (GCompareFunc)__key_compare_cb);
360         if (cb_list == NULL)
361                 goto release;
362
363         found_port_info = (port_list_info_s *)cb_list->data;
364         __free_port_info(found_port_info);
365
366         return;
367
368 release:
369         _LOGE("Not found port_info");
370 }
371
372 static void __free_key_info(port_key_info_s *key_info)
373 {
374         FREE_AND_NULL(key_info->port_name);
375         FREE_AND_NULL(key_info->remote_app_id);
376         FREE_AND_NULL(key_info);
377 }
378
379 static gboolean __socket_disconnect_handler(GIOChannel *gio,
380                 GIOCondition cond,
381                 gpointer data)
382 {
383         _LOGI("__socket_disconnect_handler %d", cond);
384         message_port_lock_mutex();
385         __free_port_info_by_key((port_key_info_s *)data);
386         message_port_unlock_mutex();
387
388         return FALSE;
389 }
390
391 static void __socket_destroy_handler(gpointer data)
392 {
393         _LOGI("__socket_destroy_handler");
394
395         port_key_info_s *key_info = (port_key_info_s *)data;
396         __free_key_info(key_info);
397 }
398
399
400 static void __delay_socket_destroy_handler(gpointer data)
401 {
402         _LOGI("__delay_socket_destroy_handler");
403         delay_port_info *delay_info = (delay_port_info *)data;
404
405         FREE_AND_NULL(delay_info->key_info->port_name);
406         FREE_AND_NULL(delay_info->key_info->remote_app_id);
407         FREE_AND_NULL(delay_info->key_info);
408         free(delay_info);
409 }
410
411 static int __create_port_key_info(
412                 port_list_info_s *port_info,
413                 port_key_info_s **key_info)
414 {
415         int ret_val = MESSAGE_PORT_ERROR_NONE;
416         port_key_info_s *_key_info = (port_key_info_s *)
417                 calloc(1, sizeof(port_key_info_s));
418         if (_key_info == NULL) {
419                 ret_val = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
420                 _LOGE("out of memory");
421                 goto out;
422         }
423
424         _key_info->port_name = strdup(port_info->port_name);
425         if (_key_info->port_name == NULL) {
426                 ret_val = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
427                 _LOGE("out of memory");
428                 goto out;
429         }
430
431         _key_info->is_trusted = port_info->is_trusted;
432
433         _key_info->remote_app_id = strdup(port_info->remote_app_info->remote_app_id);
434         if (_key_info->remote_app_id == NULL) {
435                 ret_val = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
436                 _LOGE("out of memory");
437                 goto out;
438         }
439
440 out:
441         if (ret_val == MESSAGE_PORT_ERROR_NONE) {
442                 *key_info = _key_info;
443         } else {
444                 if (_key_info) {
445                         FREE_AND_NULL(_key_info->port_name);
446                         FREE_AND_NULL(_key_info->remote_app_id);
447                         free(_key_info);
448                 }
449         }
450         return ret_val;
451 }
452
453 static int __get_remote_port_info(const char *remote_app_id, const char *remote_port, bool is_trusted,
454                 message_port_remote_app_info_s **mri, port_list_info_s **pli)
455 {
456         message_port_remote_app_info_s *remote_app_info = NULL;
457         port_list_info_s port_info;
458         GList *cb_list = NULL;
459         int ret_val = MESSAGE_PORT_ERROR_NONE;
460
461         remote_app_info = (message_port_remote_app_info_s *)g_hash_table_lookup(__remote_app_info, remote_app_id);
462         if (remote_app_info == NULL) {
463                 remote_app_info = __set_remote_app_info(remote_app_id, remote_port, is_trusted);
464
465                 if (remote_app_info == NULL) {
466                         ret_val = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
467                         goto out;
468                 }
469                 g_hash_table_insert(__remote_app_info, remote_app_info->remote_app_id, remote_app_info);
470         }
471         *mri = remote_app_info;
472
473         port_info.port_name = strdup(remote_port);
474         if (port_info.port_name == NULL) {
475                 ret_val = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
476                 goto out;
477         }
478         port_info.is_trusted = is_trusted;
479         cb_list = g_list_find_custom(remote_app_info->port_list, &port_info,
480                                         (GCompareFunc)__remote_port_compare_cb);
481         if (port_info.port_name)
482                 free(port_info.port_name);
483         if (cb_list == NULL) {
484                 port_list_info_s *tmp = __set_remote_port_info(remote_app_id, remote_port, is_trusted);
485                 if (tmp == NULL) {
486                         ret_val = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
487                         goto out;
488                 }
489                 remote_app_info->port_list = g_list_append(remote_app_info->port_list, tmp);
490                 tmp->remote_app_info = remote_app_info;
491                 *pli = tmp;
492         } else {
493                 *pli = (port_list_info_s *)cb_list->data;
494         }
495 out:
496
497         return ret_val;
498 }
499
500 int check_remote_port(const char *remote_app_id, const char *remote_port, bool is_trusted, bool *exist)
501 {
502         _LOGD("Check a remote port : [%s:%s]", remote_app_id, remote_port);
503
504         GVariant *result = NULL;
505         GError *err = NULL;
506         int ret_val = MESSAGE_PORT_ERROR_NONE;
507         char *bus_name = NULL;
508         message_port_remote_app_info_s *remote_app_info = NULL;
509         port_list_info_s *port_info = NULL;
510         int local_reg_id = 0;
511         message_port_local_port_info_s *mi = NULL;
512         gboolean name_exist = false;
513
514         if (!_initialized) {
515                 if (!__initialize())
516                         return MESSAGE_PORT_ERROR_IO_ERROR;
517         }
518
519         _LOGD("remote_app_id, app_id :[%s : %s] ", remote_app_id, app_id);
520
521         ret_val = __get_remote_port_info(remote_app_id, remote_port, is_trusted, &remote_app_info, &port_info);
522         if (ret_val != MESSAGE_PORT_ERROR_NONE)
523                 return ret_val;
524
525         /* self check */
526         if (strcmp(remote_app_id, app_id) == 0) {
527
528                 _LOGD("__is_local_port_registed ");
529                 if (!is_local_port_registed(remote_port, is_trusted, &local_reg_id, &mi))
530                         *exist = false;
531                 else
532                         *exist = true;
533
534                 _LOGD("__is_local_port_registed : %d ", *exist);
535                 return MESSAGE_PORT_ERROR_NONE;
536         }
537
538         port_info->exist = false;
539         bus_name = port_info->encoded_bus_name;
540
541         result = g_dbus_connection_call_sync(
542                         gdbus_conn,
543                         DBUS_SERVICE_DBUS,
544                         DBUS_PATH_DBUS,
545                         DBUS_INTERFACE_DBUS,
546                         "NameHasOwner",
547                         g_variant_new("(s)", bus_name),
548                         G_VARIANT_TYPE("(b)"),
549                         G_DBUS_CALL_FLAGS_NONE,
550                         -1,
551                         NULL,
552                         &err);
553
554         if (err || (result == NULL)) {
555                 if (err) {
556                         _LOGE("No reply. error = %s", err->message);
557                         g_error_free(err);
558                 }
559                 ret_val = MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE;
560         } else {
561                 g_variant_get(result, "(b)", &name_exist);
562
563                 if (!name_exist) {
564                         _LOGI("Name not exist %s", bus_name);
565                         *exist = false;
566                         ret_val = MESSAGE_PORT_ERROR_NONE;
567                 } else {
568
569                         if (is_trusted) {
570                                 if (remote_app_info->certificate_info != CERTIFICATE_MATCH) {
571                                         if (!is_preloaded(app_id, remote_app_id)) {
572                                                 if (check_certificate(app_id, remote_app_id) != MESSAGE_PORT_ERROR_NONE) {
573                                                         ret_val = MESSAGE_PORT_ERROR_CERTIFICATE_NOT_MATCH;
574                                                         goto out;
575                                                 }
576                                         }
577                                         remote_app_info->certificate_info = CERTIFICATE_MATCH;
578                                 }
579                         }
580                         port_info->exist = true;
581                         *exist = true;
582                         ret_val = MESSAGE_PORT_ERROR_NONE;
583                 }
584         }
585 out:
586         if (result)
587                 g_variant_unref(result);
588
589         if (ret_val != MESSAGE_PORT_ERROR_NONE || !name_exist)
590                 __free_port_info((gpointer)port_info);
591
592         return ret_val;
593 }
594
595 /* LCOV_EXCL_START */
596 static int __send_delayed_message(int sockfd, delay_message_info_s *message)
597 {
598         unsigned int nb = 0;
599         int sequence = message->sequence - 1;
600         int ret = MESSAGE_PORT_ERROR_NONE;
601         bool is_startline = true;
602         int offset = 0;
603
604         _LOGI("send_delayed_message : sockfd (%d) sequence(%d) sent byte(%d)",
605                 sockfd, message->sequence, message->sent_bytes);
606
607         switch (message->sequence) {
608         case SEQUENCE_START:
609                 sequence++;
610                 is_startline = false;
611
612         case SEQUENCE_PORT_LEN:
613                 if (is_startline)
614                         offset = message->sent_bytes;
615
616                 ret = write_socket(sockfd, ((char *)&message->local_port_len) + offset,
617                                 sizeof(message->local_port_len) - offset, &nb, &sequence);
618                 if (ret != MESSAGE_PORT_ERROR_NONE) {
619                         _LOGE("write local_port_len fail");
620                         goto out;
621                 }
622                 offset = 0;
623                 is_startline = false;
624
625         case SEQUENCE_PORT_NAME:
626                 if (is_startline)
627                         offset = message->sent_bytes;
628
629                 if (message->local_port_len > 0)
630                         ret = write_socket(sockfd, message->local_port_name + offset,
631                                 message->local_port_len - offset , &nb, &sequence);
632                 else
633                         sequence++;
634
635                 if (ret != MESSAGE_PORT_ERROR_NONE) {
636                         _LOGE("write local_port fail");
637                         goto out;
638                 }
639                 offset = 0;
640                 is_startline = false;
641
642         case SEQUENCE_BIDIRECTION:
643                 if (is_startline)
644                         offset = message->sent_bytes;
645
646                 ret = write_socket(sockfd, ((char *)&message->is_bidirection) + offset,
647                                 sizeof(message->is_bidirection) - offset, &nb, &sequence);
648                 if (ret != MESSAGE_PORT_ERROR_NONE) {
649                         _LOGE("write is_bidirection fail");
650                         goto out;
651                 }
652                 offset = 0;
653                 is_startline = false;
654
655         case SEQUENCE_TRUSTED:
656                 if (is_startline)
657                         offset = message->sent_bytes;
658
659                 ret = write_socket(sockfd, ((char *)&message->local_trusted) + offset,
660                                 sizeof(message->local_trusted) - offset, &nb, &sequence);
661                 if (ret != MESSAGE_PORT_ERROR_NONE) {
662                         _LOGE("write local_trusted fail");
663                         goto out;
664                 }
665                 offset = 0;
666                 is_startline = false;
667
668         case SEQUENCE_DTAT_LEN:
669                 if (is_startline)
670                         offset = message->sent_bytes;
671
672                 ret = write_socket(sockfd, ((char *)&message->data_len) + offset,
673                                 sizeof(message->data_len) - offset, &nb, &sequence);
674                 if (ret != MESSAGE_PORT_ERROR_NONE) {
675                         _LOGE("write data_len fail");
676                         goto out;
677                 }
678                 offset = 0;
679                 is_startline = false;
680
681         case SEQUENCE_DATA:
682                 if (is_startline)
683                         offset = message->sent_bytes;
684
685                 ret = write_socket(sockfd, (char *)message->data + offset,
686                         message->data_len - offset, &nb, &sequence);
687
688                 if (ret != MESSAGE_PORT_ERROR_NONE) {
689                         _LOGE("write data fail");
690                         goto out;
691                 }
692                 offset = 0;
693                 is_startline = false;
694
695         default:
696                 ret = MESSAGE_PORT_ERROR_NONE;
697
698         }
699
700 out:
701         if (ret == MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE) {
702                 if (is_startline)
703                         message->sent_bytes += nb;
704                 else
705                         message->sent_bytes = nb;
706
707                 message->sequence = sequence;
708                 _LOGE("send_delayed_message fail : sockfd (%d) sequence(%d) sent byte(%d)",
709                         sockfd, message->sequence, message->sent_bytes);
710         }
711
712         return ret;
713
714 }
715 /* LCOV_EXCL_STOP */
716
717 static bool __validate_delay_port_info(delay_port_info *delay_info)
718 {
719         message_port_remote_app_info_s *found_remote_port_info;
720         GList *cb_list;
721
722         found_remote_port_info =
723                 (message_port_remote_app_info_s *)g_hash_table_lookup(
724                                 __remote_app_info, delay_info->key_info->remote_app_id);
725         if (found_remote_port_info == NULL)
726                 return false;
727
728         cb_list = g_list_find(found_remote_port_info->port_list, delay_info->port_info);
729         if (cb_list == NULL)
730                 return false;
731
732         return true;
733 }
734 /* LCOV_EXCL_START */
735 static gboolean __process_delayed_message(gint fd, GIOCondition cond, gpointer data)
736 {
737         delay_port_info *delay_info = (delay_port_info *)data;
738         port_list_info_s *port_info = delay_info->port_info;
739         delay_message_info_s *message;
740         int ret;
741
742         if (port_info == NULL)
743                 return G_SOURCE_REMOVE;
744
745         message_port_lock_mutex();
746
747         if (__validate_delay_port_info(delay_info) == false) {
748                 message_port_unlock_mutex();
749                 return G_SOURCE_REMOVE;
750         }
751
752         if (port_info->delayed_message_list == NULL) {
753                 port_info->delayed_message_size = 0;
754                 port_info->delay_src_id = 0;
755                 message_port_unlock_mutex();
756                 return G_SOURCE_REMOVE;
757         } else {
758                 message = g_list_nth_data(port_info->delayed_message_list, 0);
759                 ret = __send_delayed_message(port_info->send_sock_fd, message);
760
761                 if (ret == MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE) {
762                         message_port_unlock_mutex();
763                         return G_SOURCE_CONTINUE;
764                 } else if (ret == MESSAGE_PORT_ERROR_IO_ERROR) {
765                         port_info->delay_src_id = 0;
766                         message_port_unlock_mutex();
767                         return G_SOURCE_REMOVE;
768                 }
769
770                 port_info->delayed_message_size -= message->size;
771
772                 port_info->delayed_message_list = g_list_remove(port_info->delayed_message_list, message);
773                 __free_delay_message_info(message);
774         }
775
776         message_port_unlock_mutex();
777
778         return G_SOURCE_CONTINUE;
779 }
780 /* LCOV_EXCL_STOP */
781
782 /* LCOV_EXCL_START */
783 static int __insert_delayed_message(port_list_info_s *port_info,
784         int sequence,
785         bundle_raw *kb_data,
786         int data_len,
787         unsigned int sent_bytes,
788         const char *local_port,
789         bool local_trusted,
790         bool is_bidirection)
791 {
792 #define QUEUE_SIZE_MAX (1024 * 1024) /* 1MB per remote port (MAX) */
793
794         unsigned int tmp_size;
795         unsigned int message_size;
796         int ret = MESSAGE_PORT_ERROR_NONE;
797         delay_port_info *delay_info;
798
799         if (port_info->delayed_message_size >= QUEUE_SIZE_MAX) {
800                 _LOGE("cache fail : delayed_message_size (%d), count(%d)",
801                         port_info->delayed_message_size, g_list_length(port_info->delayed_message_list));
802                 return MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE;
803         }
804
805         delay_message_info_s *message = (delay_message_info_s *)calloc(1, sizeof(delay_message_info_s));
806         retvm_if(!message, MESSAGE_PORT_ERROR_OUT_OF_MEMORY, "Malloc failed");
807
808         message_size = sizeof(delay_message_info_s);
809
810         message->sequence = sequence;
811         tmp_size = strlen(local_port) + 1;
812         message_size += tmp_size;
813         message->local_port_len = tmp_size;
814         message->local_port_name = strdup(local_port);
815         if (message->local_port_name == NULL) {
816                 _LOGE("local_port_name strdup fail");
817                 ret = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
818                 goto out;
819         }
820         message->is_bidirection = is_bidirection;
821         message->local_trusted = local_trusted;
822         message_size += data_len;
823         message->data_len = data_len;
824         message->data = (bundle_raw *)strdup((const char *)kb_data);
825         if (message->data == NULL) {
826                 _LOGE("data strdup fail");
827                 ret = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
828                 goto out;
829         }
830
831
832         message->sent_bytes = sent_bytes;
833         message->size = message_size;
834         port_info->delayed_message_size += message_size;
835
836         port_info->delayed_message_list = g_list_append(port_info->delayed_message_list, message);
837
838         if (port_info->delay_src_id == 0) {
839                 delay_info = (delay_port_info *)calloc(1, sizeof(delay_port_info));
840                 if (delay_info == NULL) {
841                         _LOGE("out of memory");
842                         ret = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
843                         goto out;
844                 }
845
846                 ret = __create_port_key_info(port_info, &delay_info->key_info);
847                 if (ret != MESSAGE_PORT_ERROR_NONE) {
848                         free(delay_info);
849                         goto out;
850                 }
851
852                 delay_info->port_info = port_info;
853
854                 port_info->delay_src_id = g_unix_fd_add_full(G_PRIORITY_DEFAULT,
855                                                 port_info->send_sock_fd, G_IO_OUT, __process_delayed_message,
856                                                 delay_info, __delay_socket_destroy_handler);
857         }
858
859         _LOGE("inserted : pm(%s) fd(%d) ms(%d) ds(%d) dlc(%d) sqn(%d) sb (%d)",
860                 port_info->port_name, port_info->send_sock_fd, message_size,
861                 port_info->delayed_message_size,
862                 g_list_length(port_info->delayed_message_list), sequence, sent_bytes);
863
864 out:
865         if (ret != MESSAGE_PORT_ERROR_NONE)
866                 __free_delay_message_info(message);
867
868         return ret;
869 }
870 /* LCOV_EXCL_STOP */
871
872 static int __message_port_send_async(port_list_info_s *port_info, bundle *kb, const char *local_port,
873                 bool local_trusted, bool is_bidirection)
874 {
875         int ret = 0;
876         int data_len;
877         unsigned int nb = 0;
878         bundle_raw *kb_data = NULL;
879         int sequence = SEQUENCE_START;
880
881         bundle_encode(kb, &kb_data, &data_len);
882         if (kb_data == NULL) {
883                 _LOGE("bundle encode fail");
884                 ret = MESSAGE_PORT_ERROR_INVALID_PARAMETER;
885                 goto out;
886         }
887
888         if (data_len > MAX_MESSAGE_SIZE) {
889                 _LOGE("bigger than max size\n");
890                 ret = MESSAGE_PORT_ERROR_MAX_EXCEEDED;
891                 goto out;
892         }
893
894         if (g_list_length(port_info->delayed_message_list) > 0) {
895                 ret = MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE;
896                 _LOGE("There are messages in the delayed_message_list (count %d)",
897                         g_list_length(port_info->delayed_message_list));
898                 goto out;
899         }
900
901         ret = write_string_to_socket(port_info->send_sock_fd, local_port,
902                         strlen(local_port) + 1, &nb, &sequence);
903         if (ret != MESSAGE_PORT_ERROR_NONE) {
904                 _LOGE("write local_port fail");
905                 goto out;
906         }
907
908         ret = write_socket(port_info->send_sock_fd, (char *)&is_bidirection,
909                         sizeof(is_bidirection), &nb, &sequence);
910         if (ret != MESSAGE_PORT_ERROR_NONE) {
911                 _LOGE("write is_bidirection fail");
912                 goto out;
913         }
914
915         ret = write_socket(port_info->send_sock_fd, (char *)&local_trusted,
916                         sizeof(local_trusted), &nb, &sequence);
917         if (ret != MESSAGE_PORT_ERROR_NONE) {
918                 _LOGE("write local_trusted fail");
919                 goto out;
920         }
921
922         ret = write_string_to_socket(port_info->send_sock_fd, (void *)kb_data,
923                         data_len, &nb, &sequence);
924         if (ret != MESSAGE_PORT_ERROR_NONE) {
925                 _LOGE("write kb_data fail");
926                 goto out;
927         }
928
929 out:
930         if (ret == MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE) {
931                 ret = __insert_delayed_message(port_info, sequence, kb_data, data_len, nb,
932                         local_port, local_trusted, is_bidirection);
933                 if (ret != MESSAGE_PORT_ERROR_NONE)
934                         ret = MESSAGE_PORT_ERROR_IO_ERROR;
935         }
936
937         if (kb_data)
938                 free(kb_data);
939
940         return ret;
941 }
942
943 int send_message(const char *remote_appid, const char *remote_port,
944                 const char *local_port, bool trusted_message, bool local_trusted, bool bi_dir, bundle *message)
945 {
946
947         int ret = MESSAGE_PORT_ERROR_NONE;
948         GUnixFDList *fd_list = NULL;
949
950         int len = 0;
951         bundle_raw *raw = NULL;
952         char *bus_name = NULL;
953         char *interface_name = NULL;
954
955         message_port_remote_app_info_s *remote_app_info = NULL;
956         port_list_info_s *port_info = NULL;
957         GDBusMessage *msg = NULL;
958         GError *err = NULL;
959         GVariant *body = NULL;
960         int sock_pair[2] = {0,};
961         char buf[1024];
962         port_key_info_s *__key_info;
963
964         if (!_initialized) {
965                 if (!__initialize())
966                         return MESSAGE_PORT_ERROR_IO_ERROR;
967         }
968
969         ret = __get_remote_port_info(remote_appid, remote_port, trusted_message, &remote_app_info, &port_info);
970         if (ret != MESSAGE_PORT_ERROR_NONE)
971                 return ret;
972
973         if (port_info->exist == false) {
974                 bool exist = false;
975                 _LOGD("port exist check !!");
976                 ret =  check_remote_port(remote_appid, remote_port, trusted_message, &exist);
977                 if (ret != MESSAGE_PORT_ERROR_NONE) {
978                         return ret;
979                 } else if (!exist) {
980                         return MESSAGE_PORT_ERROR_PORT_NOT_FOUND;
981                 }
982         }
983
984         if (port_info->send_sock_fd > 0) {
985                 ret = __message_port_send_async(port_info, message,
986                                 (local_port) ? local_port : "", local_trusted, bi_dir);
987         } else {
988
989                 bus_name = port_info->encoded_bus_name;
990                 interface_name = bus_name;
991
992                 if (bundle_encode(message, &raw, &len) != BUNDLE_ERROR_NONE) {
993                         ret = MESSAGE_PORT_ERROR_INVALID_PARAMETER;
994                         goto out;
995                 }
996
997                 if (MAX_MESSAGE_SIZE < len) {
998                         _LOGE("The size of message (%d) has exceeded the maximum limit.", len);
999                         ret = MESSAGE_PORT_ERROR_MAX_EXCEEDED;
1000                         goto out;
1001                 }
1002
1003                 body = g_variant_new("(ssbbssbus)", app_id, (local_port) ? local_port : "", local_trusted, bi_dir,
1004                                 remote_appid, remote_port, trusted_message, len, raw);
1005                 if (strcmp(remote_appid, app_id) != 0) { /* self send */
1006
1007                         /*  if message-port fail to get socket pair, communicate using GDBus */
1008                         if (aul_request_message_port_socket_pair(sock_pair) != AUL_R_OK) {
1009                                 _LOGE("error create socket pair");
1010                         } else {
1011
1012                                 _LOGI("sock pair : %d, %d",
1013                                                 sock_pair[SOCK_PAIR_SENDER], sock_pair[SOCK_PAIR_RECEIVER]);
1014                                 fd_list = g_unix_fd_list_new();
1015                                 g_unix_fd_list_append(fd_list, sock_pair[SOCK_PAIR_RECEIVER], &err);
1016                                 if (err != NULL) {
1017                                         _LOGE("g_unix_fd_list_append [%s]", err->message);
1018                                         ret = MESSAGE_PORT_ERROR_IO_ERROR;
1019                                         g_error_free(err);
1020                                         goto out;
1021                                 }
1022
1023                                 port_info->send_sock_fd = sock_pair[SOCK_PAIR_SENDER];
1024                                 close(sock_pair[SOCK_PAIR_RECEIVER]);
1025                                 sock_pair[SOCK_PAIR_RECEIVER] = 0;
1026
1027                                 port_info->gio_read = g_io_channel_unix_new(port_info->send_sock_fd);
1028                                 if (!port_info->gio_read) {
1029                                         _LOGE("Error is %s\n", strerror_r(errno, buf, sizeof(buf)));
1030                                         ret = MESSAGE_PORT_ERROR_IO_ERROR;
1031                                         goto out;
1032                                 }
1033
1034                                 ret = __create_port_key_info(port_info, &__key_info);
1035                                 if (ret != MESSAGE_PORT_ERROR_NONE) {
1036                                         _LOGE("out of memory");
1037                                         goto out;
1038                                 }
1039
1040                                 port_info->g_src_id = g_io_add_watch_full(
1041                                                 port_info->gio_read,
1042                                                 G_PRIORITY_DEFAULT,
1043                                                 G_IO_IN | G_IO_HUP,
1044                                                 __socket_disconnect_handler,
1045                                                 (gpointer)__key_info,
1046                                                 __socket_destroy_handler);
1047                                 if (port_info->g_src_id == 0) {
1048                                         _LOGE("fail to add watch on socket");
1049                                         ret = MESSAGE_PORT_ERROR_IO_ERROR;
1050                                         __free_key_info(__key_info);
1051                                         goto out;
1052                                 }
1053
1054                         }
1055                 }
1056
1057                 msg = g_dbus_message_new_method_call(bus_name, MESSAGEPORT_OBJECT_PATH, interface_name, "send_message");
1058                 if (!msg) {
1059                         _LOGE("Can't allocate new method call");
1060                         ret = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
1061                         goto out;
1062                 }
1063
1064                 g_dbus_message_set_unix_fd_list(msg, fd_list);
1065                 g_dbus_message_set_body(msg, body);
1066                 g_dbus_connection_send_message(gdbus_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &err);
1067                 if (err != NULL) {
1068                         _LOGE("No reply. error = %s", err->message);
1069                         g_error_free(err);
1070                         ret = MESSAGE_PORT_ERROR_IO_ERROR;
1071                         goto out;
1072                 }
1073         }
1074
1075 out:
1076         if (msg)
1077                 g_object_unref(msg);
1078         if (raw)
1079                 bundle_free_encoded_rawdata(&raw);
1080         if (fd_list)
1081                 g_object_unref(fd_list);
1082
1083         if (ret != MESSAGE_PORT_ERROR_NONE) {
1084                 __key_info = NULL;
1085                 __create_port_key_info(port_info, &__key_info);
1086
1087                 if (__key_info != NULL) {
1088                         __free_port_info_by_key(__key_info);
1089                         __free_key_info(__key_info);
1090                 }
1091
1092                 if (sock_pair[SOCK_PAIR_SENDER])
1093                         close(sock_pair[SOCK_PAIR_SENDER]);
1094                 if (sock_pair[SOCK_PAIR_RECEIVER])
1095                         close(sock_pair[SOCK_PAIR_RECEIVER]);
1096         }
1097
1098         return ret;
1099 }
1100
1101 int send_bidirectional_message(int id, const char *remote_app_id, const char *remote_port,  bool trusted_message, bundle *message)
1102 {
1103         message_port_local_port_info_s *local_info;
1104         int ret = get_local_port_info(id, &local_info);
1105         if (ret != MESSAGE_PORT_ERROR_NONE)
1106                 return ret;
1107
1108         _LOGD("bidirectional_message %s", local_info->port_name);
1109         return send_message(remote_app_id, remote_port,
1110                         local_info->port_name, trusted_message, local_info->is_trusted, true, message);
1111 }
1112
1113 static void __name_registered(GDBusConnection *connection,
1114                 const gchar *name,
1115                 const gchar *name_owner,
1116                 gpointer user_data)
1117 {
1118
1119         registered_callback_info_s *info = (registered_callback_info_s *)user_data;
1120         if (info == NULL) {
1121                 LOGE("NULL registered_callback_info");
1122                 return;
1123         }
1124
1125         _LOGI("watcher_id : %d, appeared name : %s , name_owner : %s\n", info->watcher_id, name, name_owner);
1126         if (info->registered_cb)
1127                 info->registered_cb(info->remote_app_id, info->remote_port, info->is_trusted, info->user_data);
1128 }
1129
1130 static void __name_unregistered(GDBusConnection *connection,
1131                 const gchar *name,
1132                 gpointer user_data)
1133 {
1134
1135         registered_callback_info_s *info = (registered_callback_info_s *)user_data;
1136         if (info == NULL) {
1137                 LOGE("NULL registered_callback_info");
1138                 return;
1139         }
1140
1141         _LOGI("watcher_id : %d, vanished name : %s\n", info->watcher_id, name);
1142         if (info->unregistered_cb)
1143                 info->unregistered_cb(info->remote_app_id, info->remote_port, info->is_trusted, info->user_data);
1144 }
1145
1146 int watch_remote_port(int *watcher_id, const char *remote_app_id, const char *remote_port, bool trusted_remote_port, message_port_registration_event_cb registered_cb, message_port_registration_event_cb unregistered_cb, void *user_data)
1147 {
1148         int ret_val = MESSAGE_PORT_ERROR_NONE;
1149         message_port_remote_app_info_s *remote_app_info = NULL;
1150         port_list_info_s *port_info = NULL;
1151
1152         if (!_initialized) {
1153                 if (!__initialize())
1154                         return MESSAGE_PORT_ERROR_IO_ERROR;
1155         }
1156         _LOGI("remote_app_id, app_id :[%s : %s] ", remote_app_id, app_id);
1157
1158         ret_val = __get_remote_port_info(remote_app_id, remote_port, trusted_remote_port, &remote_app_info, &port_info);
1159         if (ret_val != MESSAGE_PORT_ERROR_NONE) {
1160                 _LOGE("Failed to get remote_port_info %d", ret_val);
1161                 return ret_val;
1162         }
1163
1164         registered_callback_info_s *registered_cb_info = (registered_callback_info_s *)calloc(1, sizeof(registered_callback_info_s));
1165         retvm_if(!registered_cb_info, MESSAGE_PORT_ERROR_OUT_OF_MEMORY, "Malloc failed");
1166
1167         registered_cb_info->registered_cb = registered_cb;
1168         registered_cb_info->unregistered_cb = unregistered_cb;
1169         registered_cb_info->user_data = user_data;
1170         registered_cb_info->remote_app_id = strdup(remote_app_info->remote_app_id);
1171         if (registered_cb_info->remote_app_id == NULL) {
1172                 free(registered_cb_info);
1173                 _LOGE("Failed to alloc memory");
1174                 return MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
1175         }
1176         registered_cb_info->remote_port = strdup(port_info->port_name);
1177         if (registered_cb_info->remote_port == NULL) {
1178                 free(registered_cb_info->remote_app_id);
1179                 free(registered_cb_info);
1180                 _LOGE("Failed to alloc memory");
1181                 return MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
1182         }
1183
1184         registered_cb_info->watcher_id = g_bus_watch_name_on_connection(
1185                         gdbus_conn,
1186                         port_info->encoded_bus_name,
1187                         G_BUS_NAME_WATCHER_FLAGS_NONE,
1188                         __name_registered,
1189                         __name_unregistered,
1190                         registered_cb_info,
1191                         NULL);
1192         if (registered_cb_info->watcher_id == 0) {
1193                 free(registered_cb_info->remote_app_id);
1194                 free(registered_cb_info->remote_port);
1195                 free(registered_cb_info);
1196                 _LOGE("Failed to watch name");
1197                 return MESSAGE_PORT_ERROR_IO_ERROR;
1198         }
1199
1200         g_hash_table_insert(__registered_callback_info_hash,
1201                         GINT_TO_POINTER(registered_cb_info->watcher_id), registered_cb_info);
1202
1203         *watcher_id = registered_cb_info->watcher_id;
1204         return MESSAGE_PORT_ERROR_NONE;
1205 }
1206
1207 int remove_registration_event_cb(int watcher_id)
1208 {
1209         registered_callback_info_s *registered_cb_info = NULL;
1210         gboolean remove_result = FALSE;
1211
1212         if (watcher_id < 1)
1213                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
1214
1215         registered_cb_info = g_hash_table_lookup(__registered_callback_info_hash, GINT_TO_POINTER(watcher_id));
1216         if (registered_cb_info == NULL)
1217                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
1218
1219         remove_result = g_hash_table_remove(__registered_callback_info_hash, GINT_TO_POINTER(watcher_id));
1220         if (!remove_result)
1221                 return MESSAGE_PORT_ERROR_IO_ERROR;
1222
1223         g_bus_unwatch_name(watcher_id);
1224
1225         return MESSAGE_PORT_ERROR_NONE;
1226 }
1227