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 } message_port_callback_info_s;
107 typedef struct message_port_local_port_info {
108 messageport_message_cb callback;
112 } message_port_local_port_info_s;
114 typedef struct message_port_remote_port_info {
117 int certificate_info;
119 } message_port_remote_app_info_s;
121 typedef struct port_list_info {
123 char *encoded_bus_name;
130 static char *__get_encoded_name(const char *remote_app_id, const char *port_name, bool is_trusted)
133 int prefix_len = strlen(MESSAGEPORT_BUS_NAME_PREFIX);
135 char *postfix = is_trusted ? "1" : "0";
137 unsigned char c[MD5_DIGEST_LENGTH] = {0};
138 char *md5_interface = NULL;
142 int encoded_bus_name_len = prefix_len + postfix_len + (MD5_DIGEST_LENGTH * 2) + 2;
143 int bus_name_len = strlen(remote_app_id) + strlen(port_name) + 2;
144 char *bus_name = (char *)calloc(bus_name_len, sizeof(char));
145 if (bus_name == NULL) {
146 _LOGE("bus_name calloc failed");
150 snprintf(bus_name, bus_name_len, "%s_%s", remote_app_id, port_name);
152 MD5_Init(&mdContext);
153 MD5_Update(&mdContext, bus_name, bus_name_len);
154 MD5_Final(c, &mdContext);
156 md5_interface = (char *)calloc(encoded_bus_name_len , sizeof(char));
157 if (md5_interface == NULL) {
161 _LOGE("md5_interface calloc failed!!");
165 snprintf(md5_interface, encoded_bus_name_len, "%s", MESSAGEPORT_BUS_NAME_PREFIX);
166 temp = md5_interface;
169 for (index = 0; index < MD5_DIGEST_LENGTH; index++) {
170 snprintf(temp, 3, "%02x", c[index]);
174 if (postfix && postfix_len > 0)
175 snprintf(temp, encoded_bus_name_len - (temp - md5_interface), "%s", postfix);
179 _LOGI("encoded_bus_name : %s ", md5_interface);
181 return md5_interface;
184 static int __remote_port_compare_cb(gconstpointer a, gconstpointer b)
186 port_list_info_s *key1 = (port_list_info_s *)a;
187 port_list_info_s *key2 = (port_list_info_s *)b;
189 if (key1->is_trusted == key2->is_trusted)
190 return strcmp(key1->port_name, key2->port_name);
196 static bool __is_preloaded(const char *local_appid, const char *remote_appid)
198 _LOGI("IsPreloaded");
200 bool preload_local = false;
201 bool preload_remote = false;
203 pkgmgrinfo_appinfo_h handle = NULL;
204 int ret = pkgmgrinfo_appinfo_get_usr_appinfo(local_appid, getuid(), &handle);
205 if (ret != PMINFO_R_OK) {
206 _LOGE("Failed to get the appinfo. %d", ret);
207 pkgmgrinfo_appinfo_destroy_appinfo(handle);
210 ret = pkgmgrinfo_appinfo_is_preload(handle, &preload_local);
211 if (ret != PMINFO_R_OK) {
212 _LOGE("Failed to check the preloaded application. %d", ret);
213 pkgmgrinfo_appinfo_destroy_appinfo(handle);
216 ret = pkgmgrinfo_appinfo_get_usr_appinfo(remote_appid, getuid(), &handle);
217 if (ret != PMINFO_R_OK) {
218 _LOGE("Failed to get the appinfo. %d", ret);
219 pkgmgrinfo_appinfo_destroy_appinfo(handle);
222 ret = pkgmgrinfo_appinfo_is_preload(handle, &preload_remote);
223 if (ret != PMINFO_R_OK) {
224 _LOGE("Failed to check the preloaded application. %d", ret);
225 pkgmgrinfo_appinfo_destroy_appinfo(handle);
229 if (preload_local && preload_remote) {
230 pkgmgrinfo_appinfo_destroy_appinfo(handle);
233 pkgmgrinfo_appinfo_destroy_appinfo(handle);
237 static int __check_certificate(const char *local_appid, const char *remote_appid)
239 _LOGI("CheckCertificate");
241 pkgmgrinfo_cert_compare_result_type_e res;
242 int ret = pkgmgrinfo_pkginfo_compare_usr_app_cert_info(local_appid, remote_appid, getuid(), &res);
244 _LOGE(":CheckCertificate() Failed");
245 return MESSAGEPORT_ERROR_IO_ERROR;
247 if (res != PMINFO_CERT_COMPARE_MATCH) {
248 _LOGE("CheckCertificate() Failed : MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH");
249 return MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH;
252 return MESSAGEPORT_ERROR_NONE;
255 static void on_name_appeared(GDBusConnection *connection,
257 const gchar *name_owner,
260 _LOGI("name appeared : %s %s", __app_id, name);
263 static void on_name_vanished(GDBusConnection *connection,
267 _LOGI("name vanished : %s", name);
268 port_list_info_s *pli = (port_list_info_s *)user_data;
269 g_bus_unwatch_name(pli->watcher_id);
273 static int __get_local_port_info(int id, message_port_local_port_info_s **info)
275 message_port_local_port_info_s *mi = (message_port_local_port_info_s *)g_hash_table_lookup(__local_port_info, GINT_TO_POINTER(id));
278 return MESSAGEPORT_ERROR_INVALID_PARAMETER;
281 return MESSAGEPORT_ERROR_NONE;
284 static port_list_info_s *__set_remote_port_info(const char *remote_app_id, const char *remote_port, bool is_trusted)
286 int ret_val = MESSAGEPORT_ERROR_NONE;
287 port_list_info_s *port_info = (port_list_info_s *)calloc(1, sizeof(port_list_info_s));
290 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
293 port_info->port_name = strdup(remote_port);
294 if (!port_info->port_name) {
295 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
298 port_info->is_trusted = is_trusted;
300 port_info->encoded_bus_name = __get_encoded_name(remote_app_id, remote_port, is_trusted);
301 if (port_info->encoded_bus_name == NULL) {
302 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
306 port_info->sock_pair[0] = 0;
307 port_info->sock_pair[1] = 0;
310 if (ret_val != MESSAGEPORT_ERROR_NONE) {
312 FREE_AND_NULL(port_info->port_name);
313 FREE_AND_NULL(port_info->encoded_bus_name);
321 static message_port_remote_app_info_s *__set_remote_app_info(const char *remote_app_id, const char *remote_port, bool is_trusted)
323 port_list_info_s *port_info = NULL;
324 message_port_remote_app_info_s *remote_app_info = NULL;
325 int ret_val = MESSAGEPORT_ERROR_NONE;
327 remote_app_info = (message_port_remote_app_info_s *)calloc(1, sizeof(message_port_remote_app_info_s));
328 if (!remote_app_info) {
329 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
333 remote_app_info->remote_app_id = strdup(remote_app_id);
334 if (remote_app_info->remote_app_id == NULL) {
335 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;;
339 port_info = __set_remote_port_info(remote_app_id, remote_port, is_trusted);
340 if (port_info == NULL) {
341 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
345 remote_app_info->port_list = g_list_append(remote_app_info->port_list, port_info);
348 if (ret_val != MESSAGEPORT_ERROR_NONE) {
349 if (remote_app_info) {
350 FREE_AND_NULL(remote_app_info->remote_app_id);
351 FREE_AND_NULL(remote_app_info);
355 return remote_app_info;
358 static int __get_remote_port_info(const char *remote_app_id, const char *remote_port, bool is_trusted,
359 message_port_remote_app_info_s **mri, port_list_info_s **pli)
361 message_port_remote_app_info_s *remote_app_info = NULL;
362 port_list_info_s port_info;
363 GList *cb_list = NULL;
364 int ret_val = MESSAGEPORT_ERROR_NONE;
366 remote_app_info = (message_port_remote_app_info_s *)g_hash_table_lookup(__remote_port_info, remote_app_id);
368 if (remote_app_info == NULL) {
369 remote_app_info = __set_remote_app_info(remote_app_id, remote_port, is_trusted);
371 if (remote_app_info == NULL) {
372 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
375 g_hash_table_insert(__remote_port_info, remote_app_info->remote_app_id, remote_app_info);
378 *mri = remote_app_info;
380 port_info.port_name = strdup(remote_port);
381 port_info.is_trusted = is_trusted;
382 cb_list = g_list_find_custom(remote_app_info->port_list, &port_info,
383 (GCompareFunc)__remote_port_compare_cb);
384 if (port_info.port_name)
385 free(port_info.port_name);
386 if (cb_list == NULL) {
387 port_list_info_s *tmp = __set_remote_port_info(remote_app_id, remote_port, is_trusted);
390 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
393 remote_app_info->port_list = g_list_append(remote_app_info->port_list, tmp);
395 g_hash_table_insert(__remote_port_info, (*pli)->encoded_bus_name, *pli);
397 *pli = (port_list_info_s *)cb_list->data;
405 static bool __is_local_port_registed(const char *local_port, bool trusted, int *local_id, message_port_local_port_info_s **lpi)
410 g_hash_table_iter_init(&iter, __local_port_info);
412 while (g_hash_table_iter_next(&iter, &key, &value)) {
413 message_port_local_port_info_s *mi = (message_port_local_port_info_s *)value;
415 if ((mi->is_trusted == trusted) && strcmp(mi->port_name, local_port) == 0) {
416 *local_id = mi->local_id;
425 static int __get_sender_pid(GDBusConnection *conn, const char *sender_name)
427 GDBusMessage *msg = NULL;
428 GDBusMessage *reply = NULL;
433 msg = g_dbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
434 "org.freedesktop.DBus", "GetConnectionUnixProcessID");
436 _LOGE("Can't allocate new method call");
440 g_dbus_message_set_body(msg, g_variant_new("(s)", sender_name));
441 reply = g_dbus_connection_send_message_with_reply_sync(conn, msg,
442 G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err);
446 _LOGE("Failed to get pid [%s]", err->message);
452 body = g_dbus_message_get_body(reply);
453 g_variant_get(body, "(u)", &pid);
459 g_object_unref(reply);
464 message_port_pkt_s *__message_port_recv_raw(int fd)
468 message_port_pkt_s *pkt = NULL;
470 pkt = (message_port_pkt_s *)calloc(sizeof(char) * MAX_MESSAGE_SIZE, 1);
477 /* receive single packet from socket */
478 len = recv(fd, pkt, MAX_MESSAGE_SIZE, 0);
480 _LOGE("recv error: %d[%s]", errno, strerror(errno));
485 if (len < HEADER_LEN) {
486 _LOGE("recv error %d %d", len, pkt->len);
491 while (len < (pkt->len + HEADER_LEN)) {
493 ret = recv(fd, &pkt->data[len - 8], MAX_MESSAGE_SIZE, 0);
495 SECURE_LOGE("recv error: %d %d %d", errno, len, pkt->len);
507 static gboolean __socket_request_handler(GIOChannel *gio,
512 message_port_callback_info_s *mi;
513 message_port_pkt_s *pkt;
516 GError *error = NULL;
518 if (cond == G_IO_HUP) {
520 _LOGI("socket G_IO_HUP");
521 g_io_channel_shutdown(gio, FALSE, &error);
523 _LOGE("g_io_channel_shutdown error : %s", error->message);
526 g_io_channel_unref(gio);
531 if ((fd = g_io_channel_unix_get_fd(gio)) < 0) {
532 _LOGE("fail to get fd from io channel");
536 mi = (message_port_callback_info_s *)data;
538 if ((pkt = __message_port_recv_raw(fd)) == NULL) {
539 _LOGE("recv error on SOCKET");
543 kb = bundle_decode(pkt->data, pkt->len);
544 is_bidirection = pkt->is_bidirection;
547 mi->callback(mi->local_id, mi->remote_app_id, mi->remote_port, mi->is_trusted, kb, NULL);
549 mi->callback(mi->local_id, mi->remote_app_id, NULL, mi->is_trusted, kb, NULL);
558 static bool send_message(GVariant *parameters, GDBusMethodInvocation *invocation)
560 char *local_port = NULL;
561 char *local_appid = NULL;
562 char *remote_appid = NULL;
563 char *remote_port = NULL;
564 gboolean local_trusted = false;
565 gboolean remote_trusted = false;
566 gboolean bi_dir = false;
570 bundle_raw *raw = NULL;
571 message_port_local_port_info_s *mi;
572 message_port_callback_info_s *callback_info;
573 int local_reg_id = 0;
575 g_variant_get(parameters, "(ssbbssbus)", &local_appid, &local_port, &local_trusted, &bi_dir,
576 &remote_appid, &remote_port, &remote_trusted, &len, &raw);
579 _LOGE("Invalid argument : remote_port is NULL");
583 _LOGE("Invalid argument : remote_appid is NULL");
586 if (!__is_local_port_registed(remote_port, remote_trusted, &local_reg_id, &mi)) {
587 _LOGE("Invalid argument : remote_port:(%s) trusted(%d)", remote_port, remote_trusted);
591 _LOGE("Invalid argument : local_appid");
595 _LOGE("Invalid argument : local_port");
598 if (strcmp(remote_appid, __app_id) != 0) {
599 _LOGE("Invalid argument : remote_appid (%s)", remote_appid);
602 if (strcmp(remote_port, mi->port_name) != 0) {
603 _LOGE("Invalid argument : remote_port (%s)", remote_port);
607 _LOGE("Invalid argument : data_len");
610 if (remote_trusted) {
611 if (g_hash_table_lookup(__trusted_app_list_hash, (gpointer)local_appid) == NULL) {
612 if (!__is_preloaded(local_appid, remote_appid)) {
613 /* Check the certificate */
614 int ret = __check_certificate(local_appid, remote_appid);
615 if (ret == MESSAGEPORT_ERROR_NONE)
616 g_hash_table_insert(__trusted_app_list_hash, local_appid, "TRUE");
618 _LOGE("The application (%s) is not signed with the same certificate",
626 callback_info = (message_port_callback_info_s *)calloc(1, sizeof(message_port_callback_info_s));
627 if (callback_info == NULL)
630 callback_info->local_id = mi->local_id;
631 callback_info->remote_app_id = strdup(local_appid);
632 callback_info->remote_port = strdup(local_port);
633 callback_info->is_trusted = local_trusted;
634 callback_info->callback = mi->callback;
637 GError *error = NULL;
638 GDBusMessage *msg = g_dbus_method_invocation_get_message(invocation);
640 GUnixFDList *fd_list = g_dbus_message_get_unix_fd_list(msg);
641 int fd = g_unix_fd_list_get(fd_list, 0, &error);
643 LOGE("g_unix_fd_list_get fail : %s", error->message);
647 LOGI("g_unix_fd_list_get fd: [%d]", fd);
651 GIOChannel *gio_read = NULL;
652 gio_read = g_io_channel_unix_new(fd);
654 _LOGE("Error is %s\n", strerror(errno));
658 int g_src_id = g_io_add_watch(gio_read, G_IO_IN | G_IO_HUP,
659 __socket_request_handler, (gpointer)callback_info);
661 _LOGE("fail to add watch on socket");
667 data = bundle_decode(raw, len);
668 bundle_free_encoded_rawdata(&raw);
671 _LOGE("Invalid argument : message");
675 LOGI("call calback %s", local_appid);
677 mi->callback(mi->local_id, local_appid, local_port, local_trusted, data, NULL);
679 mi->callback(mi->local_id, local_appid, NULL, false, data, NULL);
687 static int __check_remote_port(const char *remote_app_id, const char *remote_port, bool is_trusted, bool *exist)
689 _LOGI("Check a remote port : [%s:%s]", remote_app_id, remote_port);
691 GVariant *result = NULL;
693 int ret_val = MESSAGEPORT_ERROR_NONE;
694 char *bus_name = NULL;
695 message_port_remote_app_info_s *remote_app_info = NULL;
696 port_list_info_s *port_info = NULL;
697 int local_reg_id = 0;
698 message_port_local_port_info_s *mi = NULL;
699 gboolean name_exist = false;
701 _LOGI("remote_app_id, app_id :[%s : %s] ", remote_app_id, __app_id);
703 ret_val = __get_remote_port_info(remote_app_id, remote_port, is_trusted, &remote_app_info, &port_info);
704 if (ret_val != MESSAGEPORT_ERROR_NONE)
709 if (strcmp(remote_app_id, __app_id) == 0) {
711 _LOGI("__is_local_port_registed ");
712 if (!__is_local_port_registed(remote_port, is_trusted, &local_reg_id, &mi))
717 _LOGI("__is_local_port_registed : %d ", *exist);
718 return MESSAGEPORT_ERROR_NONE;
721 port_info->exist = false;
722 bus_name = port_info->encoded_bus_name;
724 result = g_dbus_connection_call_sync(
730 g_variant_new("(s)", bus_name),
731 G_VARIANT_TYPE("(b)"),
732 G_DBUS_CALL_FLAGS_NONE,
737 if (err || (result == NULL)) {
739 _LOGE("No reply. error = %s", err->message);
742 ret_val = MESSAGEPORT_ERROR_RESOURCE_UNAVAILABLE;
744 g_variant_get(result, "(b)", &name_exist);
747 LOGE("Name not exist %s", bus_name);
749 ret_val = MESSAGEPORT_ERROR_NONE;
753 if (remote_app_info->certificate_info != CERTIFICATE_MATCH) {
754 if (!__is_preloaded(__app_id, remote_app_id)) {
755 if (__check_certificate(__app_id, remote_app_id) != MESSAGEPORT_ERROR_NONE) {
756 ret_val = MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH;
760 remote_app_info->certificate_info = CERTIFICATE_MATCH;
764 port_info->watcher_id = g_bus_watch_name_on_connection(
766 port_info->encoded_bus_name,
767 G_BUS_NAME_WATCHER_FLAGS_NONE,
773 port_info->exist = true;
775 ret_val = MESSAGEPORT_ERROR_NONE;
776 _LOGI("Exist port: %s", bus_name);
782 g_variant_unref(result);
787 static bool __check_sender_validation(GVariant *parameters, const char *sender, GDBusConnection *conn)
790 char buffer[MAX_PACKAGE_STR_SIZE] = {0, };
791 char *local_appid = NULL;
792 int pid = __get_sender_pid(conn, sender);
794 ret = aul_app_get_appid_bypid(pid, buffer, sizeof(buffer));
795 retvm_if(ret != AUL_R_OK, false, "Failed to get the sender ID: (%s) (%d)", sender, pid);
797 g_variant_get_child(parameters, 0, "s", &local_appid);
798 retvm_if(!local_appid, false, "remote_appid is NULL (%s) (%d)", sender, pid);
800 if (strncmp(buffer, local_appid, MAX_PACKAGE_STR_SIZE) == 0) {
801 g_hash_table_insert(__sender_appid_hash, strdup(sender), GINT_TO_POINTER(pid));
810 static void __dbus_method_call_handler(GDBusConnection *conn,
811 const gchar *sender, const gchar *object_path,
812 const gchar *iface_name, const gchar *method_name,
813 GVariant *parameters, GDBusMethodInvocation *invocation,
816 _LOGI("method_name: %s", method_name);
817 gpointer sender_pid = g_hash_table_lookup(__sender_appid_hash, sender);
818 if (sender_pid == NULL) {
819 if (!__check_sender_validation(parameters, sender, conn))
823 if (g_strcmp0(method_name, "send_message") == 0)
824 send_message(parameters, invocation);
828 static const GDBusInterfaceVTable interface_vtable = {
829 __dbus_method_call_handler,
834 static int __dbus_init(void)
837 GError *error = NULL;
839 __gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
840 if (__gdbus_conn == NULL) {
842 _LOGE("Failed to get dbus [%s]", error->message);
852 g_object_unref(__gdbus_conn);
859 int __register_dbus_interface(const char *port_name, bool is_trusted)
862 GDBusNodeInfo *introspection_data = NULL;
863 int registration_id = 0;
865 static gchar introspection_prefix[] =
867 " <interface name='";
869 static gchar introspection_postfix[] =
871 " <method name='send_message'>"
872 " <arg type='s' name='local_appid' direction='in'/>"
873 " <arg type='s' name='local_port' direction='in'/>"
874 " <arg type='b' name='local_trusted' direction='in'/>"
875 " <arg type='b' name='bi_dir' direction='in'/>"
876 " <arg type='s' name='remote_appid' direction='in'/>"
877 " <arg type='s' name='remote_port' direction='in'/>"
878 " <arg type='b' name='remote_trusted' direction='in'/>"
879 " <arg type='u' name='data_len' direction='in'/>"
880 " <arg type='s' name='data' direction='in'/>"
885 char *introspection_xml = NULL;
886 int introspection_xml_len = 0;
890 GError *error = NULL;
891 char *bus_name = NULL;
892 char *interface_name = NULL;
893 GVariant *result = NULL;
895 bus_name = __get_encoded_name(__app_id, port_name, is_trusted);
897 _LOGE("Fail to get bus name");
900 interface_name = bus_name;
902 introspection_xml_len = strlen(introspection_prefix) + strlen(interface_name) +
903 strlen(introspection_postfix) + 1;
905 introspection_xml = (char *)calloc(introspection_xml_len, sizeof(char));
906 if (!introspection_xml) {
907 _LOGE("out of memory");
912 result = g_dbus_connection_call_sync(
918 g_variant_new("(su)", bus_name, G_BUS_NAME_OWNER_FLAGS_NONE),
919 G_VARIANT_TYPE("(u)"),
920 G_DBUS_CALL_FLAGS_NONE,
925 _LOGE("RequestName fail : %s", error->message);
928 if (result == NULL) {
929 _LOGE("fail to get name NULL");
932 g_variant_get(result, "(u)", &owner_id);
934 _LOGE("Acquiring the own name is failed");
938 _LOGI("Acquiring the own name : %d", owner_id);
940 snprintf(introspection_xml, introspection_xml_len, "%s%s%s", introspection_prefix, interface_name, introspection_postfix);
942 introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
943 if (!introspection_data) {
944 _LOGE("g_dbus_node_info_new_for_xml() is failed.");
948 registration_id = g_dbus_connection_register_object(__gdbus_conn,
949 MESSAGEPORT_OBJECT_PATH, introspection_data->interfaces[0],
950 &interface_vtable, NULL, NULL, NULL);
952 _LOGI("registration_id %d", registration_id);
954 if (registration_id == 0) {
955 _LOGE("Failed to g_dbus_connection_register_object");
960 if (introspection_data)
961 g_dbus_node_info_unref(introspection_data);
962 if (introspection_xml)
963 free(introspection_xml);
967 g_variant_unref(result);
970 return registration_id;
974 void __list_free_port_list(gpointer data)
976 port_list_info_s *n = (port_list_info_s *)data;
978 FREE_AND_NULL(n->encoded_bus_name);
979 FREE_AND_NULL(n->port_name);
983 static void __hash_destory_local_value(gpointer data)
985 message_port_local_port_info_s *mli = (message_port_local_port_info_s *)data;
987 free(mli->port_name);
989 static void __hash_destory_remote_value(gpointer data)
991 message_port_remote_app_info_s *mri = (message_port_remote_app_info_s *)data;
994 FREE_AND_NULL(mri->sender_id);
995 FREE_AND_NULL(mri->remote_app_id);
997 g_list_free_full(mri->port_list, __list_free_port_list);
1001 static bool __initialize(void)
1004 #if !GLIB_CHECK_VERSION(2, 35, 0)
1010 char buffer[MAX_PACKAGE_STR_SIZE] = {0, };
1012 _LOGI("initialize");
1013 ret = aul_app_get_appid_bypid(pid, buffer, sizeof(buffer));
1014 retvm_if(ret != AUL_R_OK, false, "Failed to get the application ID: %d", ret);
1016 __app_id = strdup(buffer);
1017 retvm_if(!__app_id, false, "Malloc failed");
1018 _LOGI("init : %s", __app_id);
1020 if (__local_port_info == NULL) {
1021 __local_port_info = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, __hash_destory_local_value);
1022 retvm_if(!__local_port_info, false, "fail to create __local_port_info");
1025 if (__remote_port_info == NULL) {
1026 __remote_port_info = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, __hash_destory_remote_value);
1027 retvm_if(!__remote_port_info, false, "fail to create __remote_port_info");
1030 if (__sender_appid_hash == NULL) {
1031 __sender_appid_hash = g_hash_table_new(g_str_hash, g_str_equal);
1032 retvm_if(!__sender_appid_hash, false, "fail to create __sender_appid_hash");
1035 if (__trusted_app_list_hash == NULL) {
1036 __trusted_app_list_hash = g_hash_table_new(g_str_hash, g_str_equal);
1037 retvm_if(!__trusted_app_list_hash, false, "fail to create __trusted_app_list_hash");
1042 _initialized = true;
1048 static bool __message_port_register_port(const int local_id, const char *local_port, bool is_trusted, messageport_message_cb callback)
1050 message_port_local_port_info_s *mi = (message_port_local_port_info_s *)calloc(1, sizeof(message_port_local_port_info_s));
1051 retvm_if(!mi, false, "Malloc failed");
1053 mi->callback = callback;
1054 mi->is_trusted = is_trusted;
1055 mi->port_name = strdup(local_port);
1056 if (mi->port_name == NULL) {
1057 _LOGE("Malloc failed (%s)", local_port);
1061 mi->local_id = local_id;
1063 g_hash_table_insert(__local_port_info, GINT_TO_POINTER(mi->local_id), mi);
1067 static int __register_message_port(const char *local_port, bool is_trusted, messageport_message_cb callback)
1069 _SECURE_LOGI("Register a message port : [%s:%s]", __app_id, local_port);
1073 /* Check the message port is already registed */
1074 if (__is_local_port_registed(local_port, is_trusted, &local_id, NULL))
1077 local_id = __register_dbus_interface(local_port, is_trusted);
1079 _LOGE("register_dbus_interface fail !!");
1080 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1083 if (!__message_port_register_port(local_id, local_port, is_trusted, callback))
1084 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1089 int __message_port_send_async(int sockfd, bundle *kb, const char *app_id, const char *local_port,
1090 bool local_trusted, bool is_bidirection)
1095 message_port_pkt_s *pkt = NULL;
1099 bundle_raw *kb_data = NULL;
1101 bundle_encode(kb, &kb_data, &datalen);
1102 if (kb_data == NULL) {
1103 _LOGE("bundle encode fail");
1104 ret = MESSAGEPORT_ERROR_IO_ERROR;
1108 if (datalen > MAX_MESSAGE_SIZE - HEADER_LEN) {
1109 _LOGE("bigger than max size\n");
1110 ret = MESSAGEPORT_ERROR_MAX_EXCEEDED;
1114 pkt_size = datalen + 9;
1115 pkt = (message_port_pkt_s *) malloc(sizeof(char) * pkt_size);
1118 _LOGE("Malloc Failed!");
1119 ret = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1122 memset(pkt, 0, pkt_size);
1125 pkt->is_bidirection = is_bidirection;
1127 memcpy(pkt->data, kb_data, datalen);
1129 int retry_ctr = MAX_RETRY_CNT;
1132 if ((len = send(sockfd, pkt, pkt_size, 0)) != pkt_size) {
1133 SECURE_LOGE("send() failed - len[%d] pkt_size[%d] (errno %d[%s])", len, pkt_size,
1134 errno, strerror(errno));
1136 _LOGE("fd:%d\n", sockfd);
1138 if (errno == EINTR) {
1139 if (retry_ctr > 0) {
1140 _LOGI("Retrying send on fd[%d]", sockfd);
1147 ret = MESSAGEPORT_ERROR_IO_ERROR;
1159 static int __message_port_send_message(const char *remote_appid, const char *remote_port,
1160 const char *local_port, bool trusted_message, bool local_trusted, bool bi_dir, bundle *message)
1163 int ret = MESSAGEPORT_ERROR_NONE;
1164 GUnixFDList *fd_list = NULL;
1165 GError *error = NULL;
1168 bundle_raw *raw = NULL;
1169 char *bus_name = NULL;
1170 char *interface_name = NULL;
1172 message_port_remote_app_info_s *remote_app_info = NULL;
1173 port_list_info_s *port_info = NULL;
1174 GDBusMessage *msg = NULL;
1176 GVariant *body = NULL;
1178 ret = __get_remote_port_info(remote_appid, remote_port, trusted_message, &remote_app_info, &port_info);
1179 if (ret != MESSAGEPORT_ERROR_NONE)
1182 if (port_info->exist == false) {
1184 _LOGI("port exist check !!");
1185 ret = __check_remote_port(remote_appid, remote_port, trusted_message, &exist);
1186 if (ret != MESSAGEPORT_ERROR_NONE) {
1188 } else if (!exist) {
1189 ret = MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1194 if (port_info->sock_pair[0] > 0) {
1195 ret = __message_port_send_async(port_info->sock_pair[0], message,
1196 __app_id, (local_port) ? local_port : "", local_trusted, bi_dir);
1199 bus_name = port_info->encoded_bus_name;
1200 interface_name = bus_name;
1202 if (bundle_encode(message, &raw, &len) != BUNDLE_ERROR_NONE) {
1203 ret = MESSAGEPORT_ERROR_INVALID_PARAMETER;
1207 if (MAX_MESSAGE_SIZE < len) {
1208 _LOGE("The size of message (%d) has exceeded the maximum limit.", len);
1209 ret = MESSAGEPORT_ERROR_MAX_EXCEEDED;
1212 body = g_variant_new("(ssbbssbus)", __app_id, (local_port) ? local_port : "", local_trusted, bi_dir,
1213 remote_appid, remote_port, trusted_message, len, raw);
1216 if (strcmp(remote_appid, __app_id) != 0) { /* self send */
1218 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, port_info->sock_pair) != 0) {
1219 _LOGE("error create socket pair");
1220 ret = MESSAGEPORT_ERROR_IO_ERROR;
1224 _LOGI("sock pair : %d, %d", port_info->sock_pair[0], port_info->sock_pair[1]);
1226 fd_list = g_unix_fd_list_new();
1227 g_unix_fd_list_append(fd_list, port_info->sock_pair[1], &err);
1228 g_unix_fd_list_append(fd_list, port_info->sock_pair[0], &err);
1231 _LOGE("g_unix_fd_list_append [%s]", error->message);
1232 ret = MESSAGEPORT_ERROR_IO_ERROR;
1239 msg = g_dbus_message_new_method_call(bus_name, MESSAGEPORT_OBJECT_PATH, interface_name, "send_message");
1241 _LOGE("Can't allocate new method call");
1242 ret = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1246 g_dbus_message_set_unix_fd_list(msg, fd_list);
1247 g_dbus_message_set_body(msg, body);
1248 g_dbus_message_set_flags(msg, G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED);
1249 g_dbus_connection_send_message(__gdbus_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &err);
1251 _LOGE("No reply. error = %s", err->message);
1253 ret = MESSAGEPORT_ERROR_IO_ERROR;
1262 g_object_unref(msg);
1264 bundle_free_encoded_rawdata(&raw);
1266 g_object_unref(fd_list);
1272 int __message_send_bidirectional_message(int id, const char *remote_app_id, const char *remote_port, bool trusted_message, bundle *message)
1274 message_port_local_port_info_s *local_info;
1275 int ret = __get_local_port_info(id, &local_info);
1276 if (ret != MESSAGEPORT_ERROR_NONE)
1279 _LOGI("bidirectional_message %s", local_info->port_name);
1280 return __message_port_send_message(remote_app_id, remote_port,
1281 local_info->port_name, trusted_message, local_info->is_trusted, true, message);
1284 int messageport_unregister_local_port(int local_port_id, bool trusted_port)
1288 char *bus_name = NULL;
1292 _LOGI("unregister : %d", local_port_id);
1294 message_port_local_port_info_s *mi =
1295 (message_port_local_port_info_s *)
1296 g_hash_table_lookup(__local_port_info, GINT_TO_POINTER(local_port_id));
1298 return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1300 if (mi->is_trusted != trusted_port)
1301 return MESSAGEPORT_ERROR_INVALID_PARAMETER;
1303 bus_name = __get_encoded_name(__app_id, mi->port_name, mi->is_trusted);
1304 if (bus_name == NULL)
1305 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1307 g_dbus_connection_unregister_object(__gdbus_conn, local_port_id);
1309 result = g_dbus_connection_call_sync(
1313 DBUS_INTERFACE_DBUS,
1315 g_variant_new("(s)", bus_name),
1316 G_VARIANT_TYPE("(u)"),
1317 G_DBUS_CALL_FLAGS_NONE,
1326 _LOGE("RequestName fail : %s", err->message);
1328 return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1330 g_variant_get(result, "(u)", &ret);
1333 g_variant_unref(result);
1335 if (ret != DBUS_RELEASE_NAME_REPLY_RELEASED) {
1337 if (ret == DBUS_RELEASE_NAME_REPLY_NON_EXISTENT) {
1338 _LOGE("Port Not exist");
1339 return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1340 } else if (ret == DBUS_RELEASE_NAME_REPLY_NOT_OWNER) {
1341 _LOGE("Try to release not owned name. MESSAGEPORT_ERROR_INVALID_PARAMETER");
1342 return MESSAGEPORT_ERROR_INVALID_PARAMETER;
1347 g_hash_table_remove(__local_port_info, GINT_TO_POINTER(local_port_id));
1349 return MESSAGEPORT_ERROR_NONE;
1352 int messageport_register_local_port(const char *local_port, messageport_message_cb callback)
1354 if (!_initialized) {
1355 if (!__initialize())
1356 return MESSAGEPORT_ERROR_IO_ERROR;
1359 return __register_message_port(local_port, false, callback);
1362 int messageport_register_trusted_local_port(const char *local_port, messageport_message_cb callback)
1364 if (!_initialized) {
1365 if (!__initialize())
1366 return MESSAGEPORT_ERROR_IO_ERROR;
1369 return __register_message_port(local_port, true, callback);
1373 int messageport_check_remote_port(const char *remote_app_id, const char *remote_port, bool *exist)
1375 if (!_initialized) {
1376 if (!__initialize())
1377 return MESSAGEPORT_ERROR_IO_ERROR;
1380 int ret = __check_remote_port(remote_app_id, remote_port, false, exist);
1381 if (ret == MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND) {
1383 ret = MESSAGEPORT_ERROR_NONE;
1389 int messageport_check_trusted_remote_port(const char *remote_app_id, const char *remote_port, bool *exist)
1391 if (!_initialized) {
1392 if (!__initialize())
1393 return MESSAGEPORT_ERROR_IO_ERROR;
1396 int ret = __check_remote_port(remote_app_id, remote_port, true, exist);
1397 if (ret == MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND) {
1399 ret = MESSAGEPORT_ERROR_NONE;
1405 int messageport_send_message(const char *remote_app_id, const char *remote_port, bundle *message)
1407 if (!_initialized) {
1408 if (!__initialize())
1409 return MESSAGEPORT_ERROR_IO_ERROR;
1412 return __message_port_send_message(remote_app_id, remote_port, NULL, false, false, false, message);
1415 int messageport_send_trusted_message(const char *remote_app_id, const char *remote_port, bundle *message)
1417 if (!_initialized) {
1418 if (!__initialize())
1419 return MESSAGEPORT_ERROR_IO_ERROR;
1422 return __message_port_send_message(remote_app_id, remote_port, NULL, true, false, false, message);
1425 int messageport_send_bidirectional_message(int id, const char *remote_app_id, const char *remote_port,
1428 if (!_initialized) {
1429 if (!__initialize())
1430 return MESSAGEPORT_ERROR_IO_ERROR;
1433 return __message_send_bidirectional_message(id, remote_app_id, remote_port, false, message);
1436 int messageport_send_bidirectional_trusted_message(int id, const char *remote_app_id, const char *remote_port,
1439 if (!_initialized) {
1440 if (!__initialize())
1441 return MESSAGEPORT_ERROR_IO_ERROR;
1443 return __message_send_bidirectional_message(id, remote_app_id, remote_port, true, message);
1446 int messageport_get_local_port_name(int id, char **name)
1448 message_port_local_port_info_s *local_info;
1449 int ret = __get_local_port_info(id, &local_info);
1451 if (ret != MESSAGEPORT_ERROR_NONE)
1454 *name = strdup(local_info->port_name);
1457 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1459 return MESSAGEPORT_ERROR_NONE;
1462 int messageport_check_trusted_local_port(int id, bool *trusted)
1464 message_port_local_port_info_s *local_info;
1465 int ret = __get_local_port_info(id, &local_info);
1467 if (ret != MESSAGEPORT_ERROR_NONE)
1470 *trusted = local_info->is_trusted;
1472 return MESSAGEPORT_ERROR_NONE;;