4 Copyright (c) 2015 Samsung Electronics Co., Ltd.
6 Licensed under the Apache License, Version 2.0 (the License);
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
20 * @file message-port.cpp
21 * @brief This is the implementation file for the MessagePort.
24 #include <sys/socket.h>
30 #include <openssl/md5.h>
32 #include <bundle_internal.h>
33 #include <pkgmgr-info.h>
36 #include <gio/gunixfdlist.h>
38 #include "message-port.h"
39 #include "message-port-log.h"
41 #define MAX_PACKAGE_STR_SIZE 512
42 #define MESSAGEPORT_BUS_NAME_PREFIX "org.tizen.messageport._"
43 #define MESSAGEPORT_OBJECT_PATH "/org/tizen/messageport"
44 #define MESSAGEPORT_INTERFACE_PREFIX "org.tizen.messageport._"
46 #define DBUS_SERVICE_DBUS "org.freedesktop.DBus"
47 #define DBUS_PATH_DBUS "/org/freedesktop/DBus"
48 #define DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
50 #define DBUS_RELEASE_NAME_REPLY_RELEASED 1 /* *< Service was released from the given name */
51 #define DBUS_RELEASE_NAME_REPLY_NON_EXISTENT 2 /* *< The given name does not exist on the bus */
52 #define DBUS_RELEASE_NAME_REPLY_NOT_OWNER 3 /* *< Service is not an owner of the given name */
54 #define MAX_RETRY_CNT 2
56 #define retvm_if(expr, val, fmt, arg...) do { \
59 _LOGE("(%s) -> %s() return", #expr, __func__); \
64 #define retv_if(expr, val) do { \
66 _LOGE("(%s) -> %s() return", #expr, __func__); \
71 #define FREE_AND_NULL(ptr) do { \
78 static bool _initialized = false;
79 static GDBusConnection *__gdbus_conn = NULL;
80 static char *__app_id;
81 static GHashTable *__local_port_info = NULL;
82 static GHashTable *__remote_port_info = NULL;;
83 static GHashTable *__sender_appid_hash = NULL;;
84 static GHashTable *__trusted_app_list_hash = NULL;
85 static const int MAX_MESSAGE_SIZE = 16 * 1024;
87 enum __certificate_info_type {
90 CERTIFICATE_NOT_MATCH,
93 typedef struct message_port_pkt {
94 int remote_port_name_len;
95 char *remote_port_name;
101 typedef struct message_port_callback_info {
102 messageport_message_cb callback;
106 GIOChannel *gio_read;
108 } message_port_callback_info_s;
110 typedef struct message_port_local_port_info {
111 messageport_message_cb callback;
115 } message_port_local_port_info_s;
117 typedef struct message_port_remote_port_info {
120 int certificate_info;
122 } message_port_remote_app_info_s;
124 typedef struct port_list_info {
126 char *encoded_bus_name;
133 static void __callback_info_free(message_port_callback_info_s *callback_info)
135 GError *error = NULL;
136 if (callback_info == NULL)
139 if (callback_info->remote_app_id)
140 free(callback_info->remote_app_id);
142 if (callback_info->gio_read != NULL) {
143 g_io_channel_shutdown(callback_info->gio_read, FALSE, &error);
145 _LOGE("g_io_channel_shutdown error : %s", error->message);
148 g_io_channel_unref(callback_info->gio_read);
149 callback_info->gio_read = NULL;
152 if (callback_info->g_src_id != 0) {
153 g_source_remove(callback_info->g_src_id);
154 callback_info->g_src_id = 0;
160 static char *__get_encoded_name(const char *remote_app_id, const char *port_name, bool is_trusted)
163 int prefix_len = strlen(MESSAGEPORT_BUS_NAME_PREFIX);
165 char *postfix = is_trusted ? "1" : "0";
167 unsigned char c[MD5_DIGEST_LENGTH] = {0};
168 char *md5_interface = NULL;
172 int encoded_bus_name_len = prefix_len + postfix_len + (MD5_DIGEST_LENGTH * 2) + 2;
173 int bus_name_len = strlen(remote_app_id) + strlen(port_name) + 2;
174 char *bus_name = (char *)calloc(bus_name_len, sizeof(char));
175 if (bus_name == NULL) {
176 _LOGE("bus_name calloc failed");
180 snprintf(bus_name, bus_name_len, "%s_%s", remote_app_id, port_name);
182 MD5_Init(&mdContext);
183 MD5_Update(&mdContext, bus_name, bus_name_len);
184 MD5_Final(c, &mdContext);
186 md5_interface = (char *)calloc(encoded_bus_name_len , sizeof(char));
187 if (md5_interface == NULL) {
191 _LOGE("md5_interface calloc failed!!");
195 snprintf(md5_interface, encoded_bus_name_len, "%s", MESSAGEPORT_BUS_NAME_PREFIX);
196 temp = md5_interface;
199 for (index = 0; index < MD5_DIGEST_LENGTH; index++) {
200 snprintf(temp, 3, "%02x", c[index]);
204 if (postfix && postfix_len > 0)
205 snprintf(temp, encoded_bus_name_len - (temp - md5_interface), "%s", postfix);
209 _LOGI("encoded_bus_name : %s ", md5_interface);
211 return md5_interface;
214 static int __remote_port_compare_cb(gconstpointer a, gconstpointer b)
216 port_list_info_s *key1 = (port_list_info_s *)a;
217 port_list_info_s *key2 = (port_list_info_s *)b;
219 if (key1->is_trusted == key2->is_trusted)
220 return strcmp(key1->port_name, key2->port_name);
226 static bool __is_preloaded(const char *local_appid, const char *remote_appid)
228 _LOGI("IsPreloaded");
230 bool preload_local = false;
231 bool preload_remote = false;
233 pkgmgrinfo_appinfo_h handle = NULL;
234 int ret = pkgmgrinfo_appinfo_get_usr_appinfo(local_appid, getuid(), &handle);
235 if (ret != PMINFO_R_OK) {
236 _LOGE("Failed to get the appinfo. %d", ret);
237 pkgmgrinfo_appinfo_destroy_appinfo(handle);
240 ret = pkgmgrinfo_appinfo_is_preload(handle, &preload_local);
241 if (ret != PMINFO_R_OK) {
242 _LOGE("Failed to check the preloaded application. %d", ret);
243 pkgmgrinfo_appinfo_destroy_appinfo(handle);
246 ret = pkgmgrinfo_appinfo_get_usr_appinfo(remote_appid, getuid(), &handle);
247 if (ret != PMINFO_R_OK) {
248 _LOGE("Failed to get the appinfo. %d", ret);
249 pkgmgrinfo_appinfo_destroy_appinfo(handle);
252 ret = pkgmgrinfo_appinfo_is_preload(handle, &preload_remote);
253 if (ret != PMINFO_R_OK) {
254 _LOGE("Failed to check the preloaded application. %d", ret);
255 pkgmgrinfo_appinfo_destroy_appinfo(handle);
259 if (preload_local && preload_remote) {
260 pkgmgrinfo_appinfo_destroy_appinfo(handle);
263 pkgmgrinfo_appinfo_destroy_appinfo(handle);
267 static int __check_certificate(const char *local_appid, const char *remote_appid)
269 _LOGI("CheckCertificate");
271 pkgmgrinfo_cert_compare_result_type_e res;
272 int ret = pkgmgrinfo_pkginfo_compare_usr_app_cert_info(local_appid, remote_appid, getuid(), &res);
274 _LOGE(":CheckCertificate() Failed");
275 return MESSAGEPORT_ERROR_IO_ERROR;
277 if (res != PMINFO_CERT_COMPARE_MATCH) {
278 _LOGE("CheckCertificate() Failed : MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH");
279 return MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH;
282 return MESSAGEPORT_ERROR_NONE;
285 static void on_name_appeared(GDBusConnection *connection,
287 const gchar *name_owner,
290 _LOGI("name appeared : %s %s", __app_id, name);
293 static void on_name_vanished(GDBusConnection *connection,
297 _LOGI("name vanished : %s", name);
298 port_list_info_s *pli = (port_list_info_s *)user_data;
299 g_bus_unwatch_name(pli->watcher_id);
303 static int __get_local_port_info(int id, message_port_local_port_info_s **info)
305 message_port_local_port_info_s *mi = (message_port_local_port_info_s *)g_hash_table_lookup(__local_port_info, GINT_TO_POINTER(id));
308 return MESSAGEPORT_ERROR_INVALID_PARAMETER;
311 return MESSAGEPORT_ERROR_NONE;
314 static port_list_info_s *__set_remote_port_info(const char *remote_app_id, const char *remote_port, bool is_trusted)
316 int ret_val = MESSAGEPORT_ERROR_NONE;
317 port_list_info_s *port_info = (port_list_info_s *)calloc(1, sizeof(port_list_info_s));
320 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
323 port_info->port_name = strdup(remote_port);
324 if (!port_info->port_name) {
325 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
328 port_info->is_trusted = is_trusted;
330 port_info->encoded_bus_name = __get_encoded_name(remote_app_id, remote_port, is_trusted);
331 if (port_info->encoded_bus_name == NULL) {
332 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
336 port_info->sock_pair[0] = 0;
337 port_info->sock_pair[1] = 0;
340 if (ret_val != MESSAGEPORT_ERROR_NONE) {
342 FREE_AND_NULL(port_info->port_name);
343 FREE_AND_NULL(port_info->encoded_bus_name);
351 static message_port_remote_app_info_s *__set_remote_app_info(const char *remote_app_id, const char *remote_port, bool is_trusted)
353 port_list_info_s *port_info = NULL;
354 message_port_remote_app_info_s *remote_app_info = NULL;
355 int ret_val = MESSAGEPORT_ERROR_NONE;
357 remote_app_info = (message_port_remote_app_info_s *)calloc(1, sizeof(message_port_remote_app_info_s));
358 if (!remote_app_info) {
359 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
363 remote_app_info->remote_app_id = strdup(remote_app_id);
364 if (remote_app_info->remote_app_id == NULL) {
365 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;;
369 port_info = __set_remote_port_info(remote_app_id, remote_port, is_trusted);
370 if (port_info == NULL) {
371 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
375 remote_app_info->port_list = g_list_append(remote_app_info->port_list, port_info);
378 if (ret_val != MESSAGEPORT_ERROR_NONE) {
379 if (remote_app_info) {
380 FREE_AND_NULL(remote_app_info->remote_app_id);
381 FREE_AND_NULL(remote_app_info);
385 return remote_app_info;
388 static int __get_remote_port_info(const char *remote_app_id, const char *remote_port, bool is_trusted,
389 message_port_remote_app_info_s **mri, port_list_info_s **pli)
391 message_port_remote_app_info_s *remote_app_info = NULL;
392 port_list_info_s port_info;
393 GList *cb_list = NULL;
394 int ret_val = MESSAGEPORT_ERROR_NONE;
396 remote_app_info = (message_port_remote_app_info_s *)g_hash_table_lookup(__remote_port_info, remote_app_id);
398 if (remote_app_info == NULL) {
399 remote_app_info = __set_remote_app_info(remote_app_id, remote_port, is_trusted);
401 if (remote_app_info == NULL) {
402 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
405 g_hash_table_insert(__remote_port_info, remote_app_info->remote_app_id, remote_app_info);
408 *mri = remote_app_info;
410 port_info.port_name = strdup(remote_port);
411 port_info.is_trusted = is_trusted;
412 cb_list = g_list_find_custom(remote_app_info->port_list, &port_info,
413 (GCompareFunc)__remote_port_compare_cb);
414 if (port_info.port_name)
415 free(port_info.port_name);
416 if (cb_list == NULL) {
417 port_list_info_s *tmp = __set_remote_port_info(remote_app_id, remote_port, is_trusted);
420 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
423 remote_app_info->port_list = g_list_append(remote_app_info->port_list, tmp);
425 g_hash_table_insert(__remote_port_info, (*pli)->encoded_bus_name, *pli);
427 *pli = (port_list_info_s *)cb_list->data;
435 static bool __is_local_port_registed(const char *local_port, bool trusted, int *local_id, message_port_local_port_info_s **lpi)
440 g_hash_table_iter_init(&iter, __local_port_info);
442 while (g_hash_table_iter_next(&iter, &key, &value)) {
443 message_port_local_port_info_s *mi = (message_port_local_port_info_s *)value;
445 if ((mi->is_trusted == trusted) && strcmp(mi->port_name, local_port) == 0) {
446 *local_id = mi->local_id;
455 static int __get_sender_pid(GDBusConnection *conn, const char *sender_name)
457 GDBusMessage *msg = NULL;
458 GDBusMessage *reply = NULL;
463 msg = g_dbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
464 "org.freedesktop.DBus", "GetConnectionUnixProcessID");
466 _LOGE("Can't allocate new method call");
470 g_dbus_message_set_body(msg, g_variant_new("(s)", sender_name));
471 reply = g_dbus_connection_send_message_with_reply_sync(conn, msg,
472 G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err);
476 _LOGE("Failed to get pid [%s]", err->message);
482 body = g_dbus_message_get_body(reply);
483 g_variant_get(body, "(u)", &pid);
489 g_object_unref(reply);
494 static int __write_socket(int fd,
497 unsigned int *bytes_write)
499 unsigned int left = nbytes;
504 while (left && (retry_cnt < MAX_RETRY_CNT)) {
505 nb = write(fd, buffer, left);
507 if (errno == EINTR) {
508 LOGE("__write_socket: EINTR error continue ...");
512 LOGE("__write_socket: ...error fd %d: errno %d\n", fd, errno);
513 return MESSAGEPORT_ERROR_IO_ERROR;
521 return MESSAGEPORT_ERROR_NONE;
524 static int __write_string_to_socket(int fd, const char *buffer, int string_len)
527 if (__write_socket(fd, (char *)&string_len, sizeof(string_len), &nb) != MESSAGEPORT_ERROR_NONE) {
528 _LOGE("write string_len fail");
529 return MESSAGEPORT_ERROR_IO_ERROR;
532 if (string_len > 0) {
533 if (__write_socket(fd, buffer, string_len, &nb) != MESSAGEPORT_ERROR_NONE) {
534 _LOGE("wirte buffer fail");
535 return MESSAGEPORT_ERROR_IO_ERROR;
538 return MESSAGEPORT_ERROR_NONE;
541 static int __read_socket(int fd,
544 unsigned int *bytes_read)
546 unsigned int left = nbytes;
551 while (left && (retry_cnt < MAX_RETRY_CNT)) {
552 nb = read(fd, buffer, left);
554 LOGE("__read_socket: ...read EOF, socket closed %d: nb %d\n", fd, nb);
555 return MESSAGEPORT_ERROR_IO_ERROR;
556 } else if (nb == -1) {
557 if (errno == EINTR) {
558 LOGE("__read_socket: EINTR error continue ...");
562 LOGE("__read_socket: ...error fd %d: errno %d\n", fd, errno);
563 return MESSAGEPORT_ERROR_IO_ERROR;
571 return MESSAGEPORT_ERROR_NONE;
574 static int __read_string_from_socket(int fd, char **buffer, int *string_len)
577 if (__read_socket(fd, (char *)string_len, sizeof(*string_len), &nb) != MESSAGEPORT_ERROR_NONE) {
578 LOGE("read socket fail");
579 return MESSAGEPORT_ERROR_IO_ERROR;
581 if (*string_len > 0) {
582 *buffer = (char *)calloc(*string_len, sizeof(char));
583 if (*buffer == NULL) {
584 LOGE("Out of memory.");
585 return MESSAGEPORT_ERROR_IO_ERROR;
587 if (__read_socket(fd, *buffer, *string_len, &nb) != MESSAGEPORT_ERROR_NONE) {
588 LOGE("read socket fail");
589 return MESSAGEPORT_ERROR_IO_ERROR;
592 return MESSAGEPORT_ERROR_NONE;
595 message_port_pkt_s *__message_port_recv_raw(int fd)
597 message_port_pkt_s *pkt = NULL;
600 pkt = (message_port_pkt_s *)calloc(sizeof(message_port_pkt_s), 1);
605 if (__read_string_from_socket(fd, (char **)&pkt->remote_port_name, &pkt->remote_port_name_len) != MESSAGEPORT_ERROR_NONE) {
606 LOGE("read socket fail: port_name");
607 free(pkt->remote_port_name);
612 if (__read_socket(fd, (char *)&pkt->is_bidirection, sizeof(pkt->is_bidirection), &nb) != MESSAGEPORT_ERROR_NONE) {
613 LOGE("read socket fail: is_bidirection");
614 free(pkt->remote_port_name);
619 if (__read_string_from_socket(fd, (char **)&pkt->data, &pkt->data_len) != MESSAGEPORT_ERROR_NONE) {
620 LOGE("read socket fail: data");
621 free(pkt->remote_port_name);
629 static gboolean __socket_request_handler(GIOChannel *gio,
634 message_port_callback_info_s *mi;
635 message_port_pkt_s *pkt;
637 GError *error = NULL;
639 mi = (message_port_callback_info_s *)data;
642 g_io_channel_shutdown(gio, FALSE, &error);
644 _LOGE("g_io_channel_shutdown error : %s", error->message);
647 g_io_channel_unref(gio);
651 if (cond == G_IO_HUP) {
653 _LOGI("socket G_IO_HUP");
654 __callback_info_free(mi);
659 if ((fd = g_io_channel_unix_get_fd(gio)) < 0) {
660 _LOGE("fail to get fd from io channel");
661 __callback_info_free(mi);
665 if ((pkt = __message_port_recv_raw(fd)) == NULL) {
666 _LOGE("recv error on SOCKET");
667 __callback_info_free(mi);
671 kb = bundle_decode(pkt->data, pkt->data_len);
673 if (pkt->is_bidirection)
674 mi->callback(mi->local_id, mi->remote_app_id, pkt->remote_port_name, mi->is_trusted, kb, NULL);
676 mi->callback(mi->local_id, mi->remote_app_id, NULL, mi->is_trusted, kb, NULL);
679 if (pkt->remote_port_name)
680 free(pkt->remote_port_name);
690 static bool send_message(GVariant *parameters, GDBusMethodInvocation *invocation)
692 char *local_port = NULL;
693 char *local_appid = NULL;
694 char *remote_appid = NULL;
695 char *remote_port = NULL;
696 gboolean local_trusted = false;
697 gboolean remote_trusted = false;
698 gboolean bi_dir = false;
702 bundle_raw *raw = NULL;
703 message_port_local_port_info_s *mi;
704 message_port_callback_info_s *callback_info;
705 int local_reg_id = 0;
707 g_variant_get(parameters, "(ssbbssbus)", &local_appid, &local_port, &local_trusted, &bi_dir,
708 &remote_appid, &remote_port, &remote_trusted, &len, &raw);
711 _LOGE("Invalid argument : remote_port is NULL");
715 _LOGE("Invalid argument : remote_appid is NULL");
718 if (!__is_local_port_registed(remote_port, remote_trusted, &local_reg_id, &mi)) {
719 _LOGE("Invalid argument : remote_port:(%s) trusted(%d)", remote_port, remote_trusted);
723 _LOGE("Invalid argument : local_appid");
727 _LOGE("Invalid argument : local_port");
730 if (strcmp(remote_appid, __app_id) != 0) {
731 _LOGE("Invalid argument : remote_appid (%s)", remote_appid);
734 if (strcmp(remote_port, mi->port_name) != 0) {
735 _LOGE("Invalid argument : remote_port (%s)", remote_port);
739 _LOGE("Invalid argument : data_len");
742 if (remote_trusted) {
743 if (g_hash_table_lookup(__trusted_app_list_hash, (gpointer)local_appid) == NULL) {
744 if (!__is_preloaded(local_appid, remote_appid)) {
745 /* Check the certificate */
746 int ret = __check_certificate(local_appid, remote_appid);
747 if (ret == MESSAGEPORT_ERROR_NONE)
748 g_hash_table_insert(__trusted_app_list_hash, local_appid, "TRUE");
750 _LOGE("The application (%s) is not signed with the same certificate",
758 callback_info = (message_port_callback_info_s *)calloc(1, sizeof(message_port_callback_info_s));
759 if (callback_info == NULL)
762 callback_info->local_id = mi->local_id;
763 callback_info->remote_app_id = strdup(local_appid);
764 callback_info->callback = mi->callback;
765 callback_info->is_trusted = local_trusted;
767 GError *error = NULL;
768 GDBusMessage *msg = g_dbus_method_invocation_get_message(invocation);
770 GUnixFDList *fd_list = g_dbus_message_get_unix_fd_list(msg);
771 int fd = g_unix_fd_list_get(fd_list, 0, &error);
773 LOGE("g_unix_fd_list_get fail : %s", error->message);
777 LOGI("g_unix_fd_list_get fd: [%d]", fd);
781 callback_info->gio_read = g_io_channel_unix_new(fd);
782 if (!callback_info->gio_read) {
783 _LOGE("Error is %s\n", strerror(errno));
784 __callback_info_free(callback_info);
788 callback_info->g_src_id = g_io_add_watch(callback_info->gio_read, G_IO_IN | G_IO_HUP,
789 __socket_request_handler, (gpointer)callback_info);
790 if (callback_info->g_src_id == 0) {
791 _LOGE("fail to add watch on socket");
792 __callback_info_free(callback_info);
798 data = bundle_decode(raw, len);
799 bundle_free_encoded_rawdata(&raw);
802 _LOGE("Invalid argument : message");
806 LOGI("call calback %s", local_appid);
808 mi->callback(mi->local_id, local_appid, local_port, local_trusted, data, NULL);
810 mi->callback(mi->local_id, local_appid, NULL, false, data, NULL);
817 static int __check_remote_port(const char *remote_app_id, const char *remote_port, bool is_trusted, bool *exist)
819 _LOGI("Check a remote port : [%s:%s]", remote_app_id, remote_port);
821 GVariant *result = NULL;
823 int ret_val = MESSAGEPORT_ERROR_NONE;
824 char *bus_name = NULL;
825 message_port_remote_app_info_s *remote_app_info = NULL;
826 port_list_info_s *port_info = NULL;
827 int local_reg_id = 0;
828 message_port_local_port_info_s *mi = NULL;
829 gboolean name_exist = false;
831 _LOGI("remote_app_id, app_id :[%s : %s] ", remote_app_id, __app_id);
833 ret_val = __get_remote_port_info(remote_app_id, remote_port, is_trusted, &remote_app_info, &port_info);
834 if (ret_val != MESSAGEPORT_ERROR_NONE)
839 if (strcmp(remote_app_id, __app_id) == 0) {
841 _LOGI("__is_local_port_registed ");
842 if (!__is_local_port_registed(remote_port, is_trusted, &local_reg_id, &mi))
847 _LOGI("__is_local_port_registed : %d ", *exist);
848 return MESSAGEPORT_ERROR_NONE;
851 port_info->exist = false;
852 bus_name = port_info->encoded_bus_name;
854 result = g_dbus_connection_call_sync(
860 g_variant_new("(s)", bus_name),
861 G_VARIANT_TYPE("(b)"),
862 G_DBUS_CALL_FLAGS_NONE,
867 if (err || (result == NULL)) {
869 _LOGE("No reply. error = %s", err->message);
872 ret_val = MESSAGEPORT_ERROR_RESOURCE_UNAVAILABLE;
874 g_variant_get(result, "(b)", &name_exist);
877 LOGE("Name not exist %s", bus_name);
879 ret_val = MESSAGEPORT_ERROR_NONE;
883 if (remote_app_info->certificate_info != CERTIFICATE_MATCH) {
884 if (!__is_preloaded(__app_id, remote_app_id)) {
885 if (__check_certificate(__app_id, remote_app_id) != MESSAGEPORT_ERROR_NONE) {
886 ret_val = MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH;
890 remote_app_info->certificate_info = CERTIFICATE_MATCH;
894 port_info->watcher_id = g_bus_watch_name_on_connection(
896 port_info->encoded_bus_name,
897 G_BUS_NAME_WATCHER_FLAGS_NONE,
903 port_info->exist = true;
905 ret_val = MESSAGEPORT_ERROR_NONE;
906 _LOGI("Exist port: %s", bus_name);
912 g_variant_unref(result);
917 static bool __check_sender_validation(GVariant *parameters, const char *sender, GDBusConnection *conn)
920 char buffer[MAX_PACKAGE_STR_SIZE] = {0, };
921 char *local_appid = NULL;
922 int pid = __get_sender_pid(conn, sender);
924 ret = aul_app_get_appid_bypid(pid, buffer, sizeof(buffer));
925 retvm_if(ret != AUL_R_OK, false, "Failed to get the sender ID: (%s) (%d)", sender, pid);
927 g_variant_get_child(parameters, 0, "s", &local_appid);
928 retvm_if(!local_appid, false, "remote_appid is NULL (%s) (%d)", sender, pid);
930 if (strncmp(buffer, local_appid, MAX_PACKAGE_STR_SIZE) == 0) {
931 g_hash_table_insert(__sender_appid_hash, strdup(sender), GINT_TO_POINTER(pid));
940 static void __dbus_method_call_handler(GDBusConnection *conn,
941 const gchar *sender, const gchar *object_path,
942 const gchar *iface_name, const gchar *method_name,
943 GVariant *parameters, GDBusMethodInvocation *invocation,
946 _LOGI("method_name: %s", method_name);
947 gpointer sender_pid = g_hash_table_lookup(__sender_appid_hash, sender);
948 if (sender_pid == NULL) {
949 if (!__check_sender_validation(parameters, sender, conn))
953 if (g_strcmp0(method_name, "send_message") == 0)
954 send_message(parameters, invocation);
958 static const GDBusInterfaceVTable interface_vtable = {
959 __dbus_method_call_handler,
964 static int __dbus_init(void)
967 GError *error = NULL;
969 __gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
970 if (__gdbus_conn == NULL) {
972 _LOGE("Failed to get dbus [%s]", error->message);
982 g_object_unref(__gdbus_conn);
989 int __register_dbus_interface(const char *port_name, bool is_trusted)
992 GDBusNodeInfo *introspection_data = NULL;
993 int registration_id = 0;
995 static gchar introspection_prefix[] =
997 " <interface name='";
999 static gchar introspection_postfix[] =
1001 " <method name='send_message'>"
1002 " <arg type='s' name='local_appid' direction='in'/>"
1003 " <arg type='s' name='local_port' direction='in'/>"
1004 " <arg type='b' name='local_trusted' direction='in'/>"
1005 " <arg type='b' name='bi_dir' direction='in'/>"
1006 " <arg type='s' name='remote_appid' direction='in'/>"
1007 " <arg type='s' name='remote_port' direction='in'/>"
1008 " <arg type='b' name='remote_trusted' direction='in'/>"
1009 " <arg type='u' name='data_len' direction='in'/>"
1010 " <arg type='s' name='data' direction='in'/>"
1015 char *introspection_xml = NULL;
1016 int introspection_xml_len = 0;
1020 GError *error = NULL;
1021 char *bus_name = NULL;
1022 char *interface_name = NULL;
1023 GVariant *result = NULL;
1025 bus_name = __get_encoded_name(__app_id, port_name, is_trusted);
1027 _LOGE("Fail to get bus name");
1030 interface_name = bus_name;
1032 introspection_xml_len = strlen(introspection_prefix) + strlen(interface_name) +
1033 strlen(introspection_postfix) + 1;
1035 introspection_xml = (char *)calloc(introspection_xml_len, sizeof(char));
1036 if (!introspection_xml) {
1037 _LOGE("out of memory");
1042 result = g_dbus_connection_call_sync(
1046 DBUS_INTERFACE_DBUS,
1048 g_variant_new("(su)", bus_name, G_BUS_NAME_OWNER_FLAGS_NONE),
1049 G_VARIANT_TYPE("(u)"),
1050 G_DBUS_CALL_FLAGS_NONE,
1055 _LOGE("RequestName fail : %s", error->message);
1058 if (result == NULL) {
1059 _LOGE("fail to get name NULL");
1062 g_variant_get(result, "(u)", &owner_id);
1063 if (owner_id == 0) {
1064 _LOGE("Acquiring the own name is failed");
1068 _LOGI("Acquiring the own name : %d", owner_id);
1070 snprintf(introspection_xml, introspection_xml_len, "%s%s%s", introspection_prefix, interface_name, introspection_postfix);
1072 introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
1073 if (!introspection_data) {
1074 _LOGE("g_dbus_node_info_new_for_xml() is failed.");
1078 registration_id = g_dbus_connection_register_object(__gdbus_conn,
1079 MESSAGEPORT_OBJECT_PATH, introspection_data->interfaces[0],
1080 &interface_vtable, NULL, NULL, NULL);
1082 _LOGI("registration_id %d", registration_id);
1084 if (registration_id == 0) {
1085 _LOGE("Failed to g_dbus_connection_register_object");
1090 if (introspection_data)
1091 g_dbus_node_info_unref(introspection_data);
1092 if (introspection_xml)
1093 free(introspection_xml);
1097 g_variant_unref(result);
1100 return registration_id;
1104 void __list_free_port_list(gpointer data)
1106 port_list_info_s *n = (port_list_info_s *)data;
1108 FREE_AND_NULL(n->encoded_bus_name);
1109 FREE_AND_NULL(n->port_name);
1113 static void __hash_destory_local_value(gpointer data)
1115 message_port_local_port_info_s *mli = (message_port_local_port_info_s *)data;
1117 free(mli->port_name);
1119 static void __hash_destory_remote_value(gpointer data)
1121 message_port_remote_app_info_s *mri = (message_port_remote_app_info_s *)data;
1124 FREE_AND_NULL(mri->sender_id);
1125 FREE_AND_NULL(mri->remote_app_id);
1127 g_list_free_full(mri->port_list, __list_free_port_list);
1131 static bool __initialize(void)
1134 #if !GLIB_CHECK_VERSION(2, 35, 0)
1140 char buffer[MAX_PACKAGE_STR_SIZE] = {0, };
1142 _LOGI("initialize");
1143 ret = aul_app_get_appid_bypid(pid, buffer, sizeof(buffer));
1144 retvm_if(ret != AUL_R_OK, false, "Failed to get the application ID: %d", ret);
1146 __app_id = strdup(buffer);
1147 retvm_if(!__app_id, false, "Malloc failed");
1148 _LOGI("init : %s", __app_id);
1150 if (__local_port_info == NULL) {
1151 __local_port_info = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, __hash_destory_local_value);
1152 retvm_if(!__local_port_info, false, "fail to create __local_port_info");
1155 if (__remote_port_info == NULL) {
1156 __remote_port_info = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, __hash_destory_remote_value);
1157 retvm_if(!__remote_port_info, false, "fail to create __remote_port_info");
1160 if (__sender_appid_hash == NULL) {
1161 __sender_appid_hash = g_hash_table_new(g_str_hash, g_str_equal);
1162 retvm_if(!__sender_appid_hash, false, "fail to create __sender_appid_hash");
1165 if (__trusted_app_list_hash == NULL) {
1166 __trusted_app_list_hash = g_hash_table_new(g_str_hash, g_str_equal);
1167 retvm_if(!__trusted_app_list_hash, false, "fail to create __trusted_app_list_hash");
1172 _initialized = true;
1178 static bool __message_port_register_port(const int local_id, const char *local_port, bool is_trusted, messageport_message_cb callback)
1180 message_port_local_port_info_s *mi = (message_port_local_port_info_s *)calloc(1, sizeof(message_port_local_port_info_s));
1181 retvm_if(!mi, false, "Malloc failed");
1183 mi->callback = callback;
1184 mi->is_trusted = is_trusted;
1185 mi->port_name = strdup(local_port);
1186 if (mi->port_name == NULL) {
1187 _LOGE("Malloc failed (%s)", local_port);
1191 mi->local_id = local_id;
1193 g_hash_table_insert(__local_port_info, GINT_TO_POINTER(mi->local_id), mi);
1197 static int __register_message_port(const char *local_port, bool is_trusted, messageport_message_cb callback)
1199 _SECURE_LOGI("Register a message port : [%s:%s]", __app_id, local_port);
1203 /* Check the message port is already registed */
1204 if (__is_local_port_registed(local_port, is_trusted, &local_id, NULL))
1207 local_id = __register_dbus_interface(local_port, is_trusted);
1209 _LOGE("register_dbus_interface fail !!");
1210 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1213 if (!__message_port_register_port(local_id, local_port, is_trusted, callback))
1214 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1219 int __message_port_send_async(int sockfd, bundle *kb, const char *local_port,
1220 bool local_trusted, bool is_bidirection)
1224 int local_port_len = 0;
1226 bundle_raw *kb_data = NULL;
1228 if (local_port != NULL)
1229 local_port_len = strlen(local_port) + 1;
1231 if (__write_string_to_socket(sockfd, local_port, local_port_len) != MESSAGEPORT_ERROR_NONE) {
1232 _LOGE("write local_port fail");
1233 return MESSAGEPORT_ERROR_IO_ERROR;
1235 if (__write_socket(sockfd, (char *)&is_bidirection, sizeof(is_bidirection), &nb) != MESSAGEPORT_ERROR_NONE) {
1236 _LOGE("write is_bidirection fail");
1237 return MESSAGEPORT_ERROR_IO_ERROR;
1240 bundle_encode(kb, &kb_data, &data_len);
1241 if (kb_data == NULL) {
1242 _LOGE("bundle encode fail");
1243 ret = MESSAGEPORT_ERROR_IO_ERROR;
1246 if (data_len > MAX_MESSAGE_SIZE) {
1247 _LOGE("bigger than max size\n");
1248 ret = MESSAGEPORT_ERROR_MAX_EXCEEDED;
1252 if (__write_string_to_socket(sockfd, (void *)kb_data, data_len) != MESSAGEPORT_ERROR_NONE) {
1253 _LOGE("write kb_data fail");
1254 ret = MESSAGEPORT_ERROR_IO_ERROR;
1263 static int __message_port_send_message(const char *remote_appid, const char *remote_port,
1264 const char *local_port, bool trusted_message, bool local_trusted, bool bi_dir, bundle *message)
1267 int ret = MESSAGEPORT_ERROR_NONE;
1268 GUnixFDList *fd_list = NULL;
1269 GError *error = NULL;
1272 bundle_raw *raw = NULL;
1273 char *bus_name = NULL;
1274 char *interface_name = NULL;
1276 message_port_remote_app_info_s *remote_app_info = NULL;
1277 port_list_info_s *port_info = NULL;
1278 GDBusMessage *msg = NULL;
1280 GVariant *body = NULL;
1282 ret = __get_remote_port_info(remote_appid, remote_port, trusted_message, &remote_app_info, &port_info);
1283 if (ret != MESSAGEPORT_ERROR_NONE)
1286 if (port_info->exist == false) {
1288 _LOGI("port exist check !!");
1289 ret = __check_remote_port(remote_appid, remote_port, trusted_message, &exist);
1290 if (ret != MESSAGEPORT_ERROR_NONE) {
1292 } else if (!exist) {
1293 ret = MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1298 if (port_info->sock_pair[0] > 0) {
1299 ret = __message_port_send_async(port_info->sock_pair[0], message,
1300 (local_port) ? local_port : "", local_trusted, bi_dir);
1303 bus_name = port_info->encoded_bus_name;
1304 interface_name = bus_name;
1306 if (bundle_encode(message, &raw, &len) != BUNDLE_ERROR_NONE) {
1307 ret = MESSAGEPORT_ERROR_INVALID_PARAMETER;
1311 if (MAX_MESSAGE_SIZE < len) {
1312 _LOGE("The size of message (%d) has exceeded the maximum limit.", len);
1313 ret = MESSAGEPORT_ERROR_MAX_EXCEEDED;
1316 body = g_variant_new("(ssbbssbus)", __app_id, (local_port) ? local_port : "", local_trusted, bi_dir,
1317 remote_appid, remote_port, trusted_message, len, raw);
1320 if (strcmp(remote_appid, __app_id) != 0) { /* self send */
1322 /* if message-port fail to get socket pair, communicate using GDBus */
1323 if (aul_request_message_port_socket_pair(port_info->sock_pair) != AUL_R_OK) {
1324 _LOGE("error create socket pair");
1327 _LOGI("sock pair : %d, %d", port_info->sock_pair[0], port_info->sock_pair[1]);
1329 fd_list = g_unix_fd_list_new();
1330 g_unix_fd_list_append(fd_list, port_info->sock_pair[1], &err);
1331 g_unix_fd_list_append(fd_list, port_info->sock_pair[0], &err);
1334 _LOGE("g_unix_fd_list_append [%s]", error->message);
1335 ret = MESSAGEPORT_ERROR_IO_ERROR;
1343 msg = g_dbus_message_new_method_call(bus_name, MESSAGEPORT_OBJECT_PATH, interface_name, "send_message");
1345 _LOGE("Can't allocate new method call");
1346 ret = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1350 g_dbus_message_set_unix_fd_list(msg, fd_list);
1351 g_dbus_message_set_body(msg, body);
1352 g_dbus_message_set_flags(msg, G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED);
1353 g_dbus_connection_send_message(__gdbus_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &err);
1355 _LOGE("No reply. error = %s", err->message);
1357 ret = MESSAGEPORT_ERROR_IO_ERROR;
1366 g_object_unref(msg);
1368 bundle_free_encoded_rawdata(&raw);
1370 g_object_unref(fd_list);
1376 int __message_send_bidirectional_message(int id, const char *remote_app_id, const char *remote_port, bool trusted_message, bundle *message)
1378 message_port_local_port_info_s *local_info;
1379 int ret = __get_local_port_info(id, &local_info);
1380 if (ret != MESSAGEPORT_ERROR_NONE)
1383 _LOGI("bidirectional_message %s", local_info->port_name);
1384 return __message_port_send_message(remote_app_id, remote_port,
1385 local_info->port_name, trusted_message, local_info->is_trusted, true, message);
1388 int messageport_unregister_local_port(int local_port_id, bool trusted_port)
1392 char *bus_name = NULL;
1396 _LOGI("unregister : %d", local_port_id);
1398 message_port_local_port_info_s *mi =
1399 (message_port_local_port_info_s *)
1400 g_hash_table_lookup(__local_port_info, GINT_TO_POINTER(local_port_id));
1402 return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1404 if (mi->is_trusted != trusted_port)
1405 return MESSAGEPORT_ERROR_INVALID_PARAMETER;
1407 bus_name = __get_encoded_name(__app_id, mi->port_name, mi->is_trusted);
1408 if (bus_name == NULL)
1409 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1411 g_dbus_connection_unregister_object(__gdbus_conn, local_port_id);
1413 result = g_dbus_connection_call_sync(
1417 DBUS_INTERFACE_DBUS,
1419 g_variant_new("(s)", bus_name),
1420 G_VARIANT_TYPE("(u)"),
1421 G_DBUS_CALL_FLAGS_NONE,
1430 _LOGE("RequestName fail : %s", err->message);
1432 return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1434 g_variant_get(result, "(u)", &ret);
1437 g_variant_unref(result);
1439 if (ret != DBUS_RELEASE_NAME_REPLY_RELEASED) {
1441 if (ret == DBUS_RELEASE_NAME_REPLY_NON_EXISTENT) {
1442 _LOGE("Port Not exist");
1443 return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1444 } else if (ret == DBUS_RELEASE_NAME_REPLY_NOT_OWNER) {
1445 _LOGE("Try to release not owned name. MESSAGEPORT_ERROR_INVALID_PARAMETER");
1446 return MESSAGEPORT_ERROR_INVALID_PARAMETER;
1451 g_hash_table_remove(__local_port_info, GINT_TO_POINTER(local_port_id));
1453 return MESSAGEPORT_ERROR_NONE;
1456 int messageport_register_local_port(const char *local_port, messageport_message_cb callback)
1458 if (!_initialized) {
1459 if (!__initialize())
1460 return MESSAGEPORT_ERROR_IO_ERROR;
1463 return __register_message_port(local_port, false, callback);
1466 int messageport_register_trusted_local_port(const char *local_port, messageport_message_cb callback)
1468 if (!_initialized) {
1469 if (!__initialize())
1470 return MESSAGEPORT_ERROR_IO_ERROR;
1473 return __register_message_port(local_port, true, callback);
1477 int messageport_check_remote_port(const char *remote_app_id, const char *remote_port, bool *exist)
1479 if (!_initialized) {
1480 if (!__initialize())
1481 return MESSAGEPORT_ERROR_IO_ERROR;
1484 int ret = __check_remote_port(remote_app_id, remote_port, false, exist);
1485 if (ret == MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND) {
1487 ret = MESSAGEPORT_ERROR_NONE;
1493 int messageport_check_trusted_remote_port(const char *remote_app_id, const char *remote_port, bool *exist)
1495 if (!_initialized) {
1496 if (!__initialize())
1497 return MESSAGEPORT_ERROR_IO_ERROR;
1500 int ret = __check_remote_port(remote_app_id, remote_port, true, exist);
1501 if (ret == MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND) {
1503 ret = MESSAGEPORT_ERROR_NONE;
1509 int messageport_send_message(const char *remote_app_id, const char *remote_port, bundle *message)
1511 if (!_initialized) {
1512 if (!__initialize())
1513 return MESSAGEPORT_ERROR_IO_ERROR;
1516 return __message_port_send_message(remote_app_id, remote_port, NULL, false, false, false, message);
1519 int messageport_send_trusted_message(const char *remote_app_id, const char *remote_port, bundle *message)
1521 if (!_initialized) {
1522 if (!__initialize())
1523 return MESSAGEPORT_ERROR_IO_ERROR;
1526 return __message_port_send_message(remote_app_id, remote_port, NULL, true, false, false, message);
1529 int messageport_send_bidirectional_message(int id, const char *remote_app_id, const char *remote_port,
1532 if (!_initialized) {
1533 if (!__initialize())
1534 return MESSAGEPORT_ERROR_IO_ERROR;
1537 return __message_send_bidirectional_message(id, remote_app_id, remote_port, false, message);
1540 int messageport_send_bidirectional_trusted_message(int id, const char *remote_app_id, const char *remote_port,
1543 if (!_initialized) {
1544 if (!__initialize())
1545 return MESSAGEPORT_ERROR_IO_ERROR;
1547 return __message_send_bidirectional_message(id, remote_app_id, remote_port, true, message);
1550 int messageport_get_local_port_name(int id, char **name)
1552 message_port_local_port_info_s *local_info;
1553 int ret = __get_local_port_info(id, &local_info);
1555 if (ret != MESSAGEPORT_ERROR_NONE)
1558 *name = strdup(local_info->port_name);
1561 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1563 return MESSAGEPORT_ERROR_NONE;
1566 int messageport_check_trusted_local_port(int id, bool *trusted)
1568 message_port_local_port_info_s *local_info;
1569 int ret = __get_local_port_info(id, &local_info);
1571 if (ret != MESSAGEPORT_ERROR_NONE)
1574 *trusted = local_info->is_trusted;
1576 return MESSAGEPORT_ERROR_NONE;;