3 // Copyright (c) 2015 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
19 * @file message-port.cpp
20 * @brief This is the implementation file for the MessagePort.
28 #include <openssl/md5.h>
30 #include <bundle_internal.h>
31 #include <pkgmgr-info.h>
33 #include "message-port.h"
34 #include "message-port-log.h"
37 #define MAX_PACKAGE_STR_SIZE 512
38 #define MESSAGEPORT_BUS_NAME_PREFIX "org.tizen.messageport._"
39 #define MESSAGEPORT_OBJECT_PATH "/org/tizen/messageport"
40 #define MESSAGEPORT_INTERFACE "org.tizen.messageport"
41 #define MESSAGEPORT_INTERFACE_PREFIX "org.tizen.messageport._"
45 #define retvm_if(expr, val, fmt, arg...) do { \
48 _LOGE("(%s) -> %s() return", #expr, __func__); \
53 #define retv_if(expr, val) do { \
55 _LOGE("(%s) -> %s() return", #expr, __func__); \
60 #define FREE_AND_NULL(ptr) do { \
67 static bool _initialized = false;
68 static GDBusConnection *__gdbus_conn = NULL;
69 static char *__app_id;
70 static GHashTable *__local_port_info = NULL;
71 static GHashTable *__remote_port_info = NULL;;
72 static GHashTable *__sender_appid_hash = NULL;;
73 static GHashTable *__checked_app_list_hash = NULL;
74 static GHashTable *__trusted_app_list_hash = NULL;
75 static const int MAX_MESSAGE_SIZE = 16 * 1024;
79 enum __certificate_info_type {
82 CERTIFICATE_NOT_MATCH,
85 typedef struct message_port_local_port_info {
86 messageport_message_cb callback;
90 } message_port_local_port_info_s;
92 typedef struct message_port_remote_port_info {
93 char *encoded_bus_name;
99 } message_port_remote_app_info_s;
101 typedef struct port_list_info {
107 static char *__get_encoded_name(const char *name, const char *prefix, int prefix_len,
108 const char *postfix, int postfix_len)
110 unsigned char c[MD5_DIGEST_LENGTH] = {0};
111 char *md5_interface = NULL;
115 int interface_len = prefix_len + postfix_len + (MD5_DIGEST_LENGTH * 2) + 2;
117 MD5_Init(&mdContext);
118 MD5_Update(&mdContext, name, strlen(name));
119 MD5_Final(c, &mdContext);
121 md5_interface = (char *)calloc(interface_len , sizeof(char));
122 if (md5_interface == NULL) {
123 _LOGI("Malloc failed!!");
127 snprintf(md5_interface, interface_len, "%s", prefix);
128 temp = md5_interface;
131 for (index = 0; index < MD5_DIGEST_LENGTH; index++) {
132 snprintf(temp, 3, "%02x", c[index]);
136 if (postfix && postfix_len > 0) {
137 snprintf(temp, interface_len - (temp - md5_interface), "_%s", postfix);
140 return md5_interface;
143 static char *__get_interface_name(const char *port_name, bool is_trusted)
145 char *interface_name = NULL;
147 interface_name = __get_encoded_name(port_name,
148 MESSAGEPORT_INTERFACE_PREFIX,
149 strlen(MESSAGEPORT_INTERFACE_PREFIX),
150 is_trusted ? "1" : "0", 1);
152 if (!interface_name) {
153 _LOGE("failed to get interface name ");
156 return interface_name;
159 static char *__get_bus_name(const char *remote_app_id)
161 char *bus_name = NULL;
163 bus_name = __get_encoded_name(remote_app_id,
164 MESSAGEPORT_BUS_NAME_PREFIX,
165 strlen(MESSAGEPORT_BUS_NAME_PREFIX),
168 _LOGE("fail to get bus name");
173 static int __remote_port_compare_cb(gconstpointer a, gconstpointer b)
175 port_list_info_s *key1 = (port_list_info_s *)a;
176 port_list_info_s *key2 = (port_list_info_s *)b;
178 if (key1->is_trusted == key2->is_trusted) {
179 return strcmp(key1->port_name, key2->port_name);
186 static bool __is_preloaded(const char *local_appid, const char *remote_appid)
188 _LOGI("IsPreloaded");
190 bool preload_local = false;
191 bool preload_remote = false;
193 pkgmgrinfo_appinfo_h handle = NULL;
194 int ret = pkgmgrinfo_appinfo_get_usr_appinfo(local_appid, getuid(), &handle);
195 if (ret != PMINFO_R_OK) {
196 _LOGE("Failed to get the appinfo. %d", ret);
197 pkgmgrinfo_appinfo_destroy_appinfo(handle);
200 ret = pkgmgrinfo_appinfo_is_preload(handle, &preload_local);
201 if (ret != PMINFO_R_OK) {
202 _LOGE("Failed to check the preloaded application. %d", ret);
203 pkgmgrinfo_appinfo_destroy_appinfo(handle);
206 ret = pkgmgrinfo_appinfo_get_usr_appinfo(remote_appid, getuid(), &handle);
207 if (ret != PMINFO_R_OK) {
208 _LOGE("Failed to get the appinfo. %d", ret);
209 pkgmgrinfo_appinfo_destroy_appinfo(handle);
212 ret = pkgmgrinfo_appinfo_is_preload(handle, &preload_remote);
213 if (ret != PMINFO_R_OK) {
214 _LOGE("Failed to check the preloaded application. %d", ret);
215 pkgmgrinfo_appinfo_destroy_appinfo(handle);
219 if (preload_local && preload_remote) {
220 pkgmgrinfo_appinfo_destroy_appinfo(handle);
223 pkgmgrinfo_appinfo_destroy_appinfo(handle);
227 static int __check_certificate(const char *local_appid, const char *remote_appid)
229 _LOGI("CheckCertificate");
231 pkgmgrinfo_cert_compare_result_type_e res;
232 int ret = pkgmgrinfo_pkginfo_compare_usr_app_cert_info(local_appid, remote_appid, getuid(), &res);
234 _LOGE(":CheckCertificate() Failed");
235 return MESSAGEPORT_ERROR_IO_ERROR;
237 if (res != PMINFO_CERT_COMPARE_MATCH) {
238 _LOGE("CheckCertificate() Failed : MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH");
239 return MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH;
242 return MESSAGEPORT_ERROR_NONE;
245 static void on_name_appeared (GDBusConnection *connection,
247 const gchar *name_owner,
250 _LOGI("name appeared : %s %s", __app_id, name);
253 static void on_name_vanished (GDBusConnection *connection,
257 _LOGI("name vanished : %s", name);
258 message_port_remote_app_info_s *remote_app_info = (message_port_remote_app_info_s *)user_data;
259 g_bus_unwatch_name(remote_app_info->watcher_id);
260 g_hash_table_remove(__remote_port_info, remote_app_info->remote_app_id);
263 static void __hash_destory_list_value(gpointer data)
265 GList *list = (GList *)data;
266 g_list_foreach(list, (GFunc)g_free, NULL);
271 static void __set_checked_app_list(message_port_local_port_info_s *mi, char *remote_appid) {
273 GList *app_list = (GList *)g_hash_table_lookup(__checked_app_list_hash, mi->port_name);
274 if (app_list == NULL) {
275 app_list = g_list_append(app_list, strdup(remote_appid));
276 _LOGI("set checked_app_list appid: %s", remote_appid);
277 g_hash_table_insert(__checked_app_list_hash, mi->port_name, app_list);
279 GList *app = g_list_find(app_list, (gpointer)remote_appid);
281 app_list = g_list_append(app_list, strdup(remote_appid));
282 _LOGI("set checked_app_list appid: %s", remote_appid);
287 static int __get_local_port_info(int id, message_port_local_port_info_s **info)
289 message_port_local_port_info_s *mi = (message_port_local_port_info_s *)g_hash_table_lookup(__local_port_info, GINT_TO_POINTER(id));
292 return MESSAGEPORT_ERROR_INVALID_PARAMETER;
296 return MESSAGEPORT_ERROR_NONE;
299 static port_list_info_s *__set_remote_port_info(const char *remote_app_id, const char *remote_port, bool is_trusted)
301 int ret_val = MESSAGEPORT_ERROR_NONE;
302 port_list_info_s *port_info = (port_list_info_s *)calloc(1, sizeof(port_list_info_s));
305 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
308 port_info->port_name = strdup(remote_port);
309 if (!port_info->port_name) {
310 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
313 port_info->is_trusted = is_trusted;
316 if (ret_val != MESSAGEPORT_ERROR_NONE) {
318 FREE_AND_NULL(port_info->port_name);
326 static message_port_remote_app_info_s *__set_remote_app_info(const char *remote_app_id, const char *remote_port, bool is_trusted)
328 port_list_info_s *port_info = NULL;
329 message_port_remote_app_info_s *remote_app_info = NULL;
330 int ret_val = MESSAGEPORT_ERROR_NONE;
332 remote_app_info = (message_port_remote_app_info_s *)calloc(1, sizeof(message_port_remote_app_info_s));
333 if (!remote_app_info) {
334 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
338 remote_app_info->encoded_bus_name = __get_bus_name(remote_app_id);
339 if (remote_app_info->encoded_bus_name == NULL) {
340 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
344 remote_app_info->remote_app_id = strdup(remote_app_id);
345 if (remote_app_info->remote_app_id == NULL) {
346 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;;
350 remote_app_info->watcher_id = g_bus_watch_name(G_BUS_TYPE_SESSION,
351 remote_app_info->encoded_bus_name,
352 G_BUS_NAME_WATCHER_FLAGS_NONE,
358 port_info = __set_remote_port_info(remote_app_id, remote_port, is_trusted);
359 if (port_info == NULL) {
360 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
364 remote_app_info->port_list = g_list_append(remote_app_info->port_list, port_info);
367 if (ret_val != MESSAGEPORT_ERROR_NONE) {
368 if (remote_app_info) {
369 FREE_AND_NULL(remote_app_info->encoded_bus_name);
370 FREE_AND_NULL(remote_app_info->remote_app_id);
371 FREE_AND_NULL(remote_app_info);
375 return remote_app_info;
378 static int __get_remote_port_info(const char *remote_app_id, const char *remote_port, bool is_trusted,
379 message_port_remote_app_info_s **mri, port_list_info_s **pli)
381 message_port_remote_app_info_s *remote_app_info = NULL;
382 port_list_info_s port_info;
383 GList *cb_list = NULL;
385 remote_app_info = (message_port_remote_app_info_s *)g_hash_table_lookup(__remote_port_info, remote_app_id);
387 if (remote_app_info == NULL) {
388 remote_app_info = __set_remote_app_info(remote_app_id, remote_port, is_trusted);
389 retvm_if(!remote_app_info, MESSAGEPORT_ERROR_OUT_OF_MEMORY, "fail to create message_port_remote_app_info_s");
390 g_hash_table_insert(__remote_port_info, remote_app_info->remote_app_id, remote_app_info);
393 *mri = remote_app_info;
395 port_info.port_name = strdup(remote_port);
396 port_info.is_trusted = is_trusted;
397 cb_list = g_list_find_custom(remote_app_info->port_list, &port_info,
398 (GCompareFunc)__remote_port_compare_cb);
399 if (port_info.port_name)
400 free(port_info.port_name);
401 if (cb_list == NULL) {
402 port_list_info_s *tmp = __set_remote_port_info(remote_app_id, remote_port, is_trusted);
403 retvm_if(!tmp, MESSAGEPORT_ERROR_OUT_OF_MEMORY, "fail to create port_list_info_s");
404 remote_app_info->port_list = g_list_append(remote_app_info->port_list, tmp);
407 *pli = (port_list_info_s *)cb_list->data;
409 return MESSAGEPORT_ERROR_NONE;
412 static bool __is_local_port_registed(const char *local_port, bool trusted, int *local_id, message_port_local_port_info_s **lpi)
417 g_hash_table_iter_init(&iter, __local_port_info);
419 while (g_hash_table_iter_next(&iter, &key, &value)) {
420 message_port_local_port_info_s *mi = (message_port_local_port_info_s *)value;
422 if ((mi->is_trusted == trusted) && strcmp(mi->port_name, local_port) == 0) {
423 *local_id = mi->local_id;
433 static int __get_sender_pid(GDBusConnection *conn, const char *sender_name)
435 GDBusMessage *msg = NULL;
436 GDBusMessage *reply = NULL;
441 msg = g_dbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
442 "org.freedesktop.DBus", "GetConnectionUnixProcessID");
444 _LOGE("Can't allocate new method call");
448 g_dbus_message_set_body (msg, g_variant_new ("(s)", sender_name));
449 reply = g_dbus_connection_send_message_with_reply_sync(conn, msg,
450 G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err);
454 _LOGE("Failed to get pid [%s]", err->message);
460 body = g_dbus_message_get_body(reply);
461 g_variant_get(body, "(u)", &pid);
467 g_object_unref(reply);
473 static bool send_message(GVariant *parameters)
475 char *local_port = NULL;
476 char *local_appid = NULL;
477 char *remote_appid = NULL;
478 char *remote_port = NULL;
479 gboolean local_trusted = false;
480 gboolean remote_trusted = false;
481 gboolean bi_dir = false;
485 bundle_raw *raw = NULL;
486 message_port_local_port_info_s *mi;
487 int local_reg_id = 0;
489 g_variant_get(parameters, "(ssbbssbus)", &local_appid, &local_port, &local_trusted, &bi_dir,
490 &remote_appid, &remote_port, &remote_trusted, &len, &raw);
493 _LOGE("Invalid argument : remote_port is NULL");
497 _LOGE("Invalid argument : remote_appid is NULL");
500 if (!__is_local_port_registed(remote_port, remote_trusted, &local_reg_id, &mi)) {
501 _LOGE("Invalid argument : remote_port:(%s) trusted(%d)", remote_port, remote_trusted);
505 _LOGE("Invalid argument : local_appid");
509 _LOGE("Invalid argument : local_port");
512 if (strcmp(remote_appid, __app_id) != 0) {
513 _LOGE("Invalid argument : remote_appid (%s)", remote_appid);
516 if (strcmp(remote_port, mi->port_name) != 0) {
517 _LOGE("Invalid argument : remote_port (%s)", remote_port);
521 _LOGE("Invalid argument : data_len");
524 if (remote_trusted) {
525 if (g_hash_table_lookup(__trusted_app_list_hash, (gpointer)local_appid) == NULL) {
526 if (!__is_preloaded(local_appid, remote_appid)) {
527 // Check the certificate
528 int ret = __check_certificate(local_appid, remote_appid);
529 if (ret == MESSAGEPORT_ERROR_NONE) {
530 g_hash_table_insert(__trusted_app_list_hash, local_appid, "TRUE");
532 _LOGE("The application (%s) is not signed with the same certificate",
540 __set_checked_app_list(mi, local_appid);
541 data = bundle_decode(raw, len);
542 bundle_free_encoded_rawdata(&raw);
545 _LOGE("Invalid argument : message");
550 mi->callback(mi->local_id, local_appid, local_port, local_trusted, data);
552 mi->callback(mi->local_id, local_appid, NULL, false, data);
559 static int unregister_port(GVariant *parameters)
561 int ret = MESSAGEPORT_ERROR_NONE;
562 char *remote_appid = NULL;
563 char *remote_port = NULL;
565 port_list_info_s *port_info = NULL;
566 message_port_remote_app_info_s *remote_app_info = NULL;
568 g_variant_get(parameters, "(sbs)", &remote_appid, &is_trusted, &remote_port);
571 _LOGE("Invalid argument : remote_appid");
572 ret = MESSAGEPORT_ERROR_INVALID_PARAMETER;
576 _LOGE("Invalid argument : remote_port");
577 ret = MESSAGEPORT_ERROR_INVALID_PARAMETER;
581 ret = __get_remote_port_info(remote_appid, remote_port, is_trusted, &remote_app_info, &port_info);
582 if (ret != MESSAGEPORT_ERROR_NONE) {
585 port_info->exist = false;
590 g_free(remote_appid);
597 static int __check_remote_port(const char *remote_app_id, const char *remote_port, bool is_trusted, bool *exist)
599 _LOGI("Check a remote port : [%s:%s]", remote_app_id, remote_port);
601 GDBusMessage *msg = NULL;
602 GDBusMessage *reply = NULL;
605 int ret_val = MESSAGEPORT_ERROR_NONE;
606 char *bus_name = NULL;
607 message_port_remote_app_info_s *remote_app_info = NULL;
608 port_list_info_s *port_info = NULL;
609 int local_reg_id = 0;
610 message_port_local_port_info_s *mi = NULL;
611 GDBusNodeInfo *node_info;
612 GDBusInterfaceInfo *interface_info;
613 const gchar *xml_data;
614 char *interface_name = NULL;
616 _LOGI("remote_app_id, app_id :[%s : %s] ", remote_app_id, __app_id);
618 ret_val = __get_remote_port_info(remote_app_id, remote_port, is_trusted, &remote_app_info, &port_info);
619 if (ret_val != MESSAGEPORT_ERROR_NONE) {
624 if (strcmp(remote_app_id, __app_id) == 0) {
626 _LOGI("__is_local_port_registed ");
627 if (!__is_local_port_registed(remote_port, is_trusted, &local_reg_id, &mi)) {
632 _LOGI("__is_local_port_registed : %d ", *exist);
633 return MESSAGEPORT_ERROR_NONE;
636 port_info->exist = false;
637 bus_name = remote_app_info->encoded_bus_name;
639 msg = g_dbus_message_new_method_call(bus_name, MESSAGEPORT_OBJECT_PATH,
640 "org.freedesktop.DBus.Introspectable",
642 _LOGI("bus_name, remote app id:[%s : %s] ", bus_name, remote_app_id);
644 _LOGI("Can't allocate new method call");
645 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
648 g_dbus_message_set_body(msg, NULL);
649 reply = g_dbus_connection_send_message_with_reply_sync(__gdbus_conn, msg,
650 G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err);
652 if (err || (reply == NULL)) {
654 _LOGE("No reply. error = %s", err->message);
657 ret_val = MESSAGEPORT_ERROR_RESOURCE_UNAVAILABLE;
659 body = g_dbus_message_get_body(reply);
660 g_variant_get(body, "(&s)", &xml_data);
662 node_info = g_dbus_node_info_new_for_xml(xml_data, &err);
664 LOGE("g_dbus_node_info_new_for_xml [%s]", err->message);
666 ret_val = MESSAGEPORT_ERROR_NONE;
670 interface_name = __get_interface_name(remote_port, is_trusted);
671 if (interface_name == NULL) {
672 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
676 LOGI("Lookup interface : %s", interface_name);
677 interface_info = g_dbus_node_info_lookup_interface(node_info, interface_name);
678 if (interface_info == NULL) {
679 LOGE("g_dbus_node_info_lookup_interface NULL %s", interface_name);
681 ret_val = MESSAGEPORT_ERROR_NONE;
686 if (remote_app_info->certificate_info != CERTIFICATE_MATCH) {
687 if (!__is_preloaded(__app_id, remote_app_id)) {
688 if (__check_certificate(__app_id, remote_app_id) != MESSAGEPORT_ERROR_NONE) {
689 ret_val = MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH;
693 remote_app_info->certificate_info = CERTIFICATE_MATCH;
696 port_info->exist = true;
698 ret_val = MESSAGEPORT_ERROR_NONE;
706 g_object_unref(reply);
708 free(interface_name);
713 static bool __check_sender_validation(GVariant *parameters, const char *sender, GDBusConnection *conn)
716 char buffer[MAX_PACKAGE_STR_SIZE] = {0, };
717 char *local_appid = NULL;
718 int pid = __get_sender_pid(conn, sender);
720 ret = aul_app_get_appid_bypid(pid, buffer, sizeof(buffer));
721 retvm_if(ret != AUL_R_OK, false, "Failed to get the sender ID: (%s) (%d)", sender, pid);
723 g_variant_get_child(parameters, 0, "s", &local_appid);
724 retvm_if(!local_appid, false, "remote_appid is NULL (%s) (%d)", sender, pid);
726 if (strncmp(buffer, local_appid, MAX_PACKAGE_STR_SIZE) == 0) {
727 g_hash_table_insert(__sender_appid_hash, strdup(sender), GINT_TO_POINTER(pid));
736 static void __dbus_method_call_handler(GDBusConnection *conn,
737 const gchar *sender, const gchar *object_path,
738 const gchar *iface_name, const gchar *method_name,
739 GVariant *parameters, GDBusMethodInvocation *invocation,
742 _LOGI("method_name: %s", method_name);
743 gpointer sender_pid = g_hash_table_lookup(__sender_appid_hash, sender);
744 int ret = MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
745 if (sender_pid == NULL) {
746 if (!__check_sender_validation(parameters, sender, conn))
750 if (g_strcmp0(method_name, "send_message") == 0) {
751 ret = send_message(parameters);
752 } else if (g_strcmp0(method_name, "unregister_port") == 0) {
753 ret = unregister_port(parameters);
754 g_dbus_method_invocation_return_value(invocation,
755 g_variant_new("(i)", ret));
761 static const GDBusInterfaceVTable interface_vtable = {
762 __dbus_method_call_handler,
767 static int __dbus_init(void)
770 char *bus_name = NULL;
772 GError *error = NULL;
774 bus_name = __get_bus_name(__app_id);
775 retvm_if(!bus_name, false, "bus_name is NULL");
776 LOGI("bus name : %s", bus_name);
778 __gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
779 if (__gdbus_conn == NULL) {
781 _LOGE("Failed to get dbus [%s]", error->message);
787 owner_id = g_bus_own_name_on_connection(__gdbus_conn, bus_name,
788 G_BUS_NAME_OWNER_FLAGS_NONE, NULL, NULL, NULL, NULL);
791 _LOGE("Acquiring the own name is failed");
798 FREE_AND_NULL(bus_name);
800 g_object_unref(__gdbus_conn);
807 int __register_dbus_interface(const char *port_name, bool is_trusted) {
809 GDBusNodeInfo *introspection_data = NULL;
810 int registration_id = 0;
812 static gchar introspection_prefix[] =
814 " <interface name='";
816 static gchar introspection_postfix[] =
818 " <method name='send_message'>"
819 " <arg type='s' name='local_appid' direction='in'/>"
820 " <arg type='s' name='local_port' direction='in'/>"
821 " <arg type='b' name='local_trusted' direction='in'/>"
822 " <arg type='b' name='bi_dir' direction='in'/>"
823 " <arg type='s' name='remote_appid' direction='in'/>"
824 " <arg type='s' name='remote_port' direction='in'/>"
825 " <arg type='b' name='remote_trusted' direction='in'/>"
826 " <arg type='u' name='data_len' direction='in'/>"
827 " <arg type='s' name='data' direction='in'/>"
829 " <method name='unregister_port'>"
830 " <arg type='s' name='local_appid' direction='in'/>"
831 " <arg type='b' name='is_trusted' direction='in'/>"
832 " <arg type='s' name='remote_port' direction='in'/>"
833 " <arg type='i' name='response' direction='out'/>"
838 char *interface_name = NULL;
839 char *introspection_xml = NULL;
840 int introspection_xml_len = 0;
842 interface_name = __get_interface_name(port_name, is_trusted);
843 if (interface_name == NULL) {
844 LOGE("Fail to get interface name %d", introspection_xml_len);
848 introspection_xml_len = strlen(introspection_prefix) + strlen(interface_name) +
849 strlen(introspection_postfix) + 1;
851 LOGI("interface_name %s", interface_name);
853 introspection_xml = (char *)calloc(introspection_xml_len, sizeof(char));
855 snprintf(introspection_xml, introspection_xml_len, "%s%s%s", introspection_prefix, interface_name, introspection_postfix);
857 introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
858 if (!introspection_data) {
859 _LOGE("g_dbus_node_info_new_for_xml() is failed.");
863 registration_id = g_dbus_connection_register_object(__gdbus_conn,
864 MESSAGEPORT_OBJECT_PATH, introspection_data->interfaces[0],
865 &interface_vtable, NULL, NULL, NULL);
867 _LOGE("registration_id %d", registration_id);
869 if (registration_id == 0) {
870 _LOGE("Failed to g_dbus_connection_register_object");
875 if (introspection_data)
876 g_dbus_node_info_unref(introspection_data);
878 free(interface_name);
879 if (introspection_xml)
880 free(introspection_xml);
883 return registration_id;
887 void __list_free_port_list(gpointer data)
889 port_list_info_s *n = (port_list_info_s *)data;
891 FREE_AND_NULL(n->port_name);
895 static void __hash_destory_local_value(gpointer data)
897 message_port_local_port_info_s *mli = (message_port_local_port_info_s *)data;
899 free(mli->port_name);
901 static void __hash_destory_remote_value(gpointer data)
903 message_port_remote_app_info_s *mri = (message_port_remote_app_info_s *)data;
906 FREE_AND_NULL(mri->encoded_bus_name);
907 FREE_AND_NULL(mri->sender_id);
908 FREE_AND_NULL(mri->remote_app_id);
909 if (mri->port_list) {
910 g_list_free_full(mri->port_list, __list_free_port_list);
915 static bool __initialize(void)
920 char buffer[MAX_PACKAGE_STR_SIZE] = {0, };
923 ret = aul_app_get_appid_bypid(pid, buffer, sizeof(buffer));
924 retvm_if(ret != AUL_R_OK, false, "Failed to get the application ID: %d", ret);
926 __app_id = strdup(buffer);
927 retvm_if(!__app_id, false, "Malloc failed");
928 _LOGI("init : %s", __app_id);
930 if (__local_port_info == NULL) {
931 __local_port_info = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, __hash_destory_local_value);
932 retvm_if(!__local_port_info, false, "fail to create __local_port_info");
935 if (__remote_port_info == NULL) {
936 __remote_port_info = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, __hash_destory_remote_value);
937 retvm_if(!__remote_port_info, false, "fail to create __remote_port_info");
940 if (__sender_appid_hash == NULL) {
941 __sender_appid_hash = g_hash_table_new(g_str_hash, g_str_equal);
942 retvm_if(!__sender_appid_hash, false, "fail to create __sender_appid_hash");
945 if (__trusted_app_list_hash == NULL)
946 __trusted_app_list_hash = g_hash_table_new(g_str_hash, g_str_equal);
948 if (__checked_app_list_hash == NULL)
949 __checked_app_list_hash =
950 g_hash_table_new_full(g_str_hash, g_str_equal, NULL, __hash_destory_list_value);
953 if (!__dbus_init()) {
962 static bool __message_port_register_port(const int local_id, const char *local_port, bool is_trusted, messageport_message_cb callback)
964 message_port_local_port_info_s *mi = (message_port_local_port_info_s *)calloc(1, sizeof(message_port_local_port_info_s));
965 retvm_if(!mi, false, "Malloc failed");
967 mi->callback = callback;
968 mi->is_trusted = is_trusted;
969 mi->port_name = strdup(local_port);
970 if (mi->port_name == NULL) {
971 _LOGE("Malloc failed (%s)", local_port);
975 mi->local_id = local_id;
977 g_hash_table_insert(__local_port_info, GINT_TO_POINTER(mi->local_id), mi);
981 static int __register_message_port(const char *local_port, bool is_trusted, messageport_message_cb callback)
983 _SECURE_LOGI("Register a message port : [%s:%s]", __app_id, local_port);
987 // Check the message port is already registed
988 if (__is_local_port_registed(local_port, is_trusted, &local_id, NULL)) {
992 local_id = __register_dbus_interface(local_port, is_trusted);
994 _LOGE("register_dbus_interface fail !!");
995 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
998 if (!__message_port_register_port(local_id, local_port, is_trusted, callback)) {
999 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1005 static int __message_port_send_message(const char *remote_appid, const char *remote_port,
1006 const char *local_port, bool trusted_message, bool local_trusted, bool bi_dir, bundle *message)
1008 int ret = MESSAGEPORT_ERROR_NONE;
1010 bundle_raw *raw = NULL;
1011 char *bus_name = NULL;
1012 char *interface_name = NULL;
1014 message_port_remote_app_info_s *remote_app_info = NULL;
1015 port_list_info_s *port_info = NULL;
1016 GDBusMessage *msg = NULL;
1018 GVariant *body = NULL;
1020 ret = __get_remote_port_info(remote_appid, remote_port, trusted_message, &remote_app_info, &port_info);
1021 if (ret != MESSAGEPORT_ERROR_NONE) {
1025 if (port_info->exist == false) {
1027 _LOGI("port exist check !!");
1028 ret = __check_remote_port(remote_appid, remote_port, trusted_message, &exist);
1029 if (ret != MESSAGEPORT_ERROR_NONE) {
1031 } else if (!exist) {
1032 ret = MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1037 bus_name = remote_app_info->encoded_bus_name;
1039 if (bundle_encode(message, &raw, &len) != BUNDLE_ERROR_NONE) {
1040 ret = MESSAGEPORT_ERROR_INVALID_PARAMETER;
1044 if (MAX_MESSAGE_SIZE < len) {
1045 _LOGE("The size of message (%d) has exceeded the maximum limit.", len);
1046 ret = MESSAGEPORT_ERROR_MAX_EXCEEDED;
1049 body = g_variant_new("(ssbbssbus)", __app_id, (local_port) ? local_port : "", local_trusted, bi_dir,
1050 remote_appid, remote_port, trusted_message, len, raw);
1052 interface_name = __get_interface_name(remote_port, trusted_message);
1053 if (!interface_name) {
1054 _LOGE("Can't get interface_name");
1055 ret = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1059 msg = g_dbus_message_new_method_call(bus_name, MESSAGEPORT_OBJECT_PATH, interface_name, "send_message");
1061 _LOGE("Can't allocate new method call");
1062 ret = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1066 g_dbus_message_set_body(msg, body);
1067 g_dbus_message_set_flags(msg, G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED);
1068 g_dbus_connection_send_message(__gdbus_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &err);
1070 _LOGE("No reply. error = %s", err->message);
1072 ret = MESSAGEPORT_ERROR_IO_ERROR;
1078 g_object_unref(msg);
1080 bundle_free_encoded_rawdata(&raw);
1082 free(interface_name);
1087 int __message_send_bidirectional_message(int id, const char *remote_app_id, const char *remote_port, bool trusted_message, bundle *message)
1089 message_port_local_port_info_s *local_info;
1090 int ret = __get_local_port_info(id, &local_info);
1091 if (ret != MESSAGEPORT_ERROR_NONE) {
1095 _LOGE("bidirectional_message %s", local_info->port_name);
1096 return __message_port_send_message(remote_app_id, remote_port,
1097 local_info->port_name, trusted_message, local_info->is_trusted, true, message);
1100 int messageport_unregister_local_port(int local_port_id, bool trusted_port)
1103 GDBusMessage *msg = NULL;
1104 GDBusMessage *reply = NULL;
1106 char *bus_name = NULL;
1107 GList *checked_app_list = NULL;
1108 GList *checked_app = NULL;
1110 _LOGE("unregister : %d", local_port_id);
1112 message_port_local_port_info_s *mi =
1113 (message_port_local_port_info_s *)
1114 g_hash_table_lookup(__local_port_info, GINT_TO_POINTER(local_port_id));
1116 return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1118 if (mi->is_trusted != trusted_port)
1119 return MESSAGEPORT_ERROR_INVALID_PARAMETER;
1121 checked_app_list = (GList *)g_hash_table_lookup(__checked_app_list_hash, mi->port_name);
1123 for (checked_app = checked_app_list; checked_app != NULL;
1124 checked_app = checked_app->next) {
1127 char *checked_app_id = (char *)checked_app->data;
1128 char *interface_name = __get_interface_name(mi->port_name, mi->is_trusted);
1129 if (interface_name == NULL) {
1130 _LOGI("Can't get interface_name");
1131 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1134 _LOGI("unregister appid: %s", checked_app_id);
1135 bus_name = __get_bus_name(checked_app_id);
1136 msg = g_dbus_message_new_method_call(bus_name, MESSAGEPORT_OBJECT_PATH,
1137 interface_name, "unregister_port");
1140 free(interface_name);
1143 _LOGI("Can't allocate new method call");
1144 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1147 g_dbus_message_set_body(msg,
1148 g_variant_new("(sbs)", __app_id, mi->is_trusted, mi->port_name));
1149 reply = g_dbus_connection_send_message_with_reply_sync(
1152 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
1158 if (err || (reply == NULL)) {
1160 _LOGE("No reply. error = %s", err->message);
1164 if (g_dbus_message_to_gerror(reply, &err)) {
1166 _LOGE("error = %s", err->message);
1170 int ret_val = MESSAGEPORT_ERROR_NONE;
1172 body = g_dbus_message_get_body(reply);
1173 g_variant_get(body, "(u)", &ret_val);
1175 if (ret_val == MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH) {
1176 _SECURE_LOGI("The remote application (%s) is not signed with the same certificate"
1182 g_object_unref(msg);
1184 g_object_unref(reply);
1188 g_hash_table_remove(__checked_app_list_hash, mi->port_name);
1189 g_hash_table_remove(__local_port_info, GINT_TO_POINTER(local_port_id));
1191 g_dbus_connection_unregister_object(__gdbus_conn, local_port_id);
1194 g_object_unref(msg);
1196 g_object_unref(reply);
1198 return MESSAGEPORT_ERROR_NONE;
1201 int messageport_register_local_port(const char *local_port, messageport_message_cb callback)
1203 if (!_initialized) {
1204 if (!__initialize())
1205 return MESSAGEPORT_ERROR_IO_ERROR;
1208 return __register_message_port(local_port, false, callback);
1211 int messageport_register_trusted_local_port(const char *local_port, messageport_message_cb callback)
1213 if (!_initialized) {
1214 if (!__initialize())
1215 return MESSAGEPORT_ERROR_IO_ERROR;
1218 return __register_message_port(local_port, true, callback);
1222 int messageport_check_remote_port(const char *remote_app_id, const char *remote_port, bool *exist)
1224 if (!_initialized) {
1225 if (!__initialize())
1226 return MESSAGEPORT_ERROR_IO_ERROR;
1229 int ret = __check_remote_port(remote_app_id, remote_port, false, exist);
1230 if (ret == MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND) {
1232 ret = MESSAGEPORT_ERROR_NONE;
1238 int messageport_check_trusted_remote_port(const char *remote_app_id, const char *remote_port, bool *exist)
1240 if (!_initialized) {
1241 if (!__initialize())
1242 return MESSAGEPORT_ERROR_IO_ERROR;
1245 int ret = __check_remote_port(remote_app_id, remote_port, true, exist);
1246 if (ret == MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND) {
1248 ret = MESSAGEPORT_ERROR_NONE;
1254 int messageport_send_message(const char *remote_app_id, const char *remote_port, bundle *message)
1256 if (!_initialized) {
1257 if (!__initialize())
1258 return MESSAGEPORT_ERROR_IO_ERROR;
1261 return __message_port_send_message(remote_app_id, remote_port, NULL, false, false, false, message);
1264 int messageport_send_trusted_message(const char *remote_app_id, const char *remote_port, bundle *message)
1266 if (!_initialized) {
1267 if (!__initialize())
1268 return MESSAGEPORT_ERROR_IO_ERROR;
1271 return __message_port_send_message(remote_app_id, remote_port, NULL, true, false, false, message);
1274 int messageport_send_bidirectional_message(int id, const char *remote_app_id, const char *remote_port,
1277 if (!_initialized) {
1278 if (!__initialize())
1279 return MESSAGEPORT_ERROR_IO_ERROR;
1282 return __message_send_bidirectional_message(id, remote_app_id, remote_port, false, message);
1285 int messageport_send_bidirectional_trusted_message(int id, const char *remote_app_id, const char *remote_port,
1288 if (!_initialized) {
1289 if (!__initialize())
1290 return MESSAGEPORT_ERROR_IO_ERROR;
1292 return __message_send_bidirectional_message(id, remote_app_id, remote_port, true, message);
1295 int messageport_get_local_port_name(int id, char **name)
1297 message_port_local_port_info_s *local_info;
1298 int ret = __get_local_port_info(id, &local_info);
1300 if (ret != MESSAGEPORT_ERROR_NONE) {
1304 *name = strdup(local_info->port_name);
1306 if (*name == NULL) {
1307 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1310 return MESSAGEPORT_ERROR_NONE;
1313 int messageport_check_trusted_local_port(int id, bool *trusted)
1315 message_port_local_port_info_s *local_info;
1316 int ret = __get_local_port_info(id, &local_info);
1318 if (ret != MESSAGEPORT_ERROR_NONE) {
1322 *trusted = local_info->is_trusted;
1324 return MESSAGEPORT_ERROR_NONE;;