From 10f3aacf88c1804ad3f4b3dfd69c555cfc16a3a2 Mon Sep 17 00:00:00 2001 From: Jeonghoon Park Date: Thu, 17 May 2018 16:18:11 +0900 Subject: [PATCH] implements functions for application library Change-Id: I844abac6b9c1b3c2fa7a42f7b4b7f87afef75d14 --- common/common-app-inf.h | 2 + daemon/src/ttd-app-interface.c | 41 ++-- lib/things-service/src/things-service.c | 329 +++++++++++++++++++++++++++++++- 3 files changed, 350 insertions(+), 22 deletions(-) diff --git a/common/common-app-inf.h b/common/common-app-inf.h index 1bf8251..bbe5768 100644 --- a/common/common-app-inf.h +++ b/common/common-app-inf.h @@ -21,6 +21,8 @@ #define TTD_APP_INF_BUS_NAME "org.tizen.ttd.bus" #define TTD_APP_INF_BUS_INF "org.tizen.ttd.bus.appinf" #define TTD_APP_INF_OBJECT_PATH "/org/tizen/ttd/bus/appinf/object" +#define TTD_APP_INF_METHOD_REG "RegisterApp" +#define TTD_APP_INF_METHOD_UNREG "UnregisterApp" char *common_make_socket_addr_name( const char *token, const char *appID, unsigned int appPID); diff --git a/daemon/src/ttd-app-interface.c b/daemon/src/ttd-app-interface.c index e32dba0..9ff1401 100644 --- a/daemon/src/ttd-app-interface.c +++ b/daemon/src/ttd-app-interface.c @@ -27,23 +27,23 @@ #define __POST_THREAD_STOP 0 #define __QUEUE_TIME_OUT 500 -static const gchar introspection_xml[] = - "" - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - ""; +#define APP_INF_INTROSPECTION \ +"" \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +"" typedef struct __thread_data_s { char *name; @@ -455,9 +455,9 @@ _ttd_handle_method_call(GDBusConnection *connection, _D("method[%s] called by [%s]", method_name, sender); - if (g_strcmp0(method_name, "RegisterApp") == 0) { + if (g_strcmp0(method_name, TTD_APP_INF_METHOD_REG) == 0) { __handle_method_register(parameters, invocation, handle); - } else if (g_strcmp0(method_name, "UnregisterApp") == 0) { + } else if (g_strcmp0(method_name, TTD_APP_INF_METHOD_UNREG) == 0) { __handle_method_unregister(parameters, invocation, handle); } else { _E("Unkwon Method - %s", method_name); @@ -582,7 +582,8 @@ int ttd_app_interface_init(ttd_app_inf_h *handle) _handle = g_try_malloc0(sizeof(struct _ttd_app_inf_h)); retv_if(!_handle, -1); - introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL); + introspection_data = + g_dbus_node_info_new_for_xml(APP_INF_INTROSPECTION, NULL); id = g_bus_own_name(G_BUS_TYPE_SYSTEM, TTD_APP_INF_BUS_NAME, diff --git a/lib/things-service/src/things-service.c b/lib/things-service/src/things-service.c index 9623804..aa50aec 100644 --- a/lib/things-service/src/things-service.c +++ b/lib/things-service/src/things-service.c @@ -24,22 +24,347 @@ #include "log-private.h" #include "things-service.h" #include "common-app-inf.h" +#include "common-util.h" struct _ts_data { - int padding; + char *app_id; + char *token; + GSocket *socket; + GSocketAddress *addr; + GSocket *cl_socket; + GDBusConnection *bus; + GDBusProxy *proxy; + GThread *accept_thread; + int accept_thread_running; }; +static void __quit_n_join_accept_thread(ts_handle handle); +static int _create_accept_thread(ts_handle handle); + +static char *_get_socket_addr_name(const char *appID, const char *token) +{ + return common_make_socket_addr_name(token, appID, (guint)getpid()); +} + +static char *_get_app_id(void) +{ + char *app_id = NULL; + app_get_id(&app_id); + + return app_id; +} + +static char *_get_token(const char *appID) +{ + char *checksum = NULL; + char *key = NULL; + + key = g_strdup_printf("%s-%u-%llu", + appID, getpid(), common_get_monotonic_coarse_time()); + checksum = g_compute_checksum_for_string (G_CHECKSUM_MD5, key, -1); + g_free(key); + + return checksum; +} + +static gboolean +__on_disconnect(GIOChannel *ch, GIOCondition cond, gpointer data) +{ + ts_handle handle = data; + gboolean connected = FALSE; + + connected = g_socket_is_connected(handle->cl_socket); + if (!connected) + _E("client socket is disconnected"); + + if (cond == G_IO_ERR) + _E("connection has error"); + + if (cond == G_IO_HUP) + _E("connection has been broken"); + + g_socket_shutdown(handle->cl_socket, FALSE, TRUE, NULL); + g_socket_close(handle->cl_socket, NULL); + g_object_unref(handle->cl_socket); + + handle->cl_socket = NULL; + + _create_accept_thread(handle); + + return FALSE; +} + +static void _ts_handle_free(ts_handle handle) +{ + ret_if(!handle); + + __quit_n_join_accept_thread(handle); + + if (handle->app_id) + g_free(handle->app_id); + + if (handle->token) + g_free(handle->token); + + if (handle->socket) { + g_socket_close(handle->socket, NULL); + g_object_unref(handle->socket); + } + + if (handle->addr) + g_object_unref(handle->addr); + + if (handle->bus) + g_object_unref(handle->bus); + + if (handle->proxy) + g_object_unref(handle->proxy); + + g_free(handle); +} + +static void __quit_n_join_accept_thread(ts_handle handle) +{ + if (handle->accept_thread) { + g_atomic_int_set(&(handle->accept_thread_running), 0); + g_thread_join(handle->accept_thread); + handle->accept_thread = NULL; + } +} + +static gpointer accept_thread(gpointer data) +{ + ts_handle handle = data; + retv_if(!handle, NULL); + + while (TRUE) { + GSocket *new_socket = NULL; + GIOChannel *new_ch = NULL; + int fd = 0; + GError *error = NULL; + + if (!g_atomic_int_get(&(handle->accept_thread_running))) + break; + + new_socket = g_socket_accept(handle->socket, NULL, &error); + if (!new_socket) { + if (error) { + if (error->code != G_IO_ERROR_WOULD_BLOCK) + _E("err on g_socket_accept() - %s", error->message); + + g_error_free(error); + } + continue; + } + + _D("accepted new socket[%p]", new_socket); + fd = g_socket_get_fd(new_socket); + new_ch = g_io_channel_unix_new(fd); + g_io_add_watch(new_ch, (GIOCondition) (G_IO_ERR | G_IO_HUP), + __on_disconnect, handle); + handle->cl_socket = new_socket; + break; /* accept and exit thread */ + } + _D("exiting accept thread"); + + return NULL; +} + +static int _create_accept_thread(ts_handle handle) +{ + GThread *new_thread = NULL; + GError *error = NULL; + + retv_if(!handle, -1); + + if (handle->accept_thread) + __quit_n_join_accept_thread(handle); + + g_atomic_int_set(&(handle->accept_thread_running), 1); + new_thread = g_thread_try_new(NULL, accept_thread, handle, &error); + if (!new_thread) { + _E("failed to create accept thread - %s", error->message); + g_error_free(error); + return -1; + } + + return 0; +} + +static int __client_method_call(const char *method, ts_handle handle) +{ + GVariant *response = NULL; + int ret = 0; + GError *error = NULL; + + _D("call method [%s]", method); + response = g_dbus_proxy_call_sync(handle->proxy, + method, + g_variant_new("(ssu)", handle->token, handle->app_id, (guint)getpid()), + G_DBUS_CALL_FLAGS_NONE, + -1, /* The timeout in milliseconds or -1 to use the proxy default timeout. */ + NULL, /* cancellable */ + &error); + if (error) { + _E("failed to g_dbus_proxy_call_sync() - %s", error->message); + g_error_free(error); + return -1; + } + g_variant_get(response, "(i)", ret); + _D("method[%s] get response ret[%d]", method, ret); + g_variant_unref(response); + + return 0; +} + +static int _client_call_register(ts_handle handle) +{ + return __client_method_call(TTD_APP_INF_METHOD_REG, handle); +} + +static int _client_call_unregister(ts_handle handle) +{ + return __client_method_call(TTD_APP_INF_METHOD_UNREG, handle); +} + int things_service_init(ts_handle *handle) { + ts_handle _handle = NULL; + GError *error = NULL; + char *socket_name = NULL; + + retv_if(!handle, -1); + + _handle = g_try_malloc0(sizeof(ts_handle)); + _handle->app_id = _get_app_id(); + if (!_handle->app_id) { + _E("failed to get app id"); + _ts_handle_free(_handle); + return -1; + } + _D("libthings_service with - %s", _handle->app_id); + + _handle->token = _get_token(_handle->app_id); + if (!_handle->token) { + _E("failed to get token"); + _ts_handle_free(_handle); + return -1; + } + _D("get token - %s", _handle->token); + _handle->cl_socket = NULL; + _handle->socket = g_socket_new(G_SOCKET_FAMILY_UNIX, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + &error); + if (!_handle->socket) { + _E("failed to create socket - %s", error->message); + g_error_free(error); + _ts_handle_free(_handle); + return -1; + } + g_socket_set_blocking(_handle->socket, FALSE); + + socket_name = _get_socket_addr_name(_handle->app_id, _handle->token); + if (!socket_name) { + _E("failed to get socket_name"); + _ts_handle_free(_handle); + return -1; + } + _handle->addr = g_unix_socket_address_new_with_type( + socket_name, -1, G_UNIX_SOCKET_ADDRESS_ABSTRACT); + _D("got socket addr - [%s]", socket_name); + g_free(socket_name); + + g_socket_bind(_handle->socket, _handle->addr, TRUE, &error); + if (error) { + _E("failed to g_socket_bind() - %s", error->message); + g_error_free(error); + _ts_handle_free(_handle); + return -1; + } + + g_socket_listen(_handle->socket, &error); + if (error) { + _E("failed to g_socket_listen() - %s", error->message); + g_error_free(error); + _ts_handle_free(_handle); + return -1; + } + + _handle->bus = + g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (!_handle->bus) { + _E("failed to g_bus_get_sync() - %s", error->message); + g_error_free(error); + _ts_handle_free(_handle); + return -1; + } + + _handle->proxy = g_dbus_proxy_new_sync(_handle->bus, + G_DBUS_PROXY_FLAGS_NONE, + NULL, /* GDBusInterfaceInfo */ + TTD_APP_INF_BUS_NAME, + TTD_APP_INF_OBJECT_PATH, + TTD_APP_INF_BUS_INF, + NULL, /* cancellable */ + &error); + if (!_handle->proxy) { + _E("failed to g_dbus_proxy_new_sync() - %s", + error ? error->message : "error not set"); + _ts_handle_free(_handle); + return -1; + } + + if (_create_accept_thread(_handle)) { + _E("failed to _create_accept_thread()"); + _ts_handle_free(_handle); + return -1; + } + + if (_client_call_register(_handle)) { + _E("failed to call register"); + _ts_handle_free(_handle); + return -1; + } + + *handle = _handle; + return 0; } int things_service_fini(ts_handle handle) { + retv_if(!handle, -1); + + _client_call_unregister(handle); + _ts_handle_free(handle); + return 0; } int things_service_send_data(ts_handle handle, const char *json_data) { + gboolean connected = FALSE; + char *msg = NULL; + GError *error = NULL; + + retv_if(!handle, -1); + retv_if(!handle->socket, -1); + retv_if(!handle->cl_socket, -1); + retv_if(!json_data, -1); + + connected = g_socket_is_connected(handle->cl_socket); + retv_if(!connected, -1); + + msg = g_strdup_printf("%s %s", json_data, TTD_APP_MSG_DELIMITER); + g_socket_send(handle->cl_socket, msg, strlen(msg), NULL, &error); + if (error) { + _E("failed to g_socket_send() - %s", error->message); + g_error_free(error); + return -1; + } + _D("msg is sent - %s", msg); + g_free(msg); + return 0; -} \ No newline at end of file +} -- 2.7.4