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