#define __POST_THREAD_STOP 0
#define __QUEUE_TIME_OUT 500
-static const gchar introspection_xml[] =
- "<node>"
- " <interface name='org.tizen.ttd.bus.appinf'>"
- " <method name='RegisterApp'>"
- " <arg type='s' name='token' direction='in'/>"
- " <arg type='s' name='appID' direction='in'/>"
- " <arg type='u' name='appPID' direction='in'/>"
- " <arg type='i' name='response' direction='out'/>"
- " </method>"
- " <method name='UnregisterApp'>"
- " <arg type='s' name='token' direction='in'/>"
- " <arg type='s' name='appID' direction='in'/>"
- " <arg type='u' name='appPID' direction='in'/>"
- " <arg type='i' name='response' direction='out'/>"
- " </method>"
- " </interface>"
- "</node>";
+#define APP_INF_INTROSPECTION \
+"<node>" \
+" <interface name='"TTD_APP_INF_BUS_INF"'>" \
+" <method name='"TTD_APP_INF_METHOD_REG"'>" \
+" <arg type='s' name='token' direction='in'/>" \
+" <arg type='s' name='appID' direction='in'/>" \
+" <arg type='u' name='appPID' direction='in'/>" \
+" <arg type='i' name='response' direction='out'/>" \
+" </method>" \
+" <method name='"TTD_APP_INF_METHOD_UNREG"'>" \
+" <arg type='s' name='token' direction='in'/>" \
+" <arg type='s' name='appID' direction='in'/>" \
+" <arg type='u' name='appPID' direction='in'/>" \
+" <arg type='i' name='response' direction='out'/>" \
+" </method>" \
+" </interface>" \
+"</node>"
typedef struct __thread_data_s {
char *name;
_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);
_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,
#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
+}