0090517971c1ad09640a0f4de39374cae623f3cc
[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
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
412 static int __create_port_key_info(
413                 port_list_info_s *port_info,
414                 port_key_info_s **key_info)
415 {
416         int ret_val = MESSAGE_PORT_ERROR_NONE;
417         port_key_info_s *_key_info = (port_key_info_s *)
418                 calloc(1, sizeof(port_key_info_s));
419         if (_key_info == NULL) {
420                 ret_val = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
421                 _LOGE("out of memory");
422                 goto out;
423         }
424
425         _key_info->port_name = strdup(port_info->port_name);
426         if (_key_info->port_name == NULL) {
427                 ret_val = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
428                 _LOGE("out of memory");
429                 goto out;
430         }
431
432         _key_info->is_trusted = port_info->is_trusted;
433
434         _key_info->remote_app_id = strdup(port_info->remote_app_info->remote_app_id);
435         if (_key_info->remote_app_id == NULL) {
436                 ret_val = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
437                 _LOGE("out of memory");
438                 goto out;
439         }
440
441 out:
442         if (ret_val == MESSAGE_PORT_ERROR_NONE) {
443                 *key_info = _key_info;
444         } else {
445                 if (_key_info) {
446                         FREE_AND_NULL(_key_info->port_name);
447                         FREE_AND_NULL(_key_info->remote_app_id);
448                         free(_key_info);
449                 }
450         }
451         return ret_val;
452 }
453
454 static int __get_remote_port_info(const char *remote_app_id, const char *remote_port, bool is_trusted,
455                 message_port_remote_app_info_s **mri, port_list_info_s **pli)
456 {
457         message_port_remote_app_info_s *remote_app_info = NULL;
458         port_list_info_s port_info;
459         GList *cb_list = NULL;
460         int ret_val = MESSAGE_PORT_ERROR_NONE;
461
462         remote_app_info = (message_port_remote_app_info_s *)g_hash_table_lookup(__remote_app_info, remote_app_id);
463         if (remote_app_info == NULL) {
464                 remote_app_info = __set_remote_app_info(remote_app_id, remote_port, is_trusted);
465
466                 if (remote_app_info == NULL) {
467                         ret_val = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
468                         goto out;
469                 }
470                 g_hash_table_insert(__remote_app_info, remote_app_info->remote_app_id, remote_app_info);
471         }
472         *mri = remote_app_info;
473
474         port_info.port_name = strdup(remote_port);
475         if (port_info.port_name == NULL) {
476                 ret_val = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
477                 goto out;
478         }
479         port_info.is_trusted = is_trusted;
480         cb_list = g_list_find_custom(remote_app_info->port_list, &port_info,
481                                         (GCompareFunc)__remote_port_compare_cb);
482         if (port_info.port_name)
483                 free(port_info.port_name);
484         if (cb_list == NULL) {
485                 port_list_info_s *tmp = __set_remote_port_info(remote_app_id, remote_port, is_trusted);
486                 if (tmp == NULL) {
487                         ret_val = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
488                         goto out;
489                 }
490                 remote_app_info->port_list = g_list_append(remote_app_info->port_list, tmp);
491                 tmp->remote_app_info = remote_app_info;
492                 *pli = tmp;
493         } else {
494                 *pli = (port_list_info_s *)cb_list->data;
495         }
496 out:
497
498         return ret_val;
499 }
500
501 int check_remote_port(const char *remote_app_id, const char *remote_port, bool is_trusted, bool *exist)
502 {
503         _LOGD("Check a remote port : [%s:%s]", remote_app_id, remote_port);
504
505         GVariant *result = NULL;
506         GError *err = NULL;
507         int ret_val = MESSAGE_PORT_ERROR_NONE;
508         char *bus_name = NULL;
509         message_port_remote_app_info_s *remote_app_info = NULL;
510         port_list_info_s *port_info = NULL;
511         int local_reg_id = 0;
512         message_port_local_port_info_s *mi = NULL;
513         gboolean name_exist = false;
514
515         if (!_initialized) {
516                 if (!__initialize())
517                         return MESSAGE_PORT_ERROR_IO_ERROR;
518         }
519
520         _LOGD("remote_app_id, app_id :[%s : %s] ", remote_app_id, app_id);
521
522         ret_val = __get_remote_port_info(remote_app_id, remote_port, is_trusted, &remote_app_info, &port_info);
523         if (ret_val != MESSAGE_PORT_ERROR_NONE)
524                 return ret_val;
525
526         /* self check */
527         if (strcmp(remote_app_id, app_id) == 0) {
528
529                 _LOGD("__is_local_port_registed ");
530                 if (!is_local_port_registed(remote_port, is_trusted, &local_reg_id, &mi))
531                         *exist = false;
532                 else
533                         *exist = true;
534
535                 _LOGD("__is_local_port_registed : %d ", *exist);
536                 return MESSAGE_PORT_ERROR_NONE;
537         }
538
539         port_info->exist = false;
540         bus_name = port_info->encoded_bus_name;
541
542         result = g_dbus_connection_call_sync(
543                         gdbus_conn,
544                         DBUS_SERVICE_DBUS,
545                         DBUS_PATH_DBUS,
546                         DBUS_INTERFACE_DBUS,
547                         "NameHasOwner",
548                         g_variant_new("(s)", bus_name),
549                         G_VARIANT_TYPE("(b)"),
550                         G_DBUS_CALL_FLAGS_NONE,
551                         -1,
552                         NULL,
553                         &err);
554
555         if (err || (result == NULL)) {
556                 if (err) {
557                         _LOGE("No reply. error = %s", err->message);
558                         g_error_free(err);
559                 }
560                 ret_val = MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE;
561         } else {
562                 g_variant_get(result, "(b)", &name_exist);
563
564                 if (!name_exist) {
565                         _LOGI("Name not exist %s", bus_name);
566                         *exist = false;
567                         ret_val = MESSAGE_PORT_ERROR_NONE;
568                 } else {
569
570                         if (is_trusted) {
571                                 if (remote_app_info->certificate_info != CERTIFICATE_MATCH) {
572                                         if (!is_preloaded(app_id, remote_app_id)) {
573                                                 if (check_certificate(app_id, remote_app_id) != MESSAGE_PORT_ERROR_NONE) {
574                                                         ret_val = MESSAGE_PORT_ERROR_CERTIFICATE_NOT_MATCH;
575                                                         goto out;
576                                                 }
577                                         }
578                                         remote_app_info->certificate_info = CERTIFICATE_MATCH;
579                                 }
580                         }
581                         port_info->exist = true;
582                         *exist = true;
583                         ret_val = MESSAGE_PORT_ERROR_NONE;
584                 }
585         }
586 out:
587         if (result)
588                 g_variant_unref(result);
589
590         if (ret_val != MESSAGE_PORT_ERROR_NONE || !name_exist)
591                 __free_port_info((gpointer)port_info);
592
593         return ret_val;
594 }
595
596 /* LCOV_EXCL_START */
597 static int __send_delayed_message(int sockfd, delay_message_info_s *message)
598 {
599         unsigned int nb = 0;
600         int sequence = message->sequence - 1;
601         int ret = MESSAGE_PORT_ERROR_NONE;
602         bool is_startline = true;
603         int offset = 0;
604
605         _LOGI("send_delayed_message : sockfd (%d) sequence(%d) sent byte(%d)",
606                 sockfd, message->sequence, message->sent_bytes);
607
608         switch (message->sequence) {
609         case SEQUENCE_START:
610                 sequence++;
611                 is_startline = false;
612
613         case SEQUENCE_PORT_LEN:
614                 if (is_startline)
615                         offset = message->sent_bytes;
616
617                 ret = write_socket(sockfd, ((char *)&message->local_port_len) + offset,
618                                 sizeof(message->local_port_len) - offset, &nb, &sequence);
619                 if (ret != MESSAGE_PORT_ERROR_NONE) {
620                         _LOGE("write local_port_len fail");
621                         goto out;
622                 }
623                 offset = 0;
624                 is_startline = false;
625
626         case SEQUENCE_PORT_NAME:
627                 if (is_startline)
628                         offset = message->sent_bytes;
629
630                 if (message->local_port_len > 0)
631                         ret = write_socket(sockfd, message->local_port_name + offset,
632                                 message->local_port_len - offset , &nb, &sequence);
633                 else
634                         sequence++;
635
636                 if (ret != MESSAGE_PORT_ERROR_NONE) {
637                         _LOGE("write local_port fail");
638                         goto out;
639                 }
640                 offset = 0;
641                 is_startline = false;
642
643         case SEQUENCE_BIDIRECTION:
644                 if (is_startline)
645                         offset = message->sent_bytes;
646
647                 ret = write_socket(sockfd, ((char *)&message->is_bidirection) + offset,
648                                 sizeof(message->is_bidirection) - offset, &nb, &sequence);
649                 if (ret != MESSAGE_PORT_ERROR_NONE) {
650                         _LOGE("write is_bidirection fail");
651                         goto out;
652                 }
653                 offset = 0;
654                 is_startline = false;
655
656         case SEQUENCE_TRUSTED:
657                 if (is_startline)
658                         offset = message->sent_bytes;
659
660                 ret = write_socket(sockfd, ((char *)&message->local_trusted) + offset,
661                                 sizeof(message->local_trusted) - offset, &nb, &sequence);
662                 if (ret != MESSAGE_PORT_ERROR_NONE) {
663                         _LOGE("write local_trusted fail");
664                         goto out;
665                 }
666                 offset = 0;
667                 is_startline = false;
668
669         case SEQUENCE_DTAT_LEN:
670                 if (is_startline)
671                         offset = message->sent_bytes;
672
673                 ret = write_socket(sockfd, ((char *)&message->data_len) + offset,
674                                 sizeof(message->data_len) - offset, &nb, &sequence);
675                 if (ret != MESSAGE_PORT_ERROR_NONE) {
676                         _LOGE("write data_len fail");
677                         goto out;
678                 }
679                 offset = 0;
680                 is_startline = false;
681
682         case SEQUENCE_DATA:
683                 if (is_startline)
684                         offset = message->sent_bytes;
685
686                 ret = write_socket(sockfd, (char *)message->data + offset,
687                         message->data_len - offset, &nb, &sequence);
688
689                 if (ret != MESSAGE_PORT_ERROR_NONE) {
690                         _LOGE("write data fail");
691                         goto out;
692                 }
693                 offset = 0;
694                 is_startline = false;
695
696         default:
697                 ret = MESSAGE_PORT_ERROR_NONE;
698
699         }
700
701 out:
702         if (ret == MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE) {
703                 if (is_startline)
704                         message->sent_bytes += nb;
705                 else
706                         message->sent_bytes = nb;
707
708                 message->sequence = sequence;
709                 _LOGE("send_delayed_message fail : sockfd (%d) sequence(%d) sent byte(%d)",
710                         sockfd, message->sequence, message->sent_bytes);
711         }
712
713         return ret;
714
715 }
716 /* LCOV_EXCL_STOP */
717
718 static bool __validate_delay_port_info(delay_port_info *delay_info)
719 {
720         message_port_remote_app_info_s *found_remote_port_info;
721         GList *cb_list;
722
723         found_remote_port_info =
724                 (message_port_remote_app_info_s *)g_hash_table_lookup(
725                                 __remote_app_info, delay_info->key_info->remote_app_id);
726         if (found_remote_port_info == NULL)
727                 return false;
728
729         cb_list = g_list_find(found_remote_port_info->port_list, delay_info->port_info);
730         if (cb_list == NULL)
731                 return false;
732
733         return true;
734 }
735
736 /* LCOV_EXCL_START */
737 static int __pop_delayed_message(port_list_info_s *port_info)
738 {
739         delay_message_info_s *message;
740         int ret;
741
742         if (port_info->delayed_message_list == NULL)
743                 return MESSAGE_PORT_ERROR_NONE;
744
745         message = g_list_nth_data(port_info->delayed_message_list, 0);
746         ret = __send_delayed_message(port_info->send_sock_fd, message);
747
748         if (ret != MESSAGE_PORT_ERROR_NONE)
749                 return ret;
750
751         port_info->delayed_message_size -= message->size;
752         port_info->delayed_message_list = g_list_remove(port_info->delayed_message_list, message);
753         _LOGI("pop : delayed_message_size (%d), count(%d)",
754                         port_info->delayed_message_size,
755                         g_list_length(port_info->delayed_message_list));
756
757         __free_delay_message_info(message);
758
759         return MESSAGE_PORT_ERROR_NONE;
760
761 }
762
763 static gboolean __process_delayed_message(gint fd, GIOCondition cond, gpointer data)
764 {
765         delay_port_info *delay_info = (delay_port_info *)data;
766         port_list_info_s *port_info = delay_info->port_info;
767
768         int ret;
769
770         if (port_info == NULL)
771                 return G_SOURCE_REMOVE;
772
773         message_port_lock_mutex();
774
775         if (__validate_delay_port_info(delay_info) == false) {
776                 message_port_unlock_mutex();
777                 return G_SOURCE_REMOVE;
778         }
779
780         if (port_info->delayed_message_list == NULL) {
781                 port_info->delayed_message_size = 0;
782                 port_info->delay_src_id = 0;
783                 message_port_unlock_mutex();
784                 return G_SOURCE_REMOVE;
785         } else {
786                 ret = __pop_delayed_message(port_info);
787                 if (ret == MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE) {
788                         message_port_unlock_mutex();
789                         return G_SOURCE_CONTINUE;
790                 } else if (ret == MESSAGE_PORT_ERROR_IO_ERROR) {
791                         port_info->delay_src_id = 0;
792                         message_port_unlock_mutex();
793                         return G_SOURCE_REMOVE;
794                 }
795         }
796
797         message_port_unlock_mutex();
798
799         return G_SOURCE_CONTINUE;
800 }
801 /* LCOV_EXCL_STOP */
802
803 /* LCOV_EXCL_START */
804 static int __push_delayed_message(port_list_info_s *port_info,
805         int sequence,
806         bundle_raw *kb_data,
807         int data_len,
808         unsigned int sent_bytes,
809         const char *local_port,
810         bool local_trusted,
811         bool is_bidirection)
812 {
813 #define QUEUE_SIZE_MAX (1024 * 1024) /* 1MB per remote port (MAX) */
814
815         unsigned int tmp_size;
816         unsigned int message_size;
817         int ret = MESSAGE_PORT_ERROR_NONE;
818         delay_port_info *delay_info;
819
820         if (port_info->delayed_message_size >= QUEUE_SIZE_MAX) {
821                 _LOGE("cache fail : delayed_message_size (%d), count(%d)",
822                         port_info->delayed_message_size, g_list_length(port_info->delayed_message_list));
823                 return MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE;
824         }
825
826         delay_message_info_s *message = (delay_message_info_s *)calloc(1, sizeof(delay_message_info_s));
827         retvm_if(!message, MESSAGE_PORT_ERROR_OUT_OF_MEMORY, "Malloc failed");
828
829         message_size = (unsigned int)sizeof(delay_message_info_s);
830
831         message->sequence = sequence;
832         tmp_size = (unsigned int)strlen(local_port) + 1;
833         message_size += tmp_size;
834         message->local_port_len = tmp_size;
835         message->local_port_name = strdup(local_port);
836         if (message->local_port_name == NULL) {
837                 _LOGE("local_port_name strdup fail");
838                 ret = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
839                 goto out;
840         }
841         message->is_bidirection = is_bidirection;
842         message->local_trusted = local_trusted;
843         message_size += data_len;
844         message->data_len = data_len;
845         message->data = (bundle_raw *)strdup((const char *)kb_data);
846         if (message->data == NULL) {
847                 _LOGE("data strdup fail");
848                 ret = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
849                 goto out;
850         }
851
852
853         message->sent_bytes = sent_bytes;
854         message->size = message_size;
855         port_info->delayed_message_size += message_size;
856
857         port_info->delayed_message_list = g_list_append(port_info->delayed_message_list, message);
858
859         if (port_info->delay_src_id == 0) {
860                 delay_info = (delay_port_info *)calloc(1, sizeof(delay_port_info));
861                 if (delay_info == NULL) {
862                         _LOGE("out of memory");
863                         ret = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
864                         goto out;
865                 }
866
867                 ret = __create_port_key_info(port_info, &delay_info->key_info);
868                 if (ret != MESSAGE_PORT_ERROR_NONE) {
869                         free(delay_info);
870                         goto out;
871                 }
872
873                 delay_info->port_info = port_info;
874
875                 port_info->delay_src_id = g_unix_fd_add_full(G_PRIORITY_DEFAULT,
876                                                 port_info->send_sock_fd, G_IO_OUT, __process_delayed_message,
877                                                 delay_info, __delay_socket_destroy_handler);
878         }
879
880         _LOGE("inserted : pm(%s) fd(%d) ms(%d) ds(%d) dlc(%d) sqn(%d) sb (%d)",
881                 port_info->port_name, port_info->send_sock_fd, message_size,
882                 port_info->delayed_message_size,
883                 g_list_length(port_info->delayed_message_list), sequence, sent_bytes);
884
885 out:
886         if (ret != MESSAGE_PORT_ERROR_NONE)
887                 __free_delay_message_info(message);
888
889         return ret;
890 }
891 /* LCOV_EXCL_STOP */
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
909 static int __message_port_send_async(port_list_info_s *port_info, bundle *kb, const char *local_port,
910                 bool local_trusted, bool is_bidirection)
911 {
912         int ret = 0;
913         int data_len;
914         unsigned int nb = 0;
915         bundle_raw *kb_data = NULL;
916         int sequence = SEQUENCE_START;
917
918         bundle_encode(kb, &kb_data, &data_len);
919         if (kb_data == NULL) {
920                 _LOGE("bundle encode fail");
921                 ret = MESSAGE_PORT_ERROR_INVALID_PARAMETER;
922                 goto out;
923         }
924
925         if (data_len > MAX_MESSAGE_SIZE) {
926                 _LOGE("bigger than max size\n");
927                 ret = MESSAGE_PORT_ERROR_MAX_EXCEEDED;
928                 goto out;
929         }
930
931         if (g_list_length(port_info->delayed_message_list) > 0) {
932                 ret = MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE;
933                 _LOGE("There are messages in the delayed_message_list (count %d)",
934                         g_list_length(port_info->delayed_message_list));
935                 goto out;
936         }
937
938         ret = write_string_to_socket(port_info->send_sock_fd, local_port,
939                         strlen(local_port) + 1, &nb, &sequence);
940         if (ret != MESSAGE_PORT_ERROR_NONE) {
941                 _LOGE("write local_port fail");
942                 goto out;
943         }
944
945         ret = write_socket(port_info->send_sock_fd, (char *)&is_bidirection,
946                         sizeof(is_bidirection), &nb, &sequence);
947         if (ret != MESSAGE_PORT_ERROR_NONE) {
948                 _LOGE("write is_bidirection fail");
949                 goto out;
950         }
951
952         ret = write_socket(port_info->send_sock_fd, (char *)&local_trusted,
953                         sizeof(local_trusted), &nb, &sequence);
954         if (ret != MESSAGE_PORT_ERROR_NONE) {
955                 _LOGE("write local_trusted fail");
956                 goto out;
957         }
958
959         ret = write_string_to_socket(port_info->send_sock_fd, (void *)kb_data,
960                         data_len, &nb, &sequence);
961         if (ret != MESSAGE_PORT_ERROR_NONE) {
962                 _LOGE("write kb_data fail");
963                 goto out;
964         }
965
966 out:
967
968         if (ret == MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE) {
969                 ret = __push_delayed_message(port_info, sequence, kb_data, data_len, nb,
970                         local_port, local_trusted, is_bidirection);
971                 if (ret != MESSAGE_PORT_ERROR_NONE) {
972                         if (kb_data)
973                                 free(kb_data);
974                         return MESSAGE_PORT_ERROR_IO_ERROR;
975                 }
976
977                 if (__can_write(port_info->send_sock_fd)) {
978                         while (g_list_length(port_info->delayed_message_list) != 0) {
979                                 ret = __pop_delayed_message(port_info);
980                                 if (ret != MESSAGE_PORT_ERROR_NONE) {
981                                         if (ret == MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE) {
982                                                 ret = MESSAGE_PORT_ERROR_NONE;
983                                         } else if (ret == MESSAGE_PORT_ERROR_IO_ERROR) {
984                                                 g_source_remove(port_info->delay_src_id);
985                                                 port_info->delay_src_id = 0;
986                                         }
987                                         break;
988                                 }
989                         }
990                 }
991         }
992
993         if (kb_data)
994                 free(kb_data);
995
996         return ret;
997 }
998
999 int send_message(const char *remote_appid, const char *remote_port,
1000                 const char *local_port, bool trusted_message, bool local_trusted, bool bi_dir, bundle *message)
1001 {
1002
1003         int ret = MESSAGE_PORT_ERROR_NONE;
1004         GUnixFDList *fd_list = NULL;
1005
1006         int len = 0;
1007         bundle_raw *raw = NULL;
1008         char *bus_name = NULL;
1009         char *interface_name = NULL;
1010
1011         message_port_remote_app_info_s *remote_app_info = NULL;
1012         port_list_info_s *port_info = NULL;
1013         GDBusMessage *msg = NULL;
1014         GError *err = NULL;
1015         GVariant *body = NULL;
1016         int sock_pair[2] = {0,};
1017         char buf[1024];
1018         port_key_info_s *__key_info;
1019
1020         if (!_initialized) {
1021                 if (!__initialize())
1022                         return MESSAGE_PORT_ERROR_IO_ERROR;
1023         }
1024
1025         ret = __get_remote_port_info(remote_appid, remote_port, trusted_message, &remote_app_info, &port_info);
1026         if (ret != MESSAGE_PORT_ERROR_NONE)
1027                 return ret;
1028
1029         if (port_info->exist == false) {
1030                 bool exist = false;
1031                 _LOGD("port exist check !!");
1032                 ret =  check_remote_port(remote_appid, remote_port, trusted_message, &exist);
1033                 if (ret != MESSAGE_PORT_ERROR_NONE) {
1034                         return ret;
1035                 } else if (!exist) {
1036                         return MESSAGE_PORT_ERROR_PORT_NOT_FOUND;
1037                 }
1038         }
1039
1040         if (port_info->send_sock_fd > 0) {
1041                 ret = __message_port_send_async(port_info, message,
1042                                 (local_port) ? local_port : "", local_trusted, bi_dir);
1043         } else {
1044
1045                 bus_name = port_info->encoded_bus_name;
1046                 interface_name = bus_name;
1047
1048                 if (bundle_encode(message, &raw, &len) != BUNDLE_ERROR_NONE) {
1049                         ret = MESSAGE_PORT_ERROR_INVALID_PARAMETER;
1050                         goto out;
1051                 }
1052
1053                 if (MAX_MESSAGE_SIZE < len) {
1054                         _LOGE("The size of message (%d) has exceeded the maximum limit.", len);
1055                         ret = MESSAGE_PORT_ERROR_MAX_EXCEEDED;
1056                         goto out;
1057                 }
1058
1059                 body = g_variant_new("(ssbbssbus)", app_id, (local_port) ? local_port : "", local_trusted, bi_dir,
1060                                 remote_appid, remote_port, trusted_message, len, raw);
1061                 if (strcmp(remote_appid, app_id) != 0) { /* self send */
1062
1063                         /*  if message-port fail to get socket pair, communicate using GDBus */
1064                         if (aul_request_message_port_socket_pair(sock_pair) != AUL_R_OK) {
1065                                 _LOGE("error create socket pair");
1066                         } else {
1067
1068                                 _LOGI("sock pair : %d, %d",
1069                                                 sock_pair[SOCK_PAIR_SENDER], sock_pair[SOCK_PAIR_RECEIVER]);
1070                                 fd_list = g_unix_fd_list_new();
1071                                 g_unix_fd_list_append(fd_list, sock_pair[SOCK_PAIR_RECEIVER], &err);
1072                                 if (err != NULL) {
1073                                         _LOGE("g_unix_fd_list_append [%s]", err->message);
1074                                         ret = MESSAGE_PORT_ERROR_IO_ERROR;
1075                                         g_error_free(err);
1076                                         goto out;
1077                                 }
1078
1079                                 port_info->send_sock_fd = sock_pair[SOCK_PAIR_SENDER];
1080                                 close(sock_pair[SOCK_PAIR_RECEIVER]);
1081                                 sock_pair[SOCK_PAIR_RECEIVER] = 0;
1082
1083                                 port_info->gio_read = g_io_channel_unix_new(port_info->send_sock_fd);
1084                                 if (!port_info->gio_read) {
1085                                         _LOGE("Error is %s\n", strerror_r(errno, buf, sizeof(buf)));
1086                                         ret = MESSAGE_PORT_ERROR_IO_ERROR;
1087                                         goto out;
1088                                 }
1089
1090                                 ret = __create_port_key_info(port_info, &__key_info);
1091                                 if (ret != MESSAGE_PORT_ERROR_NONE) {
1092                                         _LOGE("out of memory");
1093                                         goto out;
1094                                 }
1095
1096                                 port_info->g_src_id = g_io_add_watch_full(
1097                                                 port_info->gio_read,
1098                                                 G_PRIORITY_DEFAULT,
1099                                                 G_IO_IN | G_IO_HUP,
1100                                                 __socket_disconnect_handler,
1101                                                 (gpointer)__key_info,
1102                                                 __socket_destroy_handler);
1103                                 if (port_info->g_src_id == 0) {
1104                                         _LOGE("fail to add watch on socket");
1105                                         ret = MESSAGE_PORT_ERROR_IO_ERROR;
1106                                         __free_key_info(__key_info);
1107                                         goto out;
1108                                 }
1109
1110                         }
1111                 }
1112
1113                 msg = g_dbus_message_new_method_call(bus_name, MESSAGEPORT_OBJECT_PATH, interface_name, "send_message");
1114                 if (!msg) {
1115                         _LOGE("Can't allocate new method call");
1116                         ret = MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
1117                         goto out;
1118                 }
1119
1120                 g_dbus_message_set_unix_fd_list(msg, fd_list);
1121                 g_dbus_message_set_body(msg, body);
1122                 g_dbus_connection_send_message(gdbus_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &err);
1123                 if (err != NULL) {
1124                         _LOGE("No reply. error = %s", err->message);
1125                         g_error_free(err);
1126                         ret = MESSAGE_PORT_ERROR_IO_ERROR;
1127                         goto out;
1128                 }
1129         }
1130
1131 out:
1132         if (msg)
1133                 g_object_unref(msg);
1134         if (raw)
1135                 bundle_free_encoded_rawdata(&raw);
1136         if (fd_list)
1137                 g_object_unref(fd_list);
1138
1139         if (ret != MESSAGE_PORT_ERROR_NONE
1140                         && ret != MESSAGE_PORT_ERROR_MAX_EXCEEDED) {
1141                 __key_info = NULL;
1142                 __create_port_key_info(port_info, &__key_info);
1143
1144                 if (__key_info != NULL) {
1145                         __free_port_info_by_key(__key_info);
1146                         __free_key_info(__key_info);
1147                 }
1148
1149                 if (sock_pair[SOCK_PAIR_SENDER])
1150                         close(sock_pair[SOCK_PAIR_SENDER]);
1151                 if (sock_pair[SOCK_PAIR_RECEIVER])
1152                         close(sock_pair[SOCK_PAIR_RECEIVER]);
1153         }
1154
1155         return ret;
1156 }
1157
1158 int send_bidirectional_message(int id, const char *remote_app_id, const char *remote_port,  bool trusted_message, bundle *message)
1159 {
1160         message_port_local_port_info_s *local_info;
1161         int ret = get_local_port_info(id, &local_info);
1162         if (ret != MESSAGE_PORT_ERROR_NONE)
1163                 return ret;
1164
1165         _LOGD("bidirectional_message %s", local_info->port_name);
1166         return send_message(remote_app_id, remote_port,
1167                         local_info->port_name, trusted_message, local_info->is_trusted, true, message);
1168 }
1169
1170 static void __name_registered(GDBusConnection *connection,
1171                 const gchar *name,
1172                 const gchar *name_owner,
1173                 gpointer user_data)
1174 {
1175
1176         registered_callback_info_s *info = (registered_callback_info_s *)user_data;
1177         if (info == NULL) {
1178                 LOGE("NULL registered_callback_info");
1179                 return;
1180         }
1181
1182         _LOGI("watcher_id : %d, appeared name : %s , name_owner : %s\n", info->watcher_id, name, name_owner);
1183         if (info->registered_cb)
1184                 info->registered_cb(info->remote_app_id, info->remote_port, info->is_trusted, info->user_data);
1185 }
1186
1187 static void __name_unregistered(GDBusConnection *connection,
1188                 const gchar *name,
1189                 gpointer user_data)
1190 {
1191
1192         registered_callback_info_s *info = (registered_callback_info_s *)user_data;
1193         if (info == NULL) {
1194                 LOGE("NULL registered_callback_info");
1195                 return;
1196         }
1197
1198         _LOGI("watcher_id : %d, vanished name : %s\n", info->watcher_id, name);
1199         if (info->unregistered_cb)
1200                 info->unregistered_cb(info->remote_app_id, info->remote_port, info->is_trusted, info->user_data);
1201 }
1202
1203 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)
1204 {
1205         int ret_val = MESSAGE_PORT_ERROR_NONE;
1206         message_port_remote_app_info_s *remote_app_info = NULL;
1207         port_list_info_s *port_info = NULL;
1208
1209         if (!_initialized) {
1210                 if (!__initialize())
1211                         return MESSAGE_PORT_ERROR_IO_ERROR;
1212         }
1213         _LOGI("remote_app_id, app_id :[%s : %s] ", remote_app_id, app_id);
1214
1215         ret_val = __get_remote_port_info(remote_app_id, remote_port, trusted_remote_port, &remote_app_info, &port_info);
1216         if (ret_val != MESSAGE_PORT_ERROR_NONE) {
1217                 _LOGE("Failed to get remote_port_info %d", ret_val);
1218                 return ret_val;
1219         }
1220
1221         registered_callback_info_s *registered_cb_info = (registered_callback_info_s *)calloc(1, sizeof(registered_callback_info_s));
1222         retvm_if(!registered_cb_info, MESSAGE_PORT_ERROR_OUT_OF_MEMORY, "Malloc failed");
1223
1224         registered_cb_info->registered_cb = registered_cb;
1225         registered_cb_info->unregistered_cb = unregistered_cb;
1226         registered_cb_info->user_data = user_data;
1227         registered_cb_info->remote_app_id = strdup(remote_app_info->remote_app_id);
1228         if (registered_cb_info->remote_app_id == NULL) {
1229                 free(registered_cb_info);
1230                 _LOGE("Failed to alloc memory");
1231                 return MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
1232         }
1233         registered_cb_info->remote_port = strdup(port_info->port_name);
1234         if (registered_cb_info->remote_port == NULL) {
1235                 free(registered_cb_info->remote_app_id);
1236                 free(registered_cb_info);
1237                 _LOGE("Failed to alloc memory");
1238                 return MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
1239         }
1240
1241         registered_cb_info->watcher_id = g_bus_watch_name_on_connection(
1242                         gdbus_conn,
1243                         port_info->encoded_bus_name,
1244                         G_BUS_NAME_WATCHER_FLAGS_NONE,
1245                         __name_registered,
1246                         __name_unregistered,
1247                         registered_cb_info,
1248                         NULL);
1249         if (registered_cb_info->watcher_id == 0) {
1250                 free(registered_cb_info->remote_app_id);
1251                 free(registered_cb_info->remote_port);
1252                 free(registered_cb_info);
1253                 _LOGE("Failed to watch name");
1254                 return MESSAGE_PORT_ERROR_IO_ERROR;
1255         }
1256
1257         g_hash_table_insert(__registered_callback_info_hash,
1258                         GINT_TO_POINTER(registered_cb_info->watcher_id), registered_cb_info);
1259
1260         *watcher_id = registered_cb_info->watcher_id;
1261         return MESSAGE_PORT_ERROR_NONE;
1262 }
1263
1264 int remove_registration_event_cb(int watcher_id)
1265 {
1266         registered_callback_info_s *registered_cb_info = NULL;
1267         gboolean remove_result = FALSE;
1268
1269         if (watcher_id < 1)
1270                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
1271
1272         registered_cb_info = g_hash_table_lookup(__registered_callback_info_hash, GINT_TO_POINTER(watcher_id));
1273         if (registered_cb_info == NULL)
1274                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
1275
1276         _LOGI("unwatch_remote_port [%s : %s : %d] ", registered_cb_info->remote_app_id,
1277                 registered_cb_info->remote_port, watcher_id);
1278
1279         remove_result = g_hash_table_remove(__registered_callback_info_hash, GINT_TO_POINTER(watcher_id));
1280         if (!remove_result)
1281                 return MESSAGE_PORT_ERROR_IO_ERROR;
1282
1283         g_bus_unwatch_name(watcher_id);
1284
1285         return MESSAGE_PORT_ERROR_NONE;
1286 }
1287