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