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 {
96 unsigned char data[1];
99 typedef struct message_port_callback_info {
100 messageport_message_cb callback;
105 GIOChannel *gio_read;
107 } message_port_callback_info_s;
109 typedef struct message_port_local_port_info {
110 messageport_message_cb callback;
114 } message_port_local_port_info_s;
116 typedef struct message_port_remote_port_info {
119 int certificate_info;
121 } message_port_remote_app_info_s;
123 typedef struct port_list_info {
125 char *encoded_bus_name;
132 static void __callback_info_free(message_port_callback_info_s *callback_info)
134 GError *error = NULL;
135 if (callback_info == NULL)
138 if (callback_info->remote_app_id)
139 free(callback_info->remote_app_id);
141 if (callback_info->remote_port)
142 free(callback_info->remote_port);
144 if (callback_info->gio_read != NULL) {
145 g_io_channel_shutdown(callback_info->gio_read, FALSE, &error);
147 _LOGE("g_io_channel_shutdown error : %s", error->message);
150 g_io_channel_unref(callback_info->gio_read);
151 callback_info->gio_read = NULL;
154 if (callback_info->g_src_id != 0) {
155 g_source_remove(callback_info->g_src_id);
156 callback_info->g_src_id = 0;
162 static char *__get_encoded_name(const char *remote_app_id, const char *port_name, bool is_trusted)
165 int prefix_len = strlen(MESSAGEPORT_BUS_NAME_PREFIX);
167 char *postfix = is_trusted ? "1" : "0";
169 unsigned char c[MD5_DIGEST_LENGTH] = {0};
170 char *md5_interface = NULL;
174 int encoded_bus_name_len = prefix_len + postfix_len + (MD5_DIGEST_LENGTH * 2) + 2;
175 int bus_name_len = strlen(remote_app_id) + strlen(port_name) + 2;
176 char *bus_name = (char *)calloc(bus_name_len, sizeof(char));
177 if (bus_name == NULL) {
178 _LOGE("bus_name calloc failed");
182 snprintf(bus_name, bus_name_len, "%s_%s", remote_app_id, port_name);
184 MD5_Init(&mdContext);
185 MD5_Update(&mdContext, bus_name, bus_name_len);
186 MD5_Final(c, &mdContext);
188 md5_interface = (char *)calloc(encoded_bus_name_len , sizeof(char));
189 if (md5_interface == NULL) {
193 _LOGE("md5_interface calloc failed!!");
197 snprintf(md5_interface, encoded_bus_name_len, "%s", MESSAGEPORT_BUS_NAME_PREFIX);
198 temp = md5_interface;
201 for (index = 0; index < MD5_DIGEST_LENGTH; index++) {
202 snprintf(temp, 3, "%02x", c[index]);
206 if (postfix && postfix_len > 0)
207 snprintf(temp, encoded_bus_name_len - (temp - md5_interface), "%s", postfix);
211 _LOGI("encoded_bus_name : %s ", md5_interface);
213 return md5_interface;
216 static int __remote_port_compare_cb(gconstpointer a, gconstpointer b)
218 port_list_info_s *key1 = (port_list_info_s *)a;
219 port_list_info_s *key2 = (port_list_info_s *)b;
221 if (key1->is_trusted == key2->is_trusted)
222 return strcmp(key1->port_name, key2->port_name);
228 static bool __is_preloaded(const char *local_appid, const char *remote_appid)
230 _LOGI("IsPreloaded");
232 bool preload_local = false;
233 bool preload_remote = false;
235 pkgmgrinfo_appinfo_h handle = NULL;
236 int ret = pkgmgrinfo_appinfo_get_usr_appinfo(local_appid, getuid(), &handle);
237 if (ret != PMINFO_R_OK) {
238 _LOGE("Failed to get the appinfo. %d", ret);
239 pkgmgrinfo_appinfo_destroy_appinfo(handle);
242 ret = pkgmgrinfo_appinfo_is_preload(handle, &preload_local);
243 if (ret != PMINFO_R_OK) {
244 _LOGE("Failed to check the preloaded application. %d", ret);
245 pkgmgrinfo_appinfo_destroy_appinfo(handle);
248 ret = pkgmgrinfo_appinfo_get_usr_appinfo(remote_appid, getuid(), &handle);
249 if (ret != PMINFO_R_OK) {
250 _LOGE("Failed to get the appinfo. %d", ret);
251 pkgmgrinfo_appinfo_destroy_appinfo(handle);
254 ret = pkgmgrinfo_appinfo_is_preload(handle, &preload_remote);
255 if (ret != PMINFO_R_OK) {
256 _LOGE("Failed to check the preloaded application. %d", ret);
257 pkgmgrinfo_appinfo_destroy_appinfo(handle);
261 if (preload_local && preload_remote) {
262 pkgmgrinfo_appinfo_destroy_appinfo(handle);
265 pkgmgrinfo_appinfo_destroy_appinfo(handle);
269 static int __check_certificate(const char *local_appid, const char *remote_appid)
271 _LOGI("CheckCertificate");
273 pkgmgrinfo_cert_compare_result_type_e res;
274 int ret = pkgmgrinfo_pkginfo_compare_usr_app_cert_info(local_appid, remote_appid, getuid(), &res);
276 _LOGE(":CheckCertificate() Failed");
277 return MESSAGEPORT_ERROR_IO_ERROR;
279 if (res != PMINFO_CERT_COMPARE_MATCH) {
280 _LOGE("CheckCertificate() Failed : MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH");
281 return MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH;
284 return MESSAGEPORT_ERROR_NONE;
287 static void on_name_appeared(GDBusConnection *connection,
289 const gchar *name_owner,
292 _LOGI("name appeared : %s %s", __app_id, name);
295 static void on_name_vanished(GDBusConnection *connection,
299 _LOGI("name vanished : %s", name);
300 port_list_info_s *pli = (port_list_info_s *)user_data;
301 g_bus_unwatch_name(pli->watcher_id);
305 static int __get_local_port_info(int id, message_port_local_port_info_s **info)
307 message_port_local_port_info_s *mi = (message_port_local_port_info_s *)g_hash_table_lookup(__local_port_info, GINT_TO_POINTER(id));
310 return MESSAGEPORT_ERROR_INVALID_PARAMETER;
313 return MESSAGEPORT_ERROR_NONE;
316 static port_list_info_s *__set_remote_port_info(const char *remote_app_id, const char *remote_port, bool is_trusted)
318 int ret_val = MESSAGEPORT_ERROR_NONE;
319 port_list_info_s *port_info = (port_list_info_s *)calloc(1, sizeof(port_list_info_s));
322 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
325 port_info->port_name = strdup(remote_port);
326 if (!port_info->port_name) {
327 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
330 port_info->is_trusted = is_trusted;
332 port_info->encoded_bus_name = __get_encoded_name(remote_app_id, remote_port, is_trusted);
333 if (port_info->encoded_bus_name == NULL) {
334 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
338 port_info->sock_pair[0] = 0;
339 port_info->sock_pair[1] = 0;
342 if (ret_val != MESSAGEPORT_ERROR_NONE) {
344 FREE_AND_NULL(port_info->port_name);
345 FREE_AND_NULL(port_info->encoded_bus_name);
353 static message_port_remote_app_info_s *__set_remote_app_info(const char *remote_app_id, const char *remote_port, bool is_trusted)
355 port_list_info_s *port_info = NULL;
356 message_port_remote_app_info_s *remote_app_info = NULL;
357 int ret_val = MESSAGEPORT_ERROR_NONE;
359 remote_app_info = (message_port_remote_app_info_s *)calloc(1, sizeof(message_port_remote_app_info_s));
360 if (!remote_app_info) {
361 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
365 remote_app_info->remote_app_id = strdup(remote_app_id);
366 if (remote_app_info->remote_app_id == NULL) {
367 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;;
371 port_info = __set_remote_port_info(remote_app_id, remote_port, is_trusted);
372 if (port_info == NULL) {
373 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
377 remote_app_info->port_list = g_list_append(remote_app_info->port_list, port_info);
380 if (ret_val != MESSAGEPORT_ERROR_NONE) {
381 if (remote_app_info) {
382 FREE_AND_NULL(remote_app_info->remote_app_id);
383 FREE_AND_NULL(remote_app_info);
387 return remote_app_info;
390 static int __get_remote_port_info(const char *remote_app_id, const char *remote_port, bool is_trusted,
391 message_port_remote_app_info_s **mri, port_list_info_s **pli)
393 message_port_remote_app_info_s *remote_app_info = NULL;
394 port_list_info_s port_info;
395 GList *cb_list = NULL;
396 int ret_val = MESSAGEPORT_ERROR_NONE;
398 remote_app_info = (message_port_remote_app_info_s *)g_hash_table_lookup(__remote_port_info, remote_app_id);
400 if (remote_app_info == NULL) {
401 remote_app_info = __set_remote_app_info(remote_app_id, remote_port, is_trusted);
403 if (remote_app_info == NULL) {
404 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
407 g_hash_table_insert(__remote_port_info, remote_app_info->remote_app_id, remote_app_info);
410 *mri = remote_app_info;
412 port_info.port_name = strdup(remote_port);
413 port_info.is_trusted = is_trusted;
414 cb_list = g_list_find_custom(remote_app_info->port_list, &port_info,
415 (GCompareFunc)__remote_port_compare_cb);
416 if (port_info.port_name)
417 free(port_info.port_name);
418 if (cb_list == NULL) {
419 port_list_info_s *tmp = __set_remote_port_info(remote_app_id, remote_port, is_trusted);
422 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
425 remote_app_info->port_list = g_list_append(remote_app_info->port_list, tmp);
427 g_hash_table_insert(__remote_port_info, (*pli)->encoded_bus_name, *pli);
429 *pli = (port_list_info_s *)cb_list->data;
437 static bool __is_local_port_registed(const char *local_port, bool trusted, int *local_id, message_port_local_port_info_s **lpi)
442 g_hash_table_iter_init(&iter, __local_port_info);
444 while (g_hash_table_iter_next(&iter, &key, &value)) {
445 message_port_local_port_info_s *mi = (message_port_local_port_info_s *)value;
447 if ((mi->is_trusted == trusted) && strcmp(mi->port_name, local_port) == 0) {
448 *local_id = mi->local_id;
457 static int __get_sender_pid(GDBusConnection *conn, const char *sender_name)
459 GDBusMessage *msg = NULL;
460 GDBusMessage *reply = NULL;
465 msg = g_dbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
466 "org.freedesktop.DBus", "GetConnectionUnixProcessID");
468 _LOGE("Can't allocate new method call");
472 g_dbus_message_set_body(msg, g_variant_new("(s)", sender_name));
473 reply = g_dbus_connection_send_message_with_reply_sync(conn, msg,
474 G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err);
478 _LOGE("Failed to get pid [%s]", err->message);
484 body = g_dbus_message_get_body(reply);
485 g_variant_get(body, "(u)", &pid);
491 g_object_unref(reply);
496 message_port_pkt_s *__message_port_recv_raw(int fd)
500 message_port_pkt_s *pkt = NULL;
502 pkt = (message_port_pkt_s *)calloc(sizeof(char) * MAX_MESSAGE_SIZE, 1);
509 /* receive single packet from socket */
510 len = recv(fd, pkt, MAX_MESSAGE_SIZE, 0);
512 _LOGE("recv error: %d[%s]", errno, strerror(errno));
517 if (len < HEADER_LEN) {
518 _LOGE("recv error %d %d", len, pkt->len);
523 while (len < (pkt->len + HEADER_LEN)) {
525 ret = recv(fd, &pkt->data[len - 8], MAX_MESSAGE_SIZE, 0);
527 SECURE_LOGE("recv error: %d %d %d", errno, len, pkt->len);
539 static gboolean __socket_request_handler(GIOChannel *gio,
544 message_port_callback_info_s *mi;
545 message_port_pkt_s *pkt;
548 GError *error = NULL;
550 mi = (message_port_callback_info_s *)data;
553 g_io_channel_shutdown(gio, FALSE, &error);
555 _LOGE("g_io_channel_shutdown error : %s", error->message);
558 g_io_channel_unref(gio);
562 if (cond == G_IO_HUP) {
564 _LOGI("socket G_IO_HUP");
565 __callback_info_free(mi);
570 if ((fd = g_io_channel_unix_get_fd(gio)) < 0) {
571 _LOGE("fail to get fd from io channel");
572 __callback_info_free(mi);
576 if ((pkt = __message_port_recv_raw(fd)) == NULL) {
577 _LOGE("recv error on SOCKET");
578 __callback_info_free(mi);
582 kb = bundle_decode(pkt->data, pkt->len);
583 is_bidirection = pkt->is_bidirection;
586 mi->callback(mi->local_id, mi->remote_app_id, mi->remote_port, mi->is_trusted, kb, NULL);
588 mi->callback(mi->local_id, mi->remote_app_id, NULL, mi->is_trusted, kb, NULL);
597 static bool send_message(GVariant *parameters, GDBusMethodInvocation *invocation)
599 char *local_port = NULL;
600 char *local_appid = NULL;
601 char *remote_appid = NULL;
602 char *remote_port = NULL;
603 gboolean local_trusted = false;
604 gboolean remote_trusted = false;
605 gboolean bi_dir = false;
609 bundle_raw *raw = NULL;
610 message_port_local_port_info_s *mi;
611 message_port_callback_info_s *callback_info;
612 int local_reg_id = 0;
614 g_variant_get(parameters, "(ssbbssbus)", &local_appid, &local_port, &local_trusted, &bi_dir,
615 &remote_appid, &remote_port, &remote_trusted, &len, &raw);
618 _LOGE("Invalid argument : remote_port is NULL");
622 _LOGE("Invalid argument : remote_appid is NULL");
625 if (!__is_local_port_registed(remote_port, remote_trusted, &local_reg_id, &mi)) {
626 _LOGE("Invalid argument : remote_port:(%s) trusted(%d)", remote_port, remote_trusted);
630 _LOGE("Invalid argument : local_appid");
634 _LOGE("Invalid argument : local_port");
637 if (strcmp(remote_appid, __app_id) != 0) {
638 _LOGE("Invalid argument : remote_appid (%s)", remote_appid);
641 if (strcmp(remote_port, mi->port_name) != 0) {
642 _LOGE("Invalid argument : remote_port (%s)", remote_port);
646 _LOGE("Invalid argument : data_len");
649 if (remote_trusted) {
650 if (g_hash_table_lookup(__trusted_app_list_hash, (gpointer)local_appid) == NULL) {
651 if (!__is_preloaded(local_appid, remote_appid)) {
652 /* Check the certificate */
653 int ret = __check_certificate(local_appid, remote_appid);
654 if (ret == MESSAGEPORT_ERROR_NONE)
655 g_hash_table_insert(__trusted_app_list_hash, local_appid, "TRUE");
657 _LOGE("The application (%s) is not signed with the same certificate",
665 callback_info = (message_port_callback_info_s *)calloc(1, sizeof(message_port_callback_info_s));
666 if (callback_info == NULL)
669 callback_info->local_id = mi->local_id;
670 callback_info->remote_app_id = strdup(local_appid);
671 callback_info->remote_port = strdup(local_port);
672 callback_info->is_trusted = local_trusted;
673 callback_info->callback = mi->callback;
675 GError *error = NULL;
676 GDBusMessage *msg = g_dbus_method_invocation_get_message(invocation);
678 GUnixFDList *fd_list = g_dbus_message_get_unix_fd_list(msg);
679 int fd = g_unix_fd_list_get(fd_list, 0, &error);
681 LOGE("g_unix_fd_list_get fail : %s", error->message);
685 LOGI("g_unix_fd_list_get fd: [%d]", fd);
689 callback_info->gio_read = g_io_channel_unix_new(fd);
690 if (!callback_info->gio_read) {
691 _LOGE("Error is %s\n", strerror(errno));
692 __callback_info_free(callback_info);
696 callback_info->g_src_id = g_io_add_watch(callback_info->gio_read, G_IO_IN | G_IO_HUP,
697 __socket_request_handler, (gpointer)callback_info);
698 if (callback_info->g_src_id == 0) {
699 _LOGE("fail to add watch on socket");
700 __callback_info_free(callback_info);
706 data = bundle_decode(raw, len);
707 bundle_free_encoded_rawdata(&raw);
710 _LOGE("Invalid argument : message");
714 LOGI("call calback %s", local_appid);
716 mi->callback(mi->local_id, local_appid, local_port, local_trusted, data, NULL);
718 mi->callback(mi->local_id, local_appid, NULL, false, data, NULL);
725 static int __check_remote_port(const char *remote_app_id, const char *remote_port, bool is_trusted, bool *exist)
727 _LOGI("Check a remote port : [%s:%s]", remote_app_id, remote_port);
729 GVariant *result = NULL;
731 int ret_val = MESSAGEPORT_ERROR_NONE;
732 char *bus_name = NULL;
733 message_port_remote_app_info_s *remote_app_info = NULL;
734 port_list_info_s *port_info = NULL;
735 int local_reg_id = 0;
736 message_port_local_port_info_s *mi = NULL;
737 gboolean name_exist = false;
739 _LOGI("remote_app_id, app_id :[%s : %s] ", remote_app_id, __app_id);
741 ret_val = __get_remote_port_info(remote_app_id, remote_port, is_trusted, &remote_app_info, &port_info);
742 if (ret_val != MESSAGEPORT_ERROR_NONE)
747 if (strcmp(remote_app_id, __app_id) == 0) {
749 _LOGI("__is_local_port_registed ");
750 if (!__is_local_port_registed(remote_port, is_trusted, &local_reg_id, &mi))
755 _LOGI("__is_local_port_registed : %d ", *exist);
756 return MESSAGEPORT_ERROR_NONE;
759 port_info->exist = false;
760 bus_name = port_info->encoded_bus_name;
762 result = g_dbus_connection_call_sync(
768 g_variant_new("(s)", bus_name),
769 G_VARIANT_TYPE("(b)"),
770 G_DBUS_CALL_FLAGS_NONE,
775 if (err || (result == NULL)) {
777 _LOGE("No reply. error = %s", err->message);
780 ret_val = MESSAGEPORT_ERROR_RESOURCE_UNAVAILABLE;
782 g_variant_get(result, "(b)", &name_exist);
785 LOGE("Name not exist %s", bus_name);
787 ret_val = MESSAGEPORT_ERROR_NONE;
791 if (remote_app_info->certificate_info != CERTIFICATE_MATCH) {
792 if (!__is_preloaded(__app_id, remote_app_id)) {
793 if (__check_certificate(__app_id, remote_app_id) != MESSAGEPORT_ERROR_NONE) {
794 ret_val = MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH;
798 remote_app_info->certificate_info = CERTIFICATE_MATCH;
802 port_info->watcher_id = g_bus_watch_name_on_connection(
804 port_info->encoded_bus_name,
805 G_BUS_NAME_WATCHER_FLAGS_NONE,
811 port_info->exist = true;
813 ret_val = MESSAGEPORT_ERROR_NONE;
814 _LOGI("Exist port: %s", bus_name);
820 g_variant_unref(result);
825 static bool __check_sender_validation(GVariant *parameters, const char *sender, GDBusConnection *conn)
828 char buffer[MAX_PACKAGE_STR_SIZE] = {0, };
829 char *local_appid = NULL;
830 int pid = __get_sender_pid(conn, sender);
832 ret = aul_app_get_appid_bypid(pid, buffer, sizeof(buffer));
833 retvm_if(ret != AUL_R_OK, false, "Failed to get the sender ID: (%s) (%d)", sender, pid);
835 g_variant_get_child(parameters, 0, "s", &local_appid);
836 retvm_if(!local_appid, false, "remote_appid is NULL (%s) (%d)", sender, pid);
838 if (strncmp(buffer, local_appid, MAX_PACKAGE_STR_SIZE) == 0) {
839 g_hash_table_insert(__sender_appid_hash, strdup(sender), GINT_TO_POINTER(pid));
848 static void __dbus_method_call_handler(GDBusConnection *conn,
849 const gchar *sender, const gchar *object_path,
850 const gchar *iface_name, const gchar *method_name,
851 GVariant *parameters, GDBusMethodInvocation *invocation,
854 _LOGI("method_name: %s", method_name);
855 gpointer sender_pid = g_hash_table_lookup(__sender_appid_hash, sender);
856 if (sender_pid == NULL) {
857 if (!__check_sender_validation(parameters, sender, conn))
861 if (g_strcmp0(method_name, "send_message") == 0)
862 send_message(parameters, invocation);
866 static const GDBusInterfaceVTable interface_vtable = {
867 __dbus_method_call_handler,
872 static int __dbus_init(void)
875 GError *error = NULL;
877 __gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
878 if (__gdbus_conn == NULL) {
880 _LOGE("Failed to get dbus [%s]", error->message);
890 g_object_unref(__gdbus_conn);
897 int __register_dbus_interface(const char *port_name, bool is_trusted)
900 GDBusNodeInfo *introspection_data = NULL;
901 int registration_id = 0;
903 static gchar introspection_prefix[] =
905 " <interface name='";
907 static gchar introspection_postfix[] =
909 " <method name='send_message'>"
910 " <arg type='s' name='local_appid' direction='in'/>"
911 " <arg type='s' name='local_port' direction='in'/>"
912 " <arg type='b' name='local_trusted' direction='in'/>"
913 " <arg type='b' name='bi_dir' direction='in'/>"
914 " <arg type='s' name='remote_appid' direction='in'/>"
915 " <arg type='s' name='remote_port' direction='in'/>"
916 " <arg type='b' name='remote_trusted' direction='in'/>"
917 " <arg type='u' name='data_len' direction='in'/>"
918 " <arg type='s' name='data' direction='in'/>"
923 char *introspection_xml = NULL;
924 int introspection_xml_len = 0;
928 GError *error = NULL;
929 char *bus_name = NULL;
930 char *interface_name = NULL;
931 GVariant *result = NULL;
933 bus_name = __get_encoded_name(__app_id, port_name, is_trusted);
935 _LOGE("Fail to get bus name");
938 interface_name = bus_name;
940 introspection_xml_len = strlen(introspection_prefix) + strlen(interface_name) +
941 strlen(introspection_postfix) + 1;
943 introspection_xml = (char *)calloc(introspection_xml_len, sizeof(char));
944 if (!introspection_xml) {
945 _LOGE("out of memory");
950 result = g_dbus_connection_call_sync(
956 g_variant_new("(su)", bus_name, G_BUS_NAME_OWNER_FLAGS_NONE),
957 G_VARIANT_TYPE("(u)"),
958 G_DBUS_CALL_FLAGS_NONE,
963 _LOGE("RequestName fail : %s", error->message);
966 if (result == NULL) {
967 _LOGE("fail to get name NULL");
970 g_variant_get(result, "(u)", &owner_id);
972 _LOGE("Acquiring the own name is failed");
976 _LOGI("Acquiring the own name : %d", owner_id);
978 snprintf(introspection_xml, introspection_xml_len, "%s%s%s", introspection_prefix, interface_name, introspection_postfix);
980 introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
981 if (!introspection_data) {
982 _LOGE("g_dbus_node_info_new_for_xml() is failed.");
986 registration_id = g_dbus_connection_register_object(__gdbus_conn,
987 MESSAGEPORT_OBJECT_PATH, introspection_data->interfaces[0],
988 &interface_vtable, NULL, NULL, NULL);
990 _LOGI("registration_id %d", registration_id);
992 if (registration_id == 0) {
993 _LOGE("Failed to g_dbus_connection_register_object");
998 if (introspection_data)
999 g_dbus_node_info_unref(introspection_data);
1000 if (introspection_xml)
1001 free(introspection_xml);
1005 g_variant_unref(result);
1008 return registration_id;
1012 void __list_free_port_list(gpointer data)
1014 port_list_info_s *n = (port_list_info_s *)data;
1016 FREE_AND_NULL(n->encoded_bus_name);
1017 FREE_AND_NULL(n->port_name);
1021 static void __hash_destory_local_value(gpointer data)
1023 message_port_local_port_info_s *mli = (message_port_local_port_info_s *)data;
1025 free(mli->port_name);
1027 static void __hash_destory_remote_value(gpointer data)
1029 message_port_remote_app_info_s *mri = (message_port_remote_app_info_s *)data;
1032 FREE_AND_NULL(mri->sender_id);
1033 FREE_AND_NULL(mri->remote_app_id);
1035 g_list_free_full(mri->port_list, __list_free_port_list);
1039 static bool __initialize(void)
1042 #if !GLIB_CHECK_VERSION(2, 35, 0)
1048 char buffer[MAX_PACKAGE_STR_SIZE] = {0, };
1050 _LOGI("initialize");
1051 ret = aul_app_get_appid_bypid(pid, buffer, sizeof(buffer));
1052 retvm_if(ret != AUL_R_OK, false, "Failed to get the application ID: %d", ret);
1054 __app_id = strdup(buffer);
1055 retvm_if(!__app_id, false, "Malloc failed");
1056 _LOGI("init : %s", __app_id);
1058 if (__local_port_info == NULL) {
1059 __local_port_info = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, __hash_destory_local_value);
1060 retvm_if(!__local_port_info, false, "fail to create __local_port_info");
1063 if (__remote_port_info == NULL) {
1064 __remote_port_info = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, __hash_destory_remote_value);
1065 retvm_if(!__remote_port_info, false, "fail to create __remote_port_info");
1068 if (__sender_appid_hash == NULL) {
1069 __sender_appid_hash = g_hash_table_new(g_str_hash, g_str_equal);
1070 retvm_if(!__sender_appid_hash, false, "fail to create __sender_appid_hash");
1073 if (__trusted_app_list_hash == NULL) {
1074 __trusted_app_list_hash = g_hash_table_new(g_str_hash, g_str_equal);
1075 retvm_if(!__trusted_app_list_hash, false, "fail to create __trusted_app_list_hash");
1080 _initialized = true;
1086 static bool __message_port_register_port(const int local_id, const char *local_port, bool is_trusted, messageport_message_cb callback)
1088 message_port_local_port_info_s *mi = (message_port_local_port_info_s *)calloc(1, sizeof(message_port_local_port_info_s));
1089 retvm_if(!mi, false, "Malloc failed");
1091 mi->callback = callback;
1092 mi->is_trusted = is_trusted;
1093 mi->port_name = strdup(local_port);
1094 if (mi->port_name == NULL) {
1095 _LOGE("Malloc failed (%s)", local_port);
1099 mi->local_id = local_id;
1101 g_hash_table_insert(__local_port_info, GINT_TO_POINTER(mi->local_id), mi);
1105 static int __register_message_port(const char *local_port, bool is_trusted, messageport_message_cb callback)
1107 _SECURE_LOGI("Register a message port : [%s:%s]", __app_id, local_port);
1111 /* Check the message port is already registed */
1112 if (__is_local_port_registed(local_port, is_trusted, &local_id, NULL))
1115 local_id = __register_dbus_interface(local_port, is_trusted);
1117 _LOGE("register_dbus_interface fail !!");
1118 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1121 if (!__message_port_register_port(local_id, local_port, is_trusted, callback))
1122 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1127 int __message_port_send_async(int sockfd, bundle *kb, const char *app_id, const char *local_port,
1128 bool local_trusted, bool is_bidirection)
1133 message_port_pkt_s *pkt = NULL;
1137 bundle_raw *kb_data = NULL;
1139 bundle_encode(kb, &kb_data, &datalen);
1140 if (kb_data == NULL) {
1141 _LOGE("bundle encode fail");
1142 ret = MESSAGEPORT_ERROR_IO_ERROR;
1146 if (datalen > MAX_MESSAGE_SIZE - HEADER_LEN) {
1147 _LOGE("bigger than max size\n");
1148 ret = MESSAGEPORT_ERROR_MAX_EXCEEDED;
1152 pkt_size = datalen + 9;
1153 pkt = (message_port_pkt_s *) malloc(sizeof(char) * pkt_size);
1156 _LOGE("Malloc Failed!");
1157 ret = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1160 memset(pkt, 0, pkt_size);
1163 pkt->is_bidirection = is_bidirection;
1165 memcpy(pkt->data, kb_data, datalen);
1167 int retry_ctr = MAX_RETRY_CNT;
1170 if ((len = send(sockfd, pkt, pkt_size, 0)) != pkt_size) {
1171 SECURE_LOGE("send() failed - len[%d] pkt_size[%d] (errno %d[%s])", len, pkt_size,
1172 errno, strerror(errno));
1174 _LOGE("fd:%d\n", sockfd);
1176 if (errno == EINTR) {
1177 if (retry_ctr > 0) {
1178 _LOGI("Retrying send on fd[%d]", sockfd);
1185 ret = MESSAGEPORT_ERROR_IO_ERROR;
1197 static int __message_port_send_message(const char *remote_appid, const char *remote_port,
1198 const char *local_port, bool trusted_message, bool local_trusted, bool bi_dir, bundle *message)
1201 int ret = MESSAGEPORT_ERROR_NONE;
1202 GUnixFDList *fd_list = NULL;
1203 GError *error = NULL;
1206 bundle_raw *raw = NULL;
1207 char *bus_name = NULL;
1208 char *interface_name = NULL;
1210 message_port_remote_app_info_s *remote_app_info = NULL;
1211 port_list_info_s *port_info = NULL;
1212 GDBusMessage *msg = NULL;
1214 GVariant *body = NULL;
1216 ret = __get_remote_port_info(remote_appid, remote_port, trusted_message, &remote_app_info, &port_info);
1217 if (ret != MESSAGEPORT_ERROR_NONE)
1220 if (port_info->exist == false) {
1222 _LOGI("port exist check !!");
1223 ret = __check_remote_port(remote_appid, remote_port, trusted_message, &exist);
1224 if (ret != MESSAGEPORT_ERROR_NONE) {
1226 } else if (!exist) {
1227 ret = MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1232 if (port_info->sock_pair[0] > 0) {
1233 ret = __message_port_send_async(port_info->sock_pair[0], message,
1234 __app_id, (local_port) ? local_port : "", local_trusted, bi_dir);
1237 bus_name = port_info->encoded_bus_name;
1238 interface_name = bus_name;
1240 if (bundle_encode(message, &raw, &len) != BUNDLE_ERROR_NONE) {
1241 ret = MESSAGEPORT_ERROR_INVALID_PARAMETER;
1245 if (MAX_MESSAGE_SIZE < len) {
1246 _LOGE("The size of message (%d) has exceeded the maximum limit.", len);
1247 ret = MESSAGEPORT_ERROR_MAX_EXCEEDED;
1250 body = g_variant_new("(ssbbssbus)", __app_id, (local_port) ? local_port : "", local_trusted, bi_dir,
1251 remote_appid, remote_port, trusted_message, len, raw);
1254 if (strcmp(remote_appid, __app_id) != 0) { /* self send */
1256 /* if message-port fail to get socket pair, communicate using GDBus */
1257 if (aul_request_message_port_socket_pair(port_info->sock_pair) != AUL_R_OK) {
1258 _LOGE("error create socket pair");
1261 _LOGI("sock pair : %d, %d", port_info->sock_pair[0], port_info->sock_pair[1]);
1263 fd_list = g_unix_fd_list_new();
1264 g_unix_fd_list_append(fd_list, port_info->sock_pair[1], &err);
1265 g_unix_fd_list_append(fd_list, port_info->sock_pair[0], &err);
1268 _LOGE("g_unix_fd_list_append [%s]", error->message);
1269 ret = MESSAGEPORT_ERROR_IO_ERROR;
1277 msg = g_dbus_message_new_method_call(bus_name, MESSAGEPORT_OBJECT_PATH, interface_name, "send_message");
1279 _LOGE("Can't allocate new method call");
1280 ret = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1284 g_dbus_message_set_unix_fd_list(msg, fd_list);
1285 g_dbus_message_set_body(msg, body);
1286 g_dbus_message_set_flags(msg, G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED);
1287 g_dbus_connection_send_message(__gdbus_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &err);
1289 _LOGE("No reply. error = %s", err->message);
1291 ret = MESSAGEPORT_ERROR_IO_ERROR;
1300 g_object_unref(msg);
1302 bundle_free_encoded_rawdata(&raw);
1304 g_object_unref(fd_list);
1310 int __message_send_bidirectional_message(int id, const char *remote_app_id, const char *remote_port, bool trusted_message, bundle *message)
1312 message_port_local_port_info_s *local_info;
1313 int ret = __get_local_port_info(id, &local_info);
1314 if (ret != MESSAGEPORT_ERROR_NONE)
1317 _LOGI("bidirectional_message %s", local_info->port_name);
1318 return __message_port_send_message(remote_app_id, remote_port,
1319 local_info->port_name, trusted_message, local_info->is_trusted, true, message);
1322 int messageport_unregister_local_port(int local_port_id, bool trusted_port)
1326 char *bus_name = NULL;
1330 _LOGI("unregister : %d", local_port_id);
1332 message_port_local_port_info_s *mi =
1333 (message_port_local_port_info_s *)
1334 g_hash_table_lookup(__local_port_info, GINT_TO_POINTER(local_port_id));
1336 return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1338 if (mi->is_trusted != trusted_port)
1339 return MESSAGEPORT_ERROR_INVALID_PARAMETER;
1341 bus_name = __get_encoded_name(__app_id, mi->port_name, mi->is_trusted);
1342 if (bus_name == NULL)
1343 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1345 g_dbus_connection_unregister_object(__gdbus_conn, local_port_id);
1347 result = g_dbus_connection_call_sync(
1351 DBUS_INTERFACE_DBUS,
1353 g_variant_new("(s)", bus_name),
1354 G_VARIANT_TYPE("(u)"),
1355 G_DBUS_CALL_FLAGS_NONE,
1364 _LOGE("RequestName fail : %s", err->message);
1366 return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1368 g_variant_get(result, "(u)", &ret);
1371 g_variant_unref(result);
1373 if (ret != DBUS_RELEASE_NAME_REPLY_RELEASED) {
1375 if (ret == DBUS_RELEASE_NAME_REPLY_NON_EXISTENT) {
1376 _LOGE("Port Not exist");
1377 return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1378 } else if (ret == DBUS_RELEASE_NAME_REPLY_NOT_OWNER) {
1379 _LOGE("Try to release not owned name. MESSAGEPORT_ERROR_INVALID_PARAMETER");
1380 return MESSAGEPORT_ERROR_INVALID_PARAMETER;
1385 g_hash_table_remove(__local_port_info, GINT_TO_POINTER(local_port_id));
1387 return MESSAGEPORT_ERROR_NONE;
1390 int messageport_register_local_port(const char *local_port, messageport_message_cb callback)
1392 if (!_initialized) {
1393 if (!__initialize())
1394 return MESSAGEPORT_ERROR_IO_ERROR;
1397 return __register_message_port(local_port, false, callback);
1400 int messageport_register_trusted_local_port(const char *local_port, messageport_message_cb callback)
1402 if (!_initialized) {
1403 if (!__initialize())
1404 return MESSAGEPORT_ERROR_IO_ERROR;
1407 return __register_message_port(local_port, true, callback);
1411 int messageport_check_remote_port(const char *remote_app_id, const char *remote_port, bool *exist)
1413 if (!_initialized) {
1414 if (!__initialize())
1415 return MESSAGEPORT_ERROR_IO_ERROR;
1418 int ret = __check_remote_port(remote_app_id, remote_port, false, exist);
1419 if (ret == MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND) {
1421 ret = MESSAGEPORT_ERROR_NONE;
1427 int messageport_check_trusted_remote_port(const char *remote_app_id, const char *remote_port, bool *exist)
1429 if (!_initialized) {
1430 if (!__initialize())
1431 return MESSAGEPORT_ERROR_IO_ERROR;
1434 int ret = __check_remote_port(remote_app_id, remote_port, true, exist);
1435 if (ret == MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND) {
1437 ret = MESSAGEPORT_ERROR_NONE;
1443 int messageport_send_message(const char *remote_app_id, const char *remote_port, bundle *message)
1445 if (!_initialized) {
1446 if (!__initialize())
1447 return MESSAGEPORT_ERROR_IO_ERROR;
1450 return __message_port_send_message(remote_app_id, remote_port, NULL, false, false, false, message);
1453 int messageport_send_trusted_message(const char *remote_app_id, const char *remote_port, bundle *message)
1455 if (!_initialized) {
1456 if (!__initialize())
1457 return MESSAGEPORT_ERROR_IO_ERROR;
1460 return __message_port_send_message(remote_app_id, remote_port, NULL, true, false, false, message);
1463 int messageport_send_bidirectional_message(int id, const char *remote_app_id, const char *remote_port,
1466 if (!_initialized) {
1467 if (!__initialize())
1468 return MESSAGEPORT_ERROR_IO_ERROR;
1471 return __message_send_bidirectional_message(id, remote_app_id, remote_port, false, message);
1474 int messageport_send_bidirectional_trusted_message(int id, const char *remote_app_id, const char *remote_port,
1477 if (!_initialized) {
1478 if (!__initialize())
1479 return MESSAGEPORT_ERROR_IO_ERROR;
1481 return __message_send_bidirectional_message(id, remote_app_id, remote_port, true, message);
1484 int messageport_get_local_port_name(int id, char **name)
1486 message_port_local_port_info_s *local_info;
1487 int ret = __get_local_port_info(id, &local_info);
1489 if (ret != MESSAGEPORT_ERROR_NONE)
1492 *name = strdup(local_info->port_name);
1495 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1497 return MESSAGEPORT_ERROR_NONE;
1500 int messageport_check_trusted_local_port(int id, bool *trusted)
1502 message_port_local_port_info_s *local_info;
1503 int ret = __get_local_port_info(id, &local_info);
1505 if (ret != MESSAGEPORT_ERROR_NONE)
1508 *trusted = local_info->is_trusted;
1510 return MESSAGEPORT_ERROR_NONE;;