X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgkdbus.c;h=7127130be7b9b87ec3cd0b2f102331e5dbad0a95;hb=4f5aafb71f3b8661311d0db4633142cf13294e77;hp=b8fcf7cdb2ed52ef01e752e58774f95bd9d4a498;hpb=5bb064e8bb8cf7f6df5fe0bde67b776b3d6d01a7;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gkdbus.c b/gio/gkdbus.c index b8fcf7c..7127130 100644 --- a/gio/gkdbus.c +++ b/gio/gkdbus.c @@ -51,10 +51,11 @@ #include "glibintl.h" #include "gunixfdmessage.h" -#define KDBUS_TIMEOUT_NS 2000000000LU -#define KDBUS_POOL_SIZE (16 * 1024LU * 1024LU) -#define KDBUS_ALIGN8(l) (((l) + 7) & ~7) -#define KDBUS_ALIGN8_PTR(p) ((void*) (uintptr_t)(p)) +#define KDBUS_MSG_MAX_SIZE 8192 +#define KDBUS_TIMEOUT_NS 2000000000LU +#define KDBUS_POOL_SIZE (16 * 1024LU * 1024LU) +#define KDBUS_ALIGN8(l) (((l) + 7) & ~7) +#define KDBUS_ALIGN8_PTR(p) ((void*) (uintptr_t)(p)) #define KDBUS_ITEM_HEADER_SIZE G_STRUCT_OFFSET(struct kdbus_item, data) #define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE) @@ -65,6 +66,11 @@ for (item = (head)->first; \ (guint8 *)(item) < (guint8 *)(head) + (head)->size; \ item = KDBUS_ITEM_NEXT(item)) +#define KDBUS_FOREACH(iter, first, _size) \ + for (iter = (first); \ + ((guint8 *)(iter) < (guint8 *)(first) + (_size)) && \ + ((guint8 *)(iter) >= (guint8 *)(first)); \ + iter = (void*)(((guint8 *)iter) + KDBUS_ALIGN8((iter)->size))) #define g_alloca0(x) memset(g_alloca(x), '\0', (x)) @@ -81,7 +87,37 @@ struct dbus_fixed_header { #define DBUS_EXTENDED_HEADER_TYPE ((const GVariantType *) "a{tv}") #define DBUS_MESSAGE_TYPE ((const GVariantType *) "((yyyyut)a{tv}v)") -#define KDBUS_MSG_MAX_SIZE 8192 +/* + * Macros for SipHash algorithm + */ + +#define ROTL(x,b) (guint64)( ((x) << (b)) | ( (x) >> (64 - (b))) ) + +#define U32TO8_LE(p, v) \ + (p)[0] = (guint8)((v) ); (p)[1] = (guint8)((v) >> 8); \ + (p)[2] = (guint8)((v) >> 16); (p)[3] = (guint8)((v) >> 24); + +#define U64TO8_LE(p, v) \ + U32TO8_LE((p), (guint32)((v) )); \ + U32TO8_LE((p) + 4, (guint32)((v) >> 32)); + +#define U8TO64_LE(p) \ + (((guint64)((p)[0]) ) | \ + ((guint64)((p)[1]) << 8) | \ + ((guint64)((p)[2]) << 16) | \ + ((guint64)((p)[3]) << 24) | \ + ((guint64)((p)[4]) << 32) | \ + ((guint64)((p)[5]) << 40) | \ + ((guint64)((p)[6]) << 48) | \ + ((guint64)((p)[7]) << 56)) + +#define SIPROUND \ + do { \ + v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \ + v2 += v3; v3=ROTL(v3,16); v3 ^= v2; \ + v0 += v3; v3=ROTL(v3,21); v3 ^= v0; \ + v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \ + } while(0) typedef enum { @@ -120,6 +156,12 @@ struct _GKDBusWorker guint timed_out : 1; guchar bus_id[16]; + + GDBusCapabilityFlags capabilities; + GDBusWorkerMessageReceivedCallback message_received_callback; + GDBusWorkerMessageAboutToBeSentCallback message_about_to_be_sent_callback; + GDBusWorkerDisconnectedCallback disconnected_callback; + gpointer user_data; }; static gssize _g_kdbus_receive (GKDBusWorker *kdbus, @@ -141,6 +183,341 @@ const guint8 hash_keys[8][16] = {0xf2,0x77,0xe9,0x6f,0x93,0xb5,0x4e,0x71,0x9a,0x0c,0x34,0x88,0x39,0x25,0xbf,0x35} }; +enum { + MATCH_ELEMENT_TYPE, + MATCH_ELEMENT_SENDER, + MATCH_ELEMENT_INTERFACE, + MATCH_ELEMENT_MEMBER, + MATCH_ELEMENT_PATH, + MATCH_ELEMENT_PATH_NAMESPACE, + MATCH_ELEMENT_DESTINATION, + MATCH_ELEMENT_ARG0NAMESPACE, + MATCH_ELEMENT_EAVESDROP, + MATCH_ELEMENT_ARGN, + MATCH_ELEMENT_ARGNPATH, +}; + +/* MatchElement struct */ +typedef struct { + guint16 type; + guint16 arg; + char *value; +} MatchElement; + +/* Match struct */ +typedef struct { + int n_elements; + MatchElement *elements; +} Match; + + +/** + * SipHash algorithm + * + */ +static void +_g_siphash24 (guint8 out[8], + const void *_in, + gsize inlen, + const guint8 k[16]) +{ + /* "somepseudorandomlygeneratedbytes" */ + guint64 v0 = 0x736f6d6570736575ULL; + guint64 v1 = 0x646f72616e646f6dULL; + guint64 v2 = 0x6c7967656e657261ULL; + guint64 v3 = 0x7465646279746573ULL; + guint64 b; + guint64 k0 = U8TO64_LE (k); + guint64 k1 = U8TO64_LE (k + 8); + guint64 m; + const guint8 *in = _in; + const guint8 *end = in + inlen - (inlen % sizeof(guint64)); + const int left = inlen & 7; + b = ((guint64) inlen) << 56; + v3 ^= k1; + v2 ^= k0; + v1 ^= k1; + v0 ^= k0; + + for (; in != end; in += 8) + { + m = U8TO64_LE (in); + v3 ^= m; + SIPROUND; + SIPROUND; + v0 ^= m; + } + + switch (left) + { + case 7: b |= ((guint64) in[6]) << 48; + case 6: b |= ((guint64) in[5]) << 40; + case 5: b |= ((guint64) in[4]) << 32; + case 4: b |= ((guint64) in[3]) << 24; + case 3: b |= ((guint64) in[2]) << 16; + case 2: b |= ((guint64) in[1]) << 8; + case 1: b |= ((guint64) in[0]); break; + case 0: break; + } + + v3 ^= b; + SIPROUND; + SIPROUND; + v0 ^= b; + + v2 ^= 0xff; + SIPROUND; + SIPROUND; + SIPROUND; + SIPROUND; + b = v0 ^ v1 ^ v2 ^ v3; + U64TO8_LE (out, b); +} + + +/** + * is_key() + * + */ +static gboolean +is_key (const char *key_start, const char *key_end, char *value) +{ + gsize len = strlen (value); + + if (len != key_end - key_start) + return FALSE; + + return strncmp (key_start, value, len) == 0; +} + + +/** + * parse_key() + * + */ +static gboolean +parse_key (MatchElement *element, const char *key_start, const char *key_end) +{ + gboolean res = TRUE; + + if (is_key (key_start, key_end, "type")) + { + element->type = MATCH_ELEMENT_TYPE; + } + else if (is_key (key_start, key_end, "sender")) + { + element->type = MATCH_ELEMENT_SENDER; + } + else if (is_key (key_start, key_end, "interface")) + { + element->type = MATCH_ELEMENT_INTERFACE; + } + else if (is_key (key_start, key_end, "member")) + { + element->type = MATCH_ELEMENT_MEMBER; + } + else if (is_key (key_start, key_end, "path")) + { + element->type = MATCH_ELEMENT_PATH; + } + else if (is_key (key_start, key_end, "path_namespace")) + { + element->type = MATCH_ELEMENT_PATH_NAMESPACE; + } + else if (is_key (key_start, key_end, "destination")) + { + element->type = MATCH_ELEMENT_DESTINATION; + } + else if (is_key (key_start, key_end, "arg0namespace")) + { + element->type = MATCH_ELEMENT_ARG0NAMESPACE; + } + else if (is_key (key_start, key_end, "eavesdrop")) + { + element->type = MATCH_ELEMENT_EAVESDROP; + } + else if (key_end - key_start > 3 && is_key (key_start, key_start + 3, "arg")) + { + const char *digits = key_start + 3; + const char *end_digits = digits; + + while (end_digits < key_end && g_ascii_isdigit (*end_digits)) + end_digits++; + + if (end_digits == key_end) /* argN */ + { + element->type = MATCH_ELEMENT_ARGN; + element->arg = atoi (digits); + } + else if (is_key (end_digits, key_end, "path")) /* argNpath */ + { + element->type = MATCH_ELEMENT_ARGNPATH; + element->arg = atoi (digits); + } + else + res = FALSE; + } + else + res = FALSE; + + return res; +} + + +/** + * parse_value() + * + */ +static const char * +parse_value (MatchElement *element, const char *s) +{ + char quote_char; + GString *value; + + value = g_string_new (""); + + quote_char = 0; + + for (;*s; s++) + { + if (quote_char == 0) + { + switch (*s) + { + case '\'': + quote_char = '\''; + break; + + case ',': + s++; + goto out; + + case '\\': + quote_char = '\\'; + break; + + default: + g_string_append_c (value, *s); + break; + } + } + else if (quote_char == '\\') + { + /* \ only counts as an escape if escaping a quote mark */ + if (*s != '\'') + g_string_append_c (value, '\\'); + + g_string_append_c (value, *s); + quote_char = 0; + } + else /* quote_char == ' */ + { + if (*s == '\'') + quote_char = 0; + else + g_string_append_c (value, *s); + } + } + + out: + if (quote_char == '\\') + g_string_append_c (value, '\\'); + else if (quote_char == '\'') + { + g_string_free (value, TRUE); + return NULL; + } + + element->value = g_string_free (value, FALSE); + return s; +} + + +/** + * match_new() + * + */ +static Match * +match_new (const char *str) +{ + Match *match; + GArray *elements; + const char *p; + const char *key_start; + const char *key_end; + MatchElement element; + int i; + + elements = g_array_new (TRUE, TRUE, sizeof (MatchElement)); + + p = str; + + while (*p != 0) + { + memset (&element, 0, sizeof (element)); + + /* Skip initial whitespace */ + while (*p && g_ascii_isspace (*p)) + p++; + + key_start = p; + + /* Read non-whitespace non-equals chars */ + while (*p && *p != '=' && !g_ascii_isspace (*p)) + p++; + + key_end = p; + + /* Skip any whitespace after key */ + while (*p && g_ascii_isspace (*p)) + p++; + + if (key_start == key_end) + continue; /* Allow trailing whitespace */ + if (*p != '=') + goto error; + + ++p; + + if (!parse_key (&element, key_start, key_end)) + goto error; + + p = parse_value (&element, p); + if (p == NULL) + goto error; + + g_array_append_val (elements, element); + } + + match = g_new0 (Match, 1); + match->n_elements = elements->len; + match->elements = (MatchElement *)g_array_free (elements, FALSE); + + return match; + + error: + for (i = 0; i < elements->len; i++) + g_free (g_array_index (elements, MatchElement, i).value); + g_array_free (elements, TRUE); + return NULL; +} + + +/** + * match_free() + * + */ +static void +match_free (Match *match) +{ + int i; + for (i = 0; i < match->n_elements; i++) + g_free (match->elements[i].value); + g_free (match->elements); + g_free (match); +} + + /** * g_kdbus_finalize: * @@ -177,7 +554,8 @@ g_kdbus_worker_init (GKDBusWorker *kdbus) kdbus->kdbus_buffer = NULL; - kdbus->flags = 0; /* KDBUS_HELLO_ACCEPT_FD */ + //kdbus->flags = 0; /* KDBUS_HELLO_ACCEPT_FD */ + kdbus->flags = KDBUS_HELLO_ACCEPT_FD; kdbus->attach_flags_send = _KDBUS_ATTACH_ALL; kdbus->attach_flags_recv = _KDBUS_ATTACH_ALL; } @@ -197,9 +575,9 @@ kdbus_ready (gint fd, } gboolean -_g_kdbus_open (GKDBusWorker *worker, - const gchar *address, - GError **error) +_g_kdbus_open (GKDBusWorker *worker, + const gchar *address, + GError **error) { g_return_val_if_fail (G_IS_KDBUS_WORKER (worker), FALSE); @@ -212,11 +590,6 @@ _g_kdbus_open (GKDBusWorker *worker, worker->closed = FALSE; - worker->context = g_main_context_ref_thread_default (); - worker->source = g_unix_fd_source_new (worker->fd, G_IO_IN); - g_source_set_callback (worker->source, (GSourceFunc) kdbus_ready, worker, NULL); - g_source_attach (worker->source, worker->context); - return TRUE; } @@ -229,15 +602,16 @@ static gboolean g_kdbus_free_data (GKDBusWorker *kdbus, guint64 offset) { - struct kdbus_cmd_free cmd; + struct kdbus_cmd_free cmd = { + .size = sizeof(cmd), + .offset = offset, + .flags = 0 + }; int ret; - cmd.offset = offset; - cmd.flags = 0; - ret = ioctl (kdbus->fd, KDBUS_CMD_FREE, &cmd); if (ret < 0) - return FALSE; + return FALSE; return TRUE; } @@ -313,8 +687,9 @@ GVariant * _g_kdbus_Hello (GKDBusWorker *worker, GError **error) { - struct kdbus_cmd_hello *hello; - struct kdbus_item *item; + struct kdbus_cmd_hello *cmd; + struct kdbus_bloom_parameter *bloom; + struct kdbus_item *item, *items; gchar *conn_name; size_t size, conn_name_size; @@ -325,20 +700,20 @@ _g_kdbus_Hello (GKDBusWorker *worker, size = KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_cmd_hello, items)) + KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, str) + conn_name_size + 1); - hello = g_alloca0 (size); - hello->flags = worker->flags; - hello->attach_flags_send = worker->attach_flags_send; - hello->attach_flags_recv = worker->attach_flags_recv; - hello->size = size; - hello->pool_size = KDBUS_POOL_SIZE; + cmd = g_alloca0 (size); + cmd->flags = worker->flags; + cmd->attach_flags_send = worker->attach_flags_send; + cmd->attach_flags_recv = worker->attach_flags_recv; + cmd->size = size; + cmd->pool_size = KDBUS_POOL_SIZE; - item = hello->items; + item = cmd->items; item->size = G_STRUCT_OFFSET (struct kdbus_item, str) + conn_name_size + 1; item->type = KDBUS_ITEM_CONN_DESCRIPTION; memcpy (item->str, conn_name, conn_name_size+1); item = KDBUS_ITEM_NEXT (item); - if (ioctl(worker->fd, KDBUS_CMD_HELLO, hello)) + if (ioctl(worker->fd, KDBUS_CMD_HELLO, cmd)) { g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), @@ -357,7 +732,7 @@ _g_kdbus_Hello (GKDBusWorker *worker, return NULL; } - if (hello->bus_flags > 0xFFFFFFFFULL) + if (cmd->bus_flags > 0xFFFFFFFFULL) { g_set_error_literal (error, G_IO_ERROR, @@ -366,14 +741,29 @@ _g_kdbus_Hello (GKDBusWorker *worker, return NULL; } - memcpy (worker->bus_id, hello->id128, 16); + memcpy (worker->bus_id, cmd->id128, 16); - worker->unique_id = hello->id; - asprintf(&worker->unique_name, ":1.%llu", (unsigned long long) hello->id); + worker->unique_id = cmd->id; + asprintf(&worker->unique_name, ":1.%llu", (unsigned long long) cmd->id); /* read bloom filters parameters */ - worker->bloom_size = (gsize) hello->bloom.size; - worker->bloom_n_hash = (guint) hello->bloom.n_hash; + bloom = NULL; + items = (void*)(worker->kdbus_buffer + cmd->offset); + KDBUS_FOREACH(item, items, cmd->items_size) + { + switch (item->type) + { + case KDBUS_ITEM_BLOOM_PARAMETER: + bloom = &item->bloom_parameter; + break; + } + } + + if (bloom != NULL) + { + worker->bloom_size = (gsize) bloom->size; + worker->bloom_n_hash = (guint) bloom->n_hash; + } return g_variant_new ("(s)", worker->unique_name); } @@ -390,7 +780,7 @@ _g_kdbus_RequestName (GKDBusWorker *worker, GError **error) { GVariant *result; - struct kdbus_cmd_name *kdbus_name; + struct kdbus_cmd *cmd; guint64 kdbus_flags; gssize len, size; gint status, ret; @@ -418,15 +808,15 @@ _g_kdbus_RequestName (GKDBusWorker *worker, g_kdbus_translate_nameowner_flags (flags, &kdbus_flags); len = strlen(name) + 1; - size = G_STRUCT_OFFSET (struct kdbus_cmd_name, items) + KDBUS_ITEM_SIZE(len); - kdbus_name = g_alloca0 (size); - kdbus_name->size = size; - kdbus_name->items[0].size = KDBUS_ITEM_HEADER_SIZE + len; - kdbus_name->items[0].type = KDBUS_ITEM_NAME; - kdbus_name->flags = kdbus_flags; - memcpy (kdbus_name->items[0].str, name, len); - - ret = ioctl(worker->fd, KDBUS_CMD_NAME_ACQUIRE, kdbus_name); + size = G_STRUCT_OFFSET (struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(len); + cmd = g_alloca0 (size); + cmd->size = size; + cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len; + cmd->items[0].type = KDBUS_ITEM_NAME; + cmd->flags = kdbus_flags; + memcpy (cmd->items[0].str, name, len); + + ret = ioctl(worker->fd, KDBUS_CMD_NAME_ACQUIRE, cmd); if (ret < 0) { if (errno == EEXIST) @@ -443,7 +833,7 @@ _g_kdbus_RequestName (GKDBusWorker *worker, } } - if (kdbus_name->flags & KDBUS_NAME_IN_QUEUE) + if (cmd->return_flags & KDBUS_NAME_IN_QUEUE) status = G_BUS_REQUEST_NAME_FLAGS_IN_QUEUE; result = g_variant_new ("(u)", status); @@ -462,7 +852,7 @@ _g_kdbus_ReleaseName (GKDBusWorker *worker, GError **error) { GVariant *result; - struct kdbus_cmd_name *kdbus_name; + struct kdbus_cmd *cmd; gssize len, size; gint status, ret; @@ -487,14 +877,14 @@ _g_kdbus_ReleaseName (GKDBusWorker *worker, } len = strlen(name) + 1; - size = G_STRUCT_OFFSET (struct kdbus_cmd_name, items) + KDBUS_ITEM_SIZE(len); - kdbus_name = g_alloca0 (size); - kdbus_name->size = size; - kdbus_name->items[0].size = KDBUS_ITEM_HEADER_SIZE + len; - kdbus_name->items[0].type = KDBUS_ITEM_NAME; - memcpy (kdbus_name->items[0].str, name, len); - - ret = ioctl(worker->fd, KDBUS_CMD_NAME_RELEASE, kdbus_name); + size = G_STRUCT_OFFSET (struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(len); + cmd = g_alloca0 (size); + cmd->size = size; + cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len; + cmd->items[0].type = KDBUS_ITEM_NAME; + memcpy (cmd->items[0].str, name, len); + + ret = ioctl(worker->fd, KDBUS_CMD_NAME_RELEASE, cmd); if (ret < 0) { if (errno == ESRCH) @@ -552,10 +942,10 @@ _g_kdbus_GetListNames (GKDBusWorker *worker, { GVariant *result; GVariantBuilder *builder; - - struct kdbus_cmd_name_list cmd = {}; - struct kdbus_name_list *name_list; - struct kdbus_name_info *name; + struct kdbus_info *name_list, *name; + struct kdbus_cmd_list cmd = { + .size = sizeof(cmd) + }; guint64 prev_id; gint ret; @@ -563,11 +953,11 @@ _g_kdbus_GetListNames (GKDBusWorker *worker, prev_id = 0; if (list_name_type) - cmd.flags = KDBUS_NAME_LIST_ACTIVATORS; /* ListActivatableNames */ + cmd.flags = KDBUS_LIST_ACTIVATORS; /* ListActivatableNames */ else - cmd.flags = KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES; /* ListNames */ + cmd.flags = KDBUS_LIST_UNIQUE | KDBUS_LIST_NAMES; /* ListNames */ - ret = ioctl(worker->fd, KDBUS_CMD_NAME_LIST, &cmd); + ret = ioctl(worker->fd, KDBUS_CMD_LIST, &cmd); if (ret < 0) { g_set_error (error, @@ -577,23 +967,23 @@ _g_kdbus_GetListNames (GKDBusWorker *worker, return NULL; } - name_list = (struct kdbus_name_list *) ((guint8 *) worker->kdbus_buffer + cmd.offset); + name_list = (struct kdbus_info *) ((guint8 *) worker->kdbus_buffer + cmd.offset); builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); - KDBUS_ITEM_FOREACH(name, name_list, names) + KDBUS_FOREACH(name, name_list, cmd.list_size) { struct kdbus_item *item; const gchar *item_name = ""; - if ((cmd.flags & KDBUS_NAME_LIST_UNIQUE) && name->owner_id != prev_id) + if ((cmd.flags & KDBUS_LIST_UNIQUE) && name->id != prev_id) { GString *unique_name; unique_name = g_string_new (NULL); - g_string_printf (unique_name, ":1.%llu", name->owner_id); + g_string_printf (unique_name, ":1.%llu", name->id); g_variant_builder_add (builder, "s", unique_name->str); g_string_free (unique_name,TRUE); - prev_id = name->owner_id; + prev_id = name->id; } KDBUS_ITEM_FOREACH(item, name, items) @@ -658,17 +1048,19 @@ g_kdbus_NameHasOwner_internal (GKDBusWorker *worker, */ GVariant * _g_kdbus_GetListQueuedOwners (GKDBusWorker *worker, - const gchar *name, - GError **error) + const gchar *name, + GError **error) { GVariant *result; GVariantBuilder *builder; GString *unique_name; gint ret; - struct kdbus_cmd_name_list cmd = {}; - struct kdbus_name_list *name_list; - struct kdbus_name_info *kname; + struct kdbus_info *name_list, *kname; + struct kdbus_cmd_list cmd = { + .size = sizeof(cmd), + .flags = KDBUS_LIST_QUEUED + }; if (!g_dbus_is_name (name)) { @@ -688,8 +1080,7 @@ _g_kdbus_GetListQueuedOwners (GKDBusWorker *worker, return NULL; } - cmd.flags = KDBUS_NAME_LIST_QUEUED; - ret = ioctl(worker->fd, KDBUS_CMD_NAME_LIST, &cmd); + ret = ioctl(worker->fd, KDBUS_CMD_LIST, &cmd); if (ret < 0) { g_set_error (error, @@ -699,11 +1090,11 @@ _g_kdbus_GetListQueuedOwners (GKDBusWorker *worker, return NULL; } - name_list = (struct kdbus_name_list *) ((guint8 *) worker->kdbus_buffer + cmd.offset); + name_list = (struct kdbus_info *) ((guint8 *) worker->kdbus_buffer + cmd.offset); unique_name = g_string_new (NULL); builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); - KDBUS_ITEM_FOREACH(kname, name_list, names) + KDBUS_FOREACH(kname, name_list, cmd.list_size) { struct kdbus_item *item; const char *item_name = ""; @@ -715,7 +1106,7 @@ _g_kdbus_GetListQueuedOwners (GKDBusWorker *worker, if (strcmp(item_name, name)) continue; - g_string_printf (unique_name, ":1.%llu", kname->owner_id); + g_string_printf (unique_name, ":1.%llu", kname->id); g_variant_builder_add (builder, "s", item_name); } @@ -782,7 +1173,7 @@ g_kdbus_GetConnInfo_internal (GKDBusWorker *worker, memcpy (cmd->items[0].str, name, len); } - cmd->flags = _KDBUS_ATTACH_ALL; + cmd->attach_flags = _KDBUS_ATTACH_ALL; cmd->size = size; ret = ioctl(worker->fd, KDBUS_CMD_CONN_INFO, cmd); @@ -872,125 +1263,372 @@ _g_kdbus_GetNameOwner (GKDBusWorker *worker, } -/** - * _g_kdbus_GetConnectionUnixProcessID: - * - */ -GVariant * -_g_kdbus_GetConnectionUnixProcessID (GKDBusWorker *worker, - const gchar *name, - GError **error) -{ - return g_kdbus_GetConnInfo_internal (worker, - name, - G_BUS_CREDS_PID, - error); -} +/** + * _g_kdbus_GetConnectionUnixProcessID: + * + */ +GVariant * +_g_kdbus_GetConnectionUnixProcessID (GKDBusWorker *worker, + const gchar *name, + GError **error) +{ + return g_kdbus_GetConnInfo_internal (worker, + name, + G_BUS_CREDS_PID, + error); +} + + +/** + * _g_kdbus_GetConnectionUnixUser: + * + */ +GVariant * +_g_kdbus_GetConnectionUnixUser (GKDBusWorker *worker, + const gchar *name, + GError **error) +{ + return g_kdbus_GetConnInfo_internal (worker, + name, + G_BUS_CREDS_UID, + error); +} + + +/** + * g_kdbus_bloom_add_data: + * Based on bus-bloom.c from systemd + * http://cgit.freedesktop.org/systemd/systemd/tree/src/libsystemd/sd-bus/bus-bloom.c + */ +static void +g_kdbus_bloom_add_data (GKDBusWorker *worker, + guint64 bloom_data [], + const void *data, + gsize n) +{ + guint8 hash[8]; + guint64 bit_num; + guint bytes_num = 0; + guint cnt_1, cnt_2; + guint hash_index = 0; + + guint c = 0; + guint64 p = 0; + + bit_num = worker->bloom_size * 8; + + if (bit_num > 1) + bytes_num = ((__builtin_clzll(bit_num) ^ 63U) + 7) / 8; + + for (cnt_1 = 0; cnt_1 < (worker->bloom_n_hash); cnt_1++) + { + for (cnt_2 = 0, hash_index = 0; cnt_2 < bytes_num; cnt_2++) + { + if (c <= 0) + { + _g_siphash24(hash, data, n, hash_keys[hash_index++]); + c += 8; + } + + p = (p << 8ULL) | (guint64) hash[8 - c]; + c--; + } + + p &= bit_num - 1; + bloom_data[p >> 6] |= 1ULL << (p & 63); + } +} + + +/** + * g_kdbus_bloom_add_pair: + * + */ +static void +g_kdbus_bloom_add_pair (GKDBusWorker *worker, + guint64 bloom_data [], + const gchar *parameter, + const gchar *value) +{ + gchar buf[1024]; + gsize size; + + size = strlen(parameter) + strlen(value) + 1; + if (size > 1024) + return; + + strcpy(stpcpy(stpcpy(buf, parameter), ":"), value); + g_kdbus_bloom_add_data(worker, bloom_data, buf, size); +} + + +/** + * g_kdbus_bloom_add_prefixes: + * + */ +static void +g_kdbus_bloom_add_prefixes (GKDBusWorker *worker, + guint64 bloom_data [], + const gchar *parameter, + const gchar *value, + gchar separator) +{ + gchar buf[1024]; + gsize size; + + size = strlen(parameter) + strlen(value) + 1; + if (size > 1024) + return; + + strcpy(stpcpy(stpcpy(buf, parameter), ":"), value); + + for (;;) + { + gchar *last_sep; + last_sep = strrchr(buf, separator); + if (!last_sep || last_sep == buf) + break; + + *last_sep = 0; + g_kdbus_bloom_add_data(worker, bloom_data, buf, last_sep-buf); + } +} + + +/** + * _g_kdbus_AddMatch: + * + */ +void +_g_kdbus_AddMatch (GKDBusWorker *worker, + const gchar *match_rule, + guint64 cookie) +{ + Match *match; + MatchElement *element; + const gchar *sender_name; + gsize sender_len, size; + struct kdbus_cmd_match *cmd; + struct kdbus_item *item; + guint64 *bloom; + guint64 src_id; + gchar *type; + gint cnt, ret; + + if (match_rule[0] == '-') + return; + + match = match_new (match_rule); + if (!match) + { + match_free (match); + return; + } + + sender_name = NULL; + src_id = KDBUS_MATCH_ID_ANY; + + bloom = g_alloca0 (worker->bloom_size); + size = KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_cmd_match, items)); + match = match_new (match_rule); + + for (cnt = 0; cnt < match->n_elements; cnt++) + { + element = &match->elements[cnt]; + switch (element->type) + { + case MATCH_ELEMENT_SENDER: + if (g_dbus_is_unique_name(element->value)) + { + src_id = g_ascii_strtoull ((element->value)+3, NULL, 10); + size += KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, id) + sizeof(src_id)); + } + else if (g_dbus_is_name (element->value)) + { + sender_name = element->value; + sender_len = strlen(element->value) + 1; + size += KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, str) + sender_len); + } + else + { + g_critical ("Error while adding a match"); + match_free (match); + return; + } + break; + + case MATCH_ELEMENT_TYPE: + g_kdbus_bloom_add_pair (worker, bloom, "message-type", element->value); + break; + + case MATCH_ELEMENT_INTERFACE: + g_kdbus_bloom_add_pair (worker, bloom, "interface", element->value); + break; + + case MATCH_ELEMENT_MEMBER: + g_kdbus_bloom_add_pair (worker, bloom, "member", element->value); + break; + + case MATCH_ELEMENT_PATH: + g_kdbus_bloom_add_pair (worker, bloom, "path", element->value); + break; + + case MATCH_ELEMENT_PATH_NAMESPACE: + if (g_strcmp0 (element->value, "/")) + g_kdbus_bloom_add_pair (worker, bloom, "path-slash-prefix", element->value); + break; + + case MATCH_ELEMENT_ARGN: + asprintf (&type, "arg%u", element->arg); + g_kdbus_bloom_add_pair (worker, bloom, type, element->value); + free (type); + break; + + case MATCH_ELEMENT_ARGNPATH: + asprintf (&type, "arg%u-slash-prefix", element->arg); + g_kdbus_bloom_add_pair (worker, bloom, type, element->value); + free (type); + break; + + case MATCH_ELEMENT_ARG0NAMESPACE: + g_kdbus_bloom_add_pair (worker, bloom, "arg0-dot-prefix", element->value); + break; + + case MATCH_ELEMENT_DESTINATION: + case MATCH_ELEMENT_EAVESDROP: + break; + } + } + + size += KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, data64) + worker->bloom_size); + cmd = g_alloca0 (size); + cmd->size = size; + cmd->cookie = cookie; + + item = cmd->items; + item->size = G_STRUCT_OFFSET(struct kdbus_item, data64) + worker->bloom_size; + item->type = KDBUS_ITEM_BLOOM_MASK; + memcpy(item->data64, bloom, worker->bloom_size); + item = KDBUS_ITEM_NEXT(item); + + if (src_id != KDBUS_MATCH_ID_ANY) + { + item->size = G_STRUCT_OFFSET (struct kdbus_item, id) + sizeof(src_id); + item->type = KDBUS_ITEM_ID; + item->id = src_id; + item = KDBUS_ITEM_NEXT(item); + } + if (sender_name) + { + item->size = G_STRUCT_OFFSET (struct kdbus_item, str) + sender_len; + item->type = KDBUS_ITEM_NAME; + memcpy (item->str, sender_name, sender_len); + } -/** - * _g_kdbus_GetConnectionUnixUser: - * - */ -GVariant * -_g_kdbus_GetConnectionUnixUser (GKDBusWorker *worker, - const gchar *name, - GError **error) -{ - return g_kdbus_GetConnInfo_internal (worker, - name, - G_BUS_CREDS_UID, - error); + ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd); + if (ret < 0) + g_critical ("Error while adding a match: %d", (int) errno); + + match_free (match); } /** - * _g_kdbus_match_remove: + * _g_kdbus_RemoveMatch: * */ -static void -_g_kdbus_match_remove (GKDBusWorker *worker, - guint cookie) +void +_g_kdbus_RemoveMatch (GKDBusWorker *worker, + guint64 cookie) { - struct kdbus_cmd_match cmd_match = {}; + struct kdbus_cmd_match cmd = { + .size = sizeof(cmd), + .cookie = cookie + }; gint ret; - cmd_match.size = sizeof (cmd_match); - cmd_match.cookie = cookie; - - ret = ioctl(worker->fd, KDBUS_CMD_MATCH_REMOVE, &cmd_match); + g_print ("Unsubscribe match entry with cookie - %d\n", (int)cookie); + ret = ioctl(worker->fd, KDBUS_CMD_MATCH_REMOVE, &cmd); if (ret < 0) - g_warning ("ERROR - %d\n", (int) errno); + g_warning ("Error while removing a match: %d\n", errno); } /** - * _g_kdbus_subscribe_name_acquired: + * _g_kdbus_subscribe_name_owner_changed_internal: * */ static void -_g_kdbus_subscribe_name_owner_changed (GKDBusWorker *worker, - const gchar *name, - const gchar *old_name, - const gchar *new_name, - guint cookie) +_g_kdbus_subscribe_name_owner_changed_internal (GKDBusWorker *worker, + const gchar *name, + const gchar *old_name, + const gchar *new_name, + guint64 cookie) { struct kdbus_item *item; - struct kdbus_cmd_match *cmd_match; + struct kdbus_cmd_match *cmd; gssize size, len; gint ret; - guint64 old_id = 0; /* XXX why? */ + guint64 old_id = 0; guint64 new_id = KDBUS_MATCH_ID_ANY; - len = strlen(name) + 1; + if (name) + len = strlen(name) + 1; + else + len = 0; + size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) + G_STRUCT_OFFSET (struct kdbus_item, name_change) + G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len); - cmd_match = g_alloca0 (size); - cmd_match->size = size; - cmd_match->cookie = cookie; - item = cmd_match->items; + cmd = g_alloca0 (size); + cmd->size = size; + cmd->cookie = cookie; + item = cmd->items; - if (old_name[0] == 0) + if (old_name == NULL) { old_id = KDBUS_MATCH_ID_ANY; } else { if (g_dbus_is_unique_name(old_name)) - old_id = old_id+3; + old_id = strtoull (old_name + 3, NULL, 10); else return; } - if (new_name[0] == 0) + if (new_name == NULL) { new_id = KDBUS_MATCH_ID_ANY; } else { if (g_dbus_is_unique_name(new_name)) - new_id = new_id+3; + new_id = strtoull (new_name + 3, NULL, 10); else return; } - cmd_match = g_alloca0 (size); - cmd_match->size = size; - cmd_match->cookie = cookie; - item = cmd_match->items; + cmd = g_alloca0 (size); + cmd->size = size; + cmd->cookie = cookie; + item = cmd->items; /* KDBUS_ITEM_NAME_CHANGE */ item->type = KDBUS_ITEM_NAME_CHANGE; item->name_change.old_id.id = old_id; item->name_change.new_id.id = new_id; - memcpy(item->name_change.name, name, len); + + if (name) + memcpy(item->name_change.name, name, len); + item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) + G_STRUCT_OFFSET(struct kdbus_notify_name_change, name) + len; item = KDBUS_ITEM_NEXT(item); - ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd_match); + ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd); if (ret < 0) g_warning ("ERROR - %d\n", (int) errno); } @@ -1002,39 +1640,46 @@ _g_kdbus_subscribe_name_owner_changed (GKDBusWorker *worker, */ void _g_kdbus_subscribe_name_acquired (GKDBusWorker *worker, - const gchar *name) + const gchar *name, + guint64 cookie) { struct kdbus_item *item; - struct kdbus_cmd_match *cmd_match; + struct kdbus_cmd_match *cmd; gssize size, len; - guint64 cookie; gint ret; - len = strlen(name) + 1; + g_print ("Subscribe 'NameAcquired': name - %s ; cookie - %d\n", name, (int)cookie); + if (name) + len = strlen(name) + 1; + else + len = 0; + size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) + G_STRUCT_OFFSET (struct kdbus_item, name_change) + G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len); - cookie = 0xbeefbeefbeefbeef; - cmd_match = g_alloca0 (size); - cmd_match->size = size; - cmd_match->cookie = cookie; - item = cmd_match->items; + cmd = g_alloca0 (size); + cmd->size = size; + cmd->cookie = cookie; + item = cmd->items; /* KDBUS_ITEM_NAME_ADD */ item->type = KDBUS_ITEM_NAME_ADD; item->name_change.old_id.id = KDBUS_MATCH_ID_ANY; item->name_change.new_id.id = worker->unique_id; - memcpy(item->name_change.name, name, len); + + if (name) + memcpy(item->name_change.name, name, len); + item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) + G_STRUCT_OFFSET(struct kdbus_notify_name_change, name) + len; item = KDBUS_ITEM_NEXT(item); - ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd_match); + ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd); if (ret < 0) g_warning ("ERROR - %d\n", (int) errno); - _g_kdbus_subscribe_name_owner_changed (worker, name, "", worker->unique_name, cookie); + _g_kdbus_subscribe_name_owner_changed_internal (worker, name, NULL, worker->unique_name, cookie); } @@ -1044,180 +1689,59 @@ _g_kdbus_subscribe_name_acquired (GKDBusWorker *worker, */ void _g_kdbus_subscribe_name_lost (GKDBusWorker *worker, - const gchar *name) + const gchar *name, + guint64 cookie) { struct kdbus_item *item; - struct kdbus_cmd_match *cmd_match; + struct kdbus_cmd_match *cmd; gssize size, len; - guint64 cookie; gint ret; - len = strlen(name) + 1; + g_print ("Subscribe 'NameLost': name - %s ; cookie - %d\n", name, (int)cookie); + if (name) + len = strlen(name) + 1; + else + len = 0; + size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) + G_STRUCT_OFFSET (struct kdbus_item, name_change) + G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len); - cookie = 0xdeafdeafdeafdeaf; - cmd_match = g_alloca0 (size); - cmd_match->size = size; - cmd_match->cookie = cookie; - item = cmd_match->items; + cmd = g_alloca0 (size); + cmd->size = size; + cmd->cookie = cookie; + item = cmd->items; /* KDBUS_ITEM_NAME_REMOVE */ item->type = KDBUS_ITEM_NAME_REMOVE; item->name_change.old_id.id = worker->unique_id; item->name_change.new_id.id = KDBUS_MATCH_ID_ANY; - memcpy(item->name_change.name, name, len); + + if (name) + memcpy(item->name_change.name, name, len); + item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) + G_STRUCT_OFFSET(struct kdbus_notify_name_change, name) + len; item = KDBUS_ITEM_NEXT(item); - ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd_match); + ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd); if (ret < 0) g_warning ("ERROR - %d\n", (int) errno); - _g_kdbus_subscribe_name_owner_changed (worker, name, worker->unique_name, "", cookie); + _g_kdbus_subscribe_name_owner_changed_internal (worker, name, worker->unique_name, NULL, cookie); } /** - * _g_kdbus_unsubscribe_name_acquired: * - */ -void -_g_kdbus_unsubscribe_name_acquired (GKDBusWorker *worker) -{ - guint64 cookie; - - cookie = 0xbeefbeefbeefbeef; - _g_kdbus_match_remove (worker, cookie); -} - - -/** - * _g_kdbus_unsubscribe_name_lost: * */ void -_g_kdbus_unsubscribe_name_lost (GKDBusWorker *worker) -{ - guint64 cookie; - - cookie = 0xdeafdeafdeafdeaf; - _g_kdbus_match_remove (worker, cookie); -} - - -/** - * g_kdbus_append_payload_bloom: - * - */ -static struct kdbus_bloom_filter * -g_kdbus_append_bloom (struct kdbus_item **item, - gsize size) -{ - struct kdbus_item *bloom_item; - - bloom_item = KDBUS_ALIGN8_PTR(*item); - bloom_item->size = G_STRUCT_OFFSET (struct kdbus_item, bloom_filter) + - G_STRUCT_OFFSET (struct kdbus_bloom_filter, data) + - size; - - bloom_item->type = KDBUS_ITEM_BLOOM_FILTER; - - *item = KDBUS_ITEM_NEXT(bloom_item); - return &bloom_item->bloom_filter; -} - - -/** - * g_kdbus_bloom_add_data: - * Based on bus-bloom.c from systemd - * http://cgit.freedesktop.org/systemd/systemd/tree/src/libsystemd/sd-bus/bus-bloom.c - */ -static void -g_kdbus_bloom_add_data (GKDBusWorker *worker, - guint64 bloom_data [], - const void *data, - gsize n) -{ - guint8 hash[8]; - guint64 bit_num; - guint bytes_num = 0; - guint cnt_1, cnt_2; - - guint c = 0; - guint64 p = 0; - - bit_num = worker->bloom_size * 8; - - if (bit_num > 1) - bytes_num = ((__builtin_clzll(bit_num) ^ 63U) + 7) / 8; - - for (cnt_1 = 0; cnt_1 < (worker->bloom_n_hash); cnt_1++) - { - for (cnt_2 = 0; cnt_2 < bytes_num; cnt_2++) - { - if (c <= 0) - { - g_siphash24(hash, data, n, hash_keys[cnt_1++]); - c += 8; - } - - p = (p << 8ULL) | (guint64) hash[8 - c]; - c--; - } - - p &= bit_num - 1; - bloom_data[p >> 6] |= 1ULL << (p & 63); - } -} - - -/** - * g_kdbus_bloom_add_pair: - * - */ -static void -g_kdbus_bloom_add_pair (GKDBusWorker *worker, - guint64 bloom_data [], - const gchar *parameter, - const gchar *value) -{ - GString *data = g_string_new (NULL); - - g_string_printf (data,"%s:%s",parameter,value); - g_kdbus_bloom_add_data(worker, bloom_data, data->str, data->len); - g_string_free (data, TRUE); -} - - -/** - * g_kdbus_bloom_add_prefixes: - * - */ -static void -g_kdbus_bloom_add_prefixes (GKDBusWorker *worker, - guint64 bloom_data [], - const gchar *parameter, - const gchar *value, - gchar separator) +_g_kdbus_subscribe_name_owner_changed (GKDBusWorker *worker, + const gchar *name, + guint64 cookie) { - GString *data = g_string_new (NULL); - - g_string_printf (data,"%s:%s",parameter,value); - - for (;;) - { - gchar *last_sep; - last_sep = strrchr(data->str, separator); - if (!last_sep || last_sep == data->str) - break; - - *last_sep = 0; - g_kdbus_bloom_add_data(worker, bloom_data, data->str, last_sep-(data->str)); - } - g_string_free (data, TRUE); + g_print ("NameOwnerChanged subscription\n"); } @@ -1321,9 +1845,80 @@ g_kdbus_setup_bloom (GKDBusWorker *worker, } -/* - * TODO: g_kdbus_NameOwnerChanged_generate, g_kdbus_KernelMethodError_generate +/** + * + * + */ +static void +g_kdbus_translate_id_change (GKDBusWorker *worker, + struct kdbus_item *item) +{ + g_error ("TODO: translate_id_change\n"); +} + + +/** + * + * + */ +static void +g_kdbus_translate_name_change (GKDBusWorker *worker, + struct kdbus_item *item) +{ + GDBusMessage *signal_message; + + signal_message = NULL; + + /* NameAcquired */ + if ((item->type == KDBUS_ITEM_NAME_ADD) || + (item->type == KDBUS_ITEM_NAME_CHANGE && ((guint64)item->name_change.new_id.id == worker->unique_id))) + { + signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus", + "org.freedesktop.DBus", + "NameAcquired"); + + g_dbus_message_set_sender (signal_message, "org.freedesktop.DBus"); + g_dbus_message_set_body (signal_message, + g_variant_new ("(s)", item->name_change.name)); + + (* worker->message_received_callback) (signal_message, worker->user_data); + g_object_unref (signal_message); + } + + /* NameLost */ + if ((item->type == KDBUS_ITEM_NAME_REMOVE) || + (item->type == KDBUS_ITEM_NAME_CHANGE && ((guint64)item->name_change.old_id.id == worker->unique_id))) + { + GDBusMessage *signal_message; + + signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus", + "org.freedesktop.DBus", + "NameLost"); + + g_dbus_message_set_sender (signal_message, "org.freedesktop.DBus"); + g_dbus_message_set_body (signal_message, + g_variant_new ("(s)", item->name_change.name)); + + (* worker->message_received_callback) (signal_message, worker->user_data); + g_object_unref (signal_message); + } + + /* NameOwnerChanged */ + /* TODO */ +} + + +/** + * + * */ +static void +g_kdbus_translate_kernel_reply (GKDBusWorker *worker, + struct kdbus_item *item) +{ + g_error ("TODO: translate_kernel_reply\n"); +} + /** * g_kdbus_decode_kernel_msg: @@ -1341,39 +1936,27 @@ g_kdbus_decode_kernel_msg (GKDBusWorker *worker, { case KDBUS_ITEM_ID_ADD: case KDBUS_ITEM_ID_REMOVE: + g_kdbus_translate_id_change (worker, item); + break; + case KDBUS_ITEM_NAME_ADD: case KDBUS_ITEM_NAME_REMOVE: case KDBUS_ITEM_NAME_CHANGE: - //size = g_kdbus_NameOwnerChanged_generate (worker, item); - g_error ("'NameOwnerChanged'"); + g_kdbus_translate_name_change (worker, item); break; case KDBUS_ITEM_REPLY_TIMEOUT: case KDBUS_ITEM_REPLY_DEAD: - //size = g_kdbus_KernelMethodError_generate (worker, item); - g_error ("'KernelMethodError'"); + g_kdbus_translate_kernel_reply (worker, item); + break; + + case KDBUS_ITEM_TIMESTAMP: break; default: g_warning ("Unknown field in kernel message - %lld", item->type); } } - -#if 0 - /* Override information from the user header with data from the kernel */ - g_string_printf (worker->msg_sender, "org.freedesktop.DBus"); - - /* for destination */ - if (worker->kmsg->dst_id == KDBUS_DST_ID_BROADCAST) - /* for broadcast messages we don't have to set destination */ - ; - else if (worker->kmsg->dst_id == KDBUS_DST_ID_NAME) - g_string_printf (worker->msg_destination, ":1.%" G_GUINT64_FORMAT, (guint64) worker->unique_id); - else - g_string_printf (worker->msg_destination, ":1.%" G_GUINT64_FORMAT, (guint64) worker->kmsg->dst_id); - - return size; -#endif } @@ -1463,7 +2046,7 @@ g_kdbus_decode_dbus_msg (GKDBusWorker *worker, flavour = body_size & 7; g_assert ((item->vec.offset & 7) == flavour); - vector.gbytes = g_bytes_new (((guchar *) worker->kdbus_buffer) + item->vec.offset - flavour, item->vec.size + flavour); + vector.gbytes = g_bytes_new (((guchar *) msg) + item->vec.offset - flavour, item->vec.size + flavour); vector.data.pointer = g_bytes_get_data (vector.gbytes, NULL); vector.data.pointer += flavour; vector.size = item->vec.size; @@ -1509,8 +2092,9 @@ g_kdbus_decode_dbus_msg (GKDBusWorker *worker, should be implemented in the future */ case KDBUS_ITEM_TIMESTAMP: { - g_print ("time: seq %llu mon %llu real %llu\n", - item->timestamp.seqnum, item->timestamp.monotonic_ns, item->timestamp.realtime_ns); + /* g_print ("time: seq %llu mon %llu real %llu\n", + item->timestamp.seqnum, item->timestamp.monotonic_ns, item->timestamp.realtime_ns); */ + //g_dbus_message_set_timestamp (message, item->timestamp.monotonic_ns / 1000); //g_dbus_message_set_serial (message, item->timestamp.seqnum); break; @@ -1518,9 +2102,9 @@ g_kdbus_decode_dbus_msg (GKDBusWorker *worker, case KDBUS_ITEM_CREDS: { - g_print ("creds: u%u eu %u su%u fsu%u g%u eg%u sg%u fsg%u\n", + /* g_print ("creds: u%llu eu %llu su%llu fsu%llu g%llu eg%llu sg%llu fsg%llu\n", item->creds.uid, item->creds.euid, item->creds.suid, item->creds.fsuid, - item->creds.gid, item->creds.egid, item->creds.sgid, item->creds.fsgid); + item->creds.gid, item->creds.egid, item->creds.sgid, item->creds.fsgid); */ break; } @@ -1537,7 +2121,7 @@ g_kdbus_decode_dbus_msg (GKDBusWorker *worker, case KDBUS_ITEM_AUXGROUPS: case KDBUS_ITEM_OWNED_NAME: case KDBUS_ITEM_NAME: - g_print ("unhandled %04x\n", (int) item->type); + //g_print ("unhandled %04x\n", (int) item->type); break; default: @@ -1560,11 +2144,6 @@ g_kdbus_decode_dbus_msg (GKDBusWorker *worker, parts[1] = g_variant_get_child_value (body, 1); g_variant_unref (body); - body = g_variant_get_variant (parts[1]); - g_variant_unref (parts[1]); - g_dbus_message_set_body (message, body); - g_variant_unref (body); - g_variant_get (parts[0], "(yyyyuta{tv})", &endianness, &type, &flags, &version, NULL, &serial, &fields_iter); g_variant_unref (parts[0]); @@ -1575,9 +2154,21 @@ g_kdbus_decode_dbus_msg (GKDBusWorker *worker, g_dbus_message_set_serial (message, serial); g_dbus_message_set_message_type (message, type); - g_print ("Received:\n%s\n", g_dbus_message_print (message, 2)); + //if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE) != NULL) + // { + body = g_variant_get_variant (parts[1]); + g_dbus_message_set_body (message, body); + g_variant_unref (body); + // } + g_variant_unref (parts[1]); + + //g_print ("Received:\n%s\n", g_dbus_message_print (message, 2)); + + (* worker->message_received_callback) (message, worker->user_data); - return message; + g_object_unref (message); + + return 0; } @@ -1608,6 +2199,10 @@ again: if (errno == EAGAIN) return 0; + g_warning ("in holding pattern over %d %d\n", kdbus->fd, errno); + while (1) + sleep(1); + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), _("Error while receiving message: %s"), @@ -1615,7 +2210,7 @@ again: return -1; } - msg = (struct kdbus_msg *)((guint8 *)kdbus->kdbus_buffer + recv.reply.offset); + msg = (struct kdbus_msg *)((guint8 *)kdbus->kdbus_buffer + recv.msg.offset); if (msg->payload_type == KDBUS_PAYLOAD_DBUS) g_kdbus_decode_dbus_msg (kdbus, msg); @@ -1630,9 +2225,9 @@ again: return -1; } - ioctl(kdbus->fd, KDBUS_CMD_FREE, &recv.reply.offset); + g_kdbus_free_data (kdbus, recv.msg.offset); - return 0; + return 0; } static gboolean @@ -1689,6 +2284,26 @@ g_kdbus_msg_append_payload_memfd (struct kdbus_msg *msg, return g_kdbus_msg_append_item (msg, KDBUS_ITEM_PAYLOAD_MEMFD, &mfd, sizeof mfd); } +static struct kdbus_bloom_filter * +g_kdbus_msg_append_bloom (struct kdbus_msg *msg, + gsize size) +{ + struct kdbus_item *bloom_item; + + /* align */ + msg->size += (-msg->size) & 7; + bloom_item = (struct kdbus_item *) ((guchar *) msg + msg->size); + + /* set size and type */ + bloom_item->size = G_STRUCT_OFFSET (struct kdbus_item, bloom_filter) + + G_STRUCT_OFFSET (struct kdbus_bloom_filter, data) + + size; + bloom_item->type = KDBUS_ITEM_BLOOM_FILTER; + + msg->size += bloom_item->size; + return &bloom_item->bloom_filter; +} + #if 0 #include "dbusheader.h" @@ -1792,6 +2407,7 @@ _g_kdbus_send (GKDBusWorker *kdbus, struct kdbus_msg *msg = alloca (KDBUS_MSG_MAX_SIZE); GVariantVectors body_vectors; struct kdbus_cmd_send send; + const gchar *dst_name; g_return_val_if_fail (G_IS_KDBUS_WORKER (kdbus), -1); @@ -1804,8 +2420,6 @@ _g_kdbus_send (GKDBusWorker *kdbus, /* Message destination */ { - const gchar *dst_name; - dst_name = g_dbus_message_get_destination (message); if (dst_name != NULL) @@ -1995,16 +2609,19 @@ _g_kdbus_send (GKDBusWorker *kdbus, else msg->cookie_reply = g_dbus_message_get_reply_serial(message); + if (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_SIGNAL) + msg->flags |= KDBUS_MSG_SIGNAL; /* - if (dst_id == KDBUS_DST_ID_BROADCAST) + * + */ + if (msg->dst_id == KDBUS_DST_ID_BROADCAST) { struct kdbus_bloom_filter *bloom_filter; - bloom_filter = g_kdbus_append_bloom (&item, kdbus->bloom_size); + bloom_filter = g_kdbus_msg_append_bloom (msg, kdbus->bloom_size); g_kdbus_setup_bloom (kdbus, message, bloom_filter); } - */ send.size = sizeof (send); send.flags = 0; @@ -2013,57 +2630,29 @@ _g_kdbus_send (GKDBusWorker *kdbus, /* * send message */ -//again: if (ioctl(kdbus->fd, KDBUS_CMD_SEND, &send)) { -/* - GString *error_name; - error_name = g_string_new (NULL); - - if(errno == EINTR) + if (errno == ENXIO || errno == ESRCH) { - g_string_free (error_name,TRUE); - goto again; + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN, + "Destination '%s' not known", dst_name); } - else if (errno == ENXIO) + else if (errno == EADDRNOTAVAIL) { - g_string_printf (error_name, "Name %s does not exist", g_dbus_message_get_destination(dbus_msg)); - g_kdbus_generate_local_error (worker, - dbus_msg, - g_variant_new ("(s)",error_name->str), - G_DBUS_ERROR_SERVICE_UNKNOWN); - g_string_free (error_name,TRUE); - return 0; + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN, + "No support for activation for name: %s", dst_name); } - else if ((errno == ESRCH) || (errno == EADDRNOTAVAIL)) + else if (errno == EXFULL) { - if (kmsg->flags & KDBUS_MSG_FLAGS_NO_AUTO_START) - { - g_string_printf (error_name, "Name %s does not exist", g_dbus_message_get_destination(dbus_msg)); - g_kdbus_generate_local_error (worker, - dbus_msg, - g_variant_new ("(s)",error_name->str), - G_DBUS_ERROR_SERVICE_UNKNOWN); - g_string_free (error_name,TRUE); - return 0; - } - else - { - g_string_printf (error_name, "The name %s was not provided by any .service files", g_dbus_message_get_destination(dbus_msg)); - g_kdbus_generate_local_error (worker, - dbus_msg, - g_variant_new ("(s)",error_name->str), - G_DBUS_ERROR_SERVICE_UNKNOWN); - g_string_free (error_name,TRUE); - return 0; - } + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_LIMITS_EXCEEDED, + "The memory pool of the receiver is full"); + } + else + { + g_error ("WTF? %d\n", errno); + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "%s", strerror(errno)); } - - g_print ("[KDBUS] ioctl error sending kdbus message:%d (%m)\n",errno); - g_set_error (error, G_IO_ERROR, g_io_error_from_errno(errno), _("Error sending message - KDBUS_CMD_MSG_SEND error")); -*/ - perror("ioctl send"); - g_error ("IOCTL SEND: %d\n",errno); return FALSE; } @@ -2083,14 +2672,6 @@ need_compact: GKDBusWorker * g_kdbus_worker_new (const gchar *address, GError **error) -#if 0 - GDBusCapabilityFlags capabilities, - gboolean initially_frozen, - GDBusWorkerMessageReceivedCallback message_received_callback, - GDBusWorkerMessageAboutToBeSentCallback message_about_to_be_sent_callback, - GDBusWorkerDisconnectedCallback disconnected_callback, - gpointer user_data) -#endif { GKDBusWorker *worker; @@ -2105,8 +2686,37 @@ g_kdbus_worker_new (const gchar *address, } void +g_kdbus_worker_associate (GKDBusWorker *worker, + GDBusCapabilityFlags capabilities, + GDBusWorkerMessageReceivedCallback message_received_callback, + GDBusWorkerMessageAboutToBeSentCallback message_about_to_be_sent_callback, + GDBusWorkerDisconnectedCallback disconnected_callback, + gpointer user_data) +{ + worker->capabilities = capabilities; + worker->message_received_callback = message_received_callback; + worker->message_about_to_be_sent_callback = message_about_to_be_sent_callback; + worker->disconnected_callback = disconnected_callback; + worker->user_data = user_data; +} + +void g_kdbus_worker_unfreeze (GKDBusWorker *worker) { + gchar *name; + + if (worker->source != NULL) + return; + + worker->context = g_main_context_ref_thread_default (); + worker->source = g_unix_fd_source_new (worker->fd, G_IO_IN); + + g_source_set_callback (worker->source, (GSourceFunc) kdbus_ready, worker, NULL); + name = g_strdup_printf ("kdbus worker"); + g_source_set_name (worker->source, name); + g_free (name); + + g_source_attach (worker->source, worker->context); } gboolean