[kdbus] Add support for 'NameOwnerChanged' signal
[platform/upstream/glib.git] / gio / gkdbus.c
1 /*  GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright (C) 2013 Samsung Electronics
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Michal Eljasiewicz   <m.eljasiewic@samsung.com>
21  * Author: Lukasz Skalski       <l.skalski@samsung.com>
22  */
23
24 #include "config.h"
25 #include "gkdbus.h"
26 #include "glib-unix.h"
27 #include "glibintl.h"
28 #include "kdbus.h"
29
30 #include <gio/gio.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <sys/mman.h>
34 #include <sys/ioctl.h>
35 #include <stdio.h>
36 #include <stdint.h>
37
38 #ifdef HAVE_SYS_FILIO_H
39 # include <sys/filio.h>
40 #endif
41
42 #ifdef HAVE_SYS_UIO_H
43 #include <sys/uio.h>
44 #endif
45
46 #include <glib/gstdio.h>
47 #include <glib/glib-private.h>
48 #include <gio/gio.h>
49 #include <gio/gunixfdlist.h>
50
51 #include "glibintl.h"
52 #include "gunixfdmessage.h"
53
54 #define KDBUS_MSG_MAX_SIZE         8192
55 #define KDBUS_TIMEOUT_NS           2000000000LU
56 #define KDBUS_POOL_SIZE            (16 * 1024LU * 1024LU)
57 #define KDBUS_ALIGN8(l)            (((l) + 7) & ~7)
58 #define KDBUS_ALIGN8_PTR(p)        ((void*) (uintptr_t)(p))
59
60 #define KDBUS_ITEM_HEADER_SIZE G_STRUCT_OFFSET(struct kdbus_item, data)
61 #define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
62
63 #define KDBUS_ITEM_NEXT(item) \
64         (typeof(item))(((guint8 *)item) + KDBUS_ALIGN8((item)->size))
65 #define KDBUS_ITEM_FOREACH(item, head, first)                    \
66         for (item = (head)->first;                               \
67              (guint8 *)(item) < (guint8 *)(head) + (head)->size; \
68              item = KDBUS_ITEM_NEXT(item))
69 #define KDBUS_FOREACH(iter, first, _size)                             \
70         for (iter = (first);                                          \
71              ((guint8 *)(iter) < (guint8 *)(first) + (_size)) &&      \
72                ((guint8 *)(iter) >= (guint8 *)(first));               \
73              iter = (void*)(((guint8 *)iter) + KDBUS_ALIGN8((iter)->size)))
74
75 #define g_alloca0(x) memset(g_alloca(x), '\0', (x))
76
77 struct dbus_fixed_header {
78   guint8  endian;
79   guint8  type;
80   guint8  flags;
81   guint8  version;
82   guint32 reserved;
83   guint64 serial;
84 };
85
86 #define DBUS_FIXED_HEADER_TYPE     ((const GVariantType *) "(yyyyut)")
87 #define DBUS_EXTENDED_HEADER_TYPE  ((const GVariantType *) "a{tv}")
88 #define DBUS_MESSAGE_TYPE          ((const GVariantType *) "((yyyyut)a{tv}v)")
89
90 /*
91  * Macros for SipHash algorithm
92  */
93
94 #define ROTL(x,b) (guint64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
95
96 #define U32TO8_LE(p, v)         \
97     (p)[0] = (guint8)((v)      ); (p)[1] = (guint8)((v) >>  8); \
98     (p)[2] = (guint8)((v) >> 16); (p)[3] = (guint8)((v) >> 24);
99
100 #define U64TO8_LE(p, v)         \
101   U32TO8_LE((p),     (guint32)((v)      ));   \
102   U32TO8_LE((p) + 4, (guint32)((v) >> 32));
103
104 #define U8TO64_LE(p) \
105   (((guint64)((p)[0])      ) | \
106    ((guint64)((p)[1]) <<  8) | \
107    ((guint64)((p)[2]) << 16) | \
108    ((guint64)((p)[3]) << 24) | \
109    ((guint64)((p)[4]) << 32) | \
110    ((guint64)((p)[5]) << 40) | \
111    ((guint64)((p)[6]) << 48) | \
112    ((guint64)((p)[7]) << 56))
113
114 #define SIPROUND            \
115   do {              \
116     v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
117     v2 += v3; v3=ROTL(v3,16); v3 ^= v2;     \
118     v0 += v3; v3=ROTL(v3,21); v3 ^= v0;     \
119     v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
120   } while(0)
121
122 typedef enum
123 {
124   G_BUS_CREDS_PID              = 1,
125   G_BUS_CREDS_UID              = 2,
126   G_BUS_CREDS_UNIQUE_NAME      = 3,
127   G_BUS_CREDS_SELINUX_CONTEXT  = 4
128 } GBusCredentialsFlags;
129
130 typedef GObjectClass GKDBusWorkerClass;
131
132 struct _GKDBusWorker
133 {
134   GObject            parent_instance;
135
136   gint               fd;
137
138   GMainContext      *context;
139   GSource           *source;
140
141   gchar             *kdbus_buffer;
142
143   gchar             *unique_name;
144   guint64            unique_id;
145
146   guint64            flags;
147   guint64            attach_flags_send;
148   guint64            attach_flags_recv;
149
150   gsize              bloom_size;
151   guint              bloom_n_hash;
152
153   guint              closed : 1;
154   guint              inited : 1;
155   guint              timeout;
156   guint              timed_out : 1;
157
158   guchar             bus_id[16];
159
160   GDBusCapabilityFlags                     capabilities;
161   GDBusWorkerMessageReceivedCallback       message_received_callback;
162   GDBusWorkerMessageAboutToBeSentCallback  message_about_to_be_sent_callback;
163   GDBusWorkerDisconnectedCallback          disconnected_callback;
164   gpointer                                 user_data;
165 };
166
167 static gssize _g_kdbus_receive (GKDBusWorker  *kdbus,
168                                 GCancellable  *cancellable,
169                                 GError       **error);
170
171 G_DEFINE_TYPE (GKDBusWorker, g_kdbus_worker, G_TYPE_OBJECT)
172
173 /* Hash keys for bloom filters*/
174 const guint8 hash_keys[8][16] =
175 {
176   {0xb9,0x66,0x0b,0xf0,0x46,0x70,0x47,0xc1,0x88,0x75,0xc4,0x9c,0x54,0xb9,0xbd,0x15},
177   {0xaa,0xa1,0x54,0xa2,0xe0,0x71,0x4b,0x39,0xbf,0xe1,0xdd,0x2e,0x9f,0xc5,0x4a,0x3b},
178   {0x63,0xfd,0xae,0xbe,0xcd,0x82,0x48,0x12,0xa1,0x6e,0x41,0x26,0xcb,0xfa,0xa0,0xc8},
179   {0x23,0xbe,0x45,0x29,0x32,0xd2,0x46,0x2d,0x82,0x03,0x52,0x28,0xfe,0x37,0x17,0xf5},
180   {0x56,0x3b,0xbf,0xee,0x5a,0x4f,0x43,0x39,0xaf,0xaa,0x94,0x08,0xdf,0xf0,0xfc,0x10},
181   {0x31,0x80,0xc8,0x73,0xc7,0xea,0x46,0xd3,0xaa,0x25,0x75,0x0f,0x9e,0x4c,0x09,0x29},
182   {0x7d,0xf7,0x18,0x4b,0x7b,0xa4,0x44,0xd5,0x85,0x3c,0x06,0xe0,0x65,0x53,0x96,0x6d},
183   {0xf2,0x77,0xe9,0x6f,0x93,0xb5,0x4e,0x71,0x9a,0x0c,0x34,0x88,0x39,0x25,0xbf,0x35}
184 };
185
186 enum {
187   MATCH_ELEMENT_TYPE,
188   MATCH_ELEMENT_SENDER,
189   MATCH_ELEMENT_INTERFACE,
190   MATCH_ELEMENT_MEMBER,
191   MATCH_ELEMENT_PATH,
192   MATCH_ELEMENT_PATH_NAMESPACE,
193   MATCH_ELEMENT_DESTINATION,
194   MATCH_ELEMENT_ARG0NAMESPACE,
195   MATCH_ELEMENT_EAVESDROP,
196   MATCH_ELEMENT_ARGN,
197   MATCH_ELEMENT_ARGNPATH,
198 };
199
200 /* MatchElement struct */
201 typedef struct {
202   guint16 type;
203   guint16 arg;
204   char *value;
205 } MatchElement;
206
207 /* Match struct */
208 typedef struct {
209   int n_elements;
210   MatchElement *elements;
211 } Match;
212
213
214 /**
215  * SipHash algorithm
216  *
217  */
218 static void
219 _g_siphash24 (guint8         out[8],
220               const void    *_in,
221               gsize          inlen,
222               const guint8   k[16])
223 {
224   /* "somepseudorandomlygeneratedbytes" */
225   guint64 v0 = 0x736f6d6570736575ULL;
226   guint64 v1 = 0x646f72616e646f6dULL;
227   guint64 v2 = 0x6c7967656e657261ULL;
228   guint64 v3 = 0x7465646279746573ULL;
229   guint64 b;
230   guint64 k0 = U8TO64_LE (k);
231   guint64 k1 = U8TO64_LE (k + 8);
232   guint64 m;
233   const guint8 *in = _in;
234   const guint8 *end = in + inlen - (inlen % sizeof(guint64));
235   const int left = inlen & 7;
236   b = ((guint64) inlen) << 56;
237   v3 ^= k1;
238   v2 ^= k0;
239   v1 ^= k1;
240   v0 ^= k0;
241
242   for (; in != end; in += 8)
243     {
244       m = U8TO64_LE (in);
245       v3 ^= m;
246       SIPROUND;
247       SIPROUND;
248       v0 ^= m;
249     }
250
251   switch (left)
252     {
253       case 7: b |= ((guint64) in[6]) << 48;
254       case 6: b |= ((guint64) in[5]) << 40;
255       case 5: b |= ((guint64) in[4]) << 32;
256       case 4: b |= ((guint64) in[3]) << 24;
257       case 3: b |= ((guint64) in[2]) << 16;
258       case 2: b |= ((guint64) in[1]) <<  8;
259       case 1: b |= ((guint64) in[0]); break;
260       case 0: break;
261     }
262
263   v3 ^= b;
264   SIPROUND;
265   SIPROUND;
266   v0 ^= b;
267
268   v2 ^= 0xff;
269   SIPROUND;
270   SIPROUND;
271   SIPROUND;
272   SIPROUND;
273   b = v0 ^ v1 ^ v2  ^ v3;
274   U64TO8_LE (out, b);
275 }
276
277
278 /**
279  * is_key()
280  *
281  */
282 static gboolean
283 is_key (const char *key_start, const char *key_end, char *value)
284 {
285   gsize len = strlen (value);
286
287   if (len != key_end - key_start)
288     return FALSE;
289
290   return strncmp (key_start, value, len) == 0;
291 }
292
293
294 /**
295  * parse_key()
296  *
297  */
298 static gboolean
299 parse_key (MatchElement *element, const char *key_start, const char *key_end)
300 {
301   gboolean res = TRUE;
302
303   if (is_key (key_start, key_end, "type"))
304     {
305       element->type = MATCH_ELEMENT_TYPE;
306     }
307   else if (is_key (key_start, key_end, "sender"))
308     {
309       element->type = MATCH_ELEMENT_SENDER;
310     }
311   else if (is_key (key_start, key_end, "interface"))
312     {
313       element->type = MATCH_ELEMENT_INTERFACE;
314     }
315   else if (is_key (key_start, key_end, "member"))
316     {
317       element->type = MATCH_ELEMENT_MEMBER;
318     }
319   else if (is_key (key_start, key_end, "path"))
320     {
321       element->type = MATCH_ELEMENT_PATH;
322     }
323   else if (is_key (key_start, key_end, "path_namespace"))
324     {
325       element->type = MATCH_ELEMENT_PATH_NAMESPACE;
326     }
327   else if (is_key (key_start, key_end, "destination"))
328     {
329       element->type = MATCH_ELEMENT_DESTINATION;
330     }
331   else if (is_key (key_start, key_end, "arg0namespace"))
332     {
333       element->type = MATCH_ELEMENT_ARG0NAMESPACE;
334     }
335   else if (is_key (key_start, key_end, "eavesdrop"))
336     {
337       element->type = MATCH_ELEMENT_EAVESDROP;
338     }
339   else if (key_end - key_start > 3 && is_key (key_start, key_start + 3, "arg"))
340     {
341       const char *digits = key_start + 3;
342       const char *end_digits = digits;
343
344       while (end_digits < key_end && g_ascii_isdigit (*end_digits))
345         end_digits++;
346
347       if (end_digits == key_end) /* argN */
348         {
349           element->type = MATCH_ELEMENT_ARGN;
350           element->arg = atoi (digits);
351         }
352       else if (is_key (end_digits, key_end, "path")) /* argNpath */
353         {
354           element->type = MATCH_ELEMENT_ARGNPATH;
355           element->arg = atoi (digits);
356         }
357       else
358         res = FALSE;
359     }
360   else
361     res = FALSE;
362
363   return res;
364 }
365
366
367 /**
368  * parse_value()
369  *
370  */
371 static const char *
372 parse_value (MatchElement *element, const char *s)
373 {
374   char quote_char;
375   GString *value;
376
377   value = g_string_new ("");
378
379   quote_char = 0;
380
381   for (;*s; s++)
382     {
383       if (quote_char == 0)
384         {
385           switch (*s)
386             {
387             case '\'':
388               quote_char = '\'';
389               break;
390
391             case ',':
392               s++;
393               goto out;
394
395             case '\\':
396               quote_char = '\\';
397               break;
398
399             default:
400               g_string_append_c (value, *s);
401               break;
402             }
403         }
404       else if (quote_char == '\\')
405         {
406           /* \ only counts as an escape if escaping a quote mark */
407           if (*s != '\'')
408             g_string_append_c (value, '\\');
409
410           g_string_append_c (value, *s);
411           quote_char = 0;
412         }
413       else /* quote_char == ' */
414         {
415           if (*s == '\'')
416             quote_char = 0;
417           else
418             g_string_append_c (value, *s);
419         }
420     }
421
422  out:
423   if (quote_char == '\\')
424     g_string_append_c (value, '\\');
425   else if (quote_char == '\'')
426     {
427       g_string_free (value, TRUE);
428       return NULL;
429     }
430
431   element->value = g_string_free (value, FALSE);
432   return s;
433 }
434
435
436 /**
437  * match_new()
438  *
439  */
440 static Match *
441 match_new (const char *str)
442 {
443   Match *match;
444   GArray *elements;
445   const char *p;
446   const char *key_start;
447   const char *key_end;
448   MatchElement element;
449   int i;
450
451   elements = g_array_new (TRUE, TRUE, sizeof (MatchElement));
452
453   p = str;
454
455   while (*p != 0)
456     {
457       memset (&element, 0, sizeof (element));
458
459       /* Skip initial whitespace */
460       while (*p && g_ascii_isspace (*p))
461         p++;
462
463       key_start = p;
464
465       /* Read non-whitespace non-equals chars */
466       while (*p && *p != '=' && !g_ascii_isspace (*p))
467         p++;
468
469       key_end = p;
470
471       /* Skip any whitespace after key */
472       while (*p && g_ascii_isspace (*p))
473         p++;
474
475       if (key_start == key_end)
476         continue; /* Allow trailing whitespace */
477       if (*p != '=')
478         goto error;
479
480       ++p;
481
482       if (!parse_key (&element, key_start, key_end))
483         goto error;
484
485       p = parse_value (&element, p);
486       if (p == NULL)
487         goto error;
488
489       g_array_append_val (elements, element);
490     }
491
492   match = g_new0 (Match, 1);
493   match->n_elements = elements->len;
494   match->elements = (MatchElement *)g_array_free (elements, FALSE);
495
496   return match;
497
498  error:
499   for (i = 0; i < elements->len; i++)
500     g_free (g_array_index (elements, MatchElement, i).value);
501   g_array_free (elements, TRUE);
502   return NULL;
503 }
504
505
506 /**
507  * match_free()
508  *
509  */
510 static void
511 match_free (Match *match)
512 {
513   int i;
514   for (i = 0; i < match->n_elements; i++)
515     g_free (match->elements[i].value);
516   g_free (match->elements);
517   g_free (match);
518 }
519
520
521 /**
522  * g_kdbus_finalize:
523  *
524  */
525 static void
526 g_kdbus_worker_finalize (GObject *object)
527 {
528   GKDBusWorker *kdbus = G_KDBUS_WORKER (object);
529
530   if (kdbus->kdbus_buffer != NULL)
531     munmap (kdbus->kdbus_buffer, KDBUS_POOL_SIZE);
532
533   kdbus->kdbus_buffer = NULL;
534
535   if (kdbus->fd != -1 && !kdbus->closed)
536     _g_kdbus_close (kdbus);
537
538   G_OBJECT_CLASS (g_kdbus_worker_parent_class)->finalize (object);
539 }
540
541 static void
542 g_kdbus_worker_class_init (GKDBusWorkerClass *class)
543 {
544   class->finalize = g_kdbus_worker_finalize;
545 }
546
547 static void
548 g_kdbus_worker_init (GKDBusWorker *kdbus)
549 {
550   kdbus->fd = -1;
551
552   kdbus->unique_id = -1;
553   kdbus->unique_name = NULL;
554
555   kdbus->kdbus_buffer = NULL;
556
557   kdbus->flags = KDBUS_HELLO_ACCEPT_FD;
558   kdbus->attach_flags_send = _KDBUS_ATTACH_ALL;
559   kdbus->attach_flags_recv = _KDBUS_ATTACH_ALL;
560 }
561
562 static gboolean
563 kdbus_ready (gint         fd,
564              GIOCondition condition,
565              gpointer     user_data)
566 {
567   GKDBusWorker *kdbus = user_data;
568   GError *error = NULL;
569
570   _g_kdbus_receive (kdbus, NULL, &error);
571   g_assert_no_error (error);
572
573   return G_SOURCE_CONTINUE;
574 }
575
576 gboolean
577 _g_kdbus_open (GKDBusWorker  *worker,
578                const gchar   *address,
579                GError       **error)
580 {
581   g_return_val_if_fail (G_IS_KDBUS_WORKER (worker), FALSE);
582
583   worker->fd = open(address, O_RDWR|O_NOCTTY|O_CLOEXEC);
584   if (worker->fd<0)
585     {
586       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Can't open kdbus endpoint"));
587       return FALSE;
588     }
589
590   worker->closed = FALSE;
591
592   return TRUE;
593 }
594
595
596 /**
597  * g_kdbus_free_data:
598  *
599  */
600 static gboolean
601 g_kdbus_free_data (GKDBusWorker      *kdbus,
602                    guint64      offset)
603 {
604   struct kdbus_cmd_free cmd = {
605     .size = sizeof(cmd),
606     .offset = offset,
607     .flags = 0
608   };
609   int ret;
610
611   ret = ioctl (kdbus->fd, KDBUS_CMD_FREE, &cmd);
612   if (ret < 0)
613     return FALSE;
614
615   return TRUE;
616 }
617
618
619 /**
620  * g_kdbus_translate_nameowner_flags:
621  *
622  */
623 static void
624 g_kdbus_translate_nameowner_flags (GBusNameOwnerFlags   flags,
625                                    guint64             *kdbus_flags)
626 {
627   guint64 new_flags;
628
629   new_flags = 0;
630
631   if (flags & G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT)
632     new_flags |= KDBUS_NAME_ALLOW_REPLACEMENT;
633
634   if (flags & G_BUS_NAME_OWNER_FLAGS_REPLACE)
635     new_flags |= KDBUS_NAME_REPLACE_EXISTING;
636
637   if (!(flags & G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE))
638     new_flags |= KDBUS_NAME_QUEUE;
639
640   *kdbus_flags = new_flags;
641 }
642
643
644 /**
645  * _g_kdbus_close:
646  *
647  */
648 void
649 _g_kdbus_close (GKDBusWorker *kdbus)
650 {
651   g_return_val_if_fail (G_IS_KDBUS_WORKER (kdbus), FALSE);
652
653   if (kdbus->closed)
654     return;
655
656   g_source_destroy (kdbus->source);
657   kdbus->source = 0;
658
659   g_main_context_unref (kdbus->context);
660   kdbus->context = NULL;
661
662   close (kdbus->fd);
663   kdbus->fd = -1;
664
665   kdbus->closed = TRUE;
666 }
667
668 /**
669  * _g_kdbus_is_closed:
670  *
671  */
672 gboolean
673 _g_kdbus_is_closed (GKDBusWorker  *kdbus)
674 {
675   g_return_val_if_fail (G_IS_KDBUS_WORKER (kdbus), FALSE);
676
677   return kdbus->closed;
678 }
679
680
681 /**
682  * _g_kdbus_Hello:
683  *
684  */
685 GVariant *
686 _g_kdbus_Hello (GKDBusWorker *worker,
687                 GError    **error)
688 {
689   struct kdbus_cmd_hello *cmd;
690   struct kdbus_bloom_parameter *bloom;
691   struct kdbus_item *item, *items;
692
693   gchar *conn_name;
694   size_t size, conn_name_size;
695
696   conn_name = "gdbus-kdbus";
697   conn_name_size = strlen (conn_name);
698
699   size = KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_cmd_hello, items)) +
700          KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, str) + conn_name_size + 1);
701
702   cmd = g_alloca0 (size);
703   cmd->flags = worker->flags;
704   cmd->attach_flags_send = worker->attach_flags_send;
705   cmd->attach_flags_recv = worker->attach_flags_recv;
706   cmd->size = size;
707   cmd->pool_size = KDBUS_POOL_SIZE;
708
709   item = cmd->items;
710   item->size = G_STRUCT_OFFSET (struct kdbus_item, str) + conn_name_size + 1;
711   item->type = KDBUS_ITEM_CONN_DESCRIPTION;
712   memcpy (item->str, conn_name, conn_name_size+1);
713   item = KDBUS_ITEM_NEXT (item);
714
715   if (ioctl(worker->fd, KDBUS_CMD_HELLO, cmd))
716     {
717       g_set_error (error, G_IO_ERROR,
718                    g_io_error_from_errno (errno),
719                    _("Failed to send HELLO: %s"),
720                    g_strerror (errno));
721       return NULL;
722     }
723
724   worker->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, worker->fd, 0);
725   if (worker->kdbus_buffer == MAP_FAILED)
726     {
727       g_set_error (error, G_IO_ERROR,
728                    g_io_error_from_errno (errno),
729                    _("mmap error: %s"),
730                    g_strerror (errno));
731       return NULL;
732     }
733
734   if (cmd->bus_flags > 0xFFFFFFFFULL)
735     {
736       g_set_error_literal (error,
737                            G_IO_ERROR,
738                            G_IO_ERROR_FAILED,
739                            _("Incompatible HELLO flags"));
740       return NULL;
741     }
742
743   memcpy (worker->bus_id, cmd->id128, 16);
744
745   worker->unique_id = cmd->id;
746   asprintf(&worker->unique_name, ":1.%llu", (unsigned long long) cmd->id);
747
748   /* read bloom filters parameters */
749   bloom = NULL;
750   items = (void*)(worker->kdbus_buffer + cmd->offset);
751   KDBUS_FOREACH(item, items, cmd->items_size)
752     {
753       switch (item->type)
754         {
755           case KDBUS_ITEM_BLOOM_PARAMETER:
756             bloom = &item->bloom_parameter;
757           break;
758         }
759     }
760
761   if (bloom != NULL)
762     {
763       worker->bloom_size = (gsize) bloom->size;
764       worker->bloom_n_hash = (guint) bloom->n_hash;
765     }
766   else
767     {
768       g_set_error_literal (error,
769                            G_IO_ERROR,
770                            G_IO_ERROR_FAILED,
771                            _("Can't read bloom filter parameters"));
772       return NULL;
773     }
774
775
776   return g_variant_new ("(s)", worker->unique_name);
777 }
778
779
780 /**
781  * _g_kdbus_RequestName:
782  *
783  */
784 GVariant *
785 _g_kdbus_RequestName (GKDBusWorker        *worker,
786                       const gchar         *name,
787                       GBusNameOwnerFlags   flags,
788                       GError             **error)
789 {
790   GVariant *result;
791   struct kdbus_cmd *cmd;
792   guint64 kdbus_flags;
793   gssize len, size;
794   gint status, ret;
795
796   status = G_BUS_REQUEST_NAME_FLAGS_PRIMARY_OWNER;
797
798   if (!g_dbus_is_name (name))
799     {
800       g_set_error (error,
801                    G_DBUS_ERROR,
802                    G_DBUS_ERROR_INVALID_ARGS,
803                    "Given bus name \"%s\" is not valid", name);
804       return NULL;
805     }
806
807   if (*name == ':')
808     {
809       g_set_error (error,
810                    G_DBUS_ERROR,
811                    G_DBUS_ERROR_INVALID_ARGS,
812                    "Cannot acquire a service starting with ':' such as \"%s\"", name);
813       return NULL;
814     }
815
816   g_kdbus_translate_nameowner_flags (flags, &kdbus_flags);
817
818   len = strlen(name) + 1;
819   size = G_STRUCT_OFFSET (struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(len);
820   cmd = g_alloca0 (size);
821   cmd->size = size;
822   cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
823   cmd->items[0].type = KDBUS_ITEM_NAME;
824   cmd->flags = kdbus_flags;
825   memcpy (cmd->items[0].str, name, len);
826
827   ret = ioctl(worker->fd, KDBUS_CMD_NAME_ACQUIRE, cmd);
828   if (ret < 0)
829     {
830       if (errno == EEXIST)
831         status = G_BUS_REQUEST_NAME_FLAGS_EXISTS;
832       else if (errno == EALREADY)
833         status = G_BUS_REQUEST_NAME_FLAGS_ALREADY_OWNER;
834       else
835         {
836           g_set_error (error, G_IO_ERROR,
837                        g_io_error_from_errno (errno),
838                        _("Error while acquiring name: %s"),
839                        g_strerror (errno));
840           return NULL;
841         }
842     }
843
844   if (cmd->return_flags & KDBUS_NAME_IN_QUEUE)
845     status = G_BUS_REQUEST_NAME_FLAGS_IN_QUEUE;
846
847   result = g_variant_new ("(u)", status);
848
849   return result;
850 }
851
852
853 /**
854  * _g_kdbus_ReleaseName:
855  *
856  */
857 GVariant *
858 _g_kdbus_ReleaseName (GKDBusWorker     *worker,
859                       const gchar         *name,
860                       GError             **error)
861 {
862   GVariant *result;
863   struct kdbus_cmd *cmd;
864   gssize len, size;
865   gint status, ret;
866
867   status = G_BUS_RELEASE_NAME_FLAGS_RELEASED;
868
869   if (!g_dbus_is_name (name))
870     {
871       g_set_error (error,
872                    G_DBUS_ERROR,
873                    G_DBUS_ERROR_INVALID_ARGS,
874                    "Given bus name \"%s\" is not valid", name);
875       return NULL;
876     }
877
878   if (*name == ':')
879     {
880       g_set_error (error,
881                    G_DBUS_ERROR,
882                    G_DBUS_ERROR_INVALID_ARGS,
883                    "Cannot release a service starting with ':' such as \"%s\"", name);
884       return NULL;
885     }
886
887   len = strlen(name) + 1;
888   size = G_STRUCT_OFFSET (struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(len);
889   cmd = g_alloca0 (size);
890   cmd->size = size;
891   cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
892   cmd->items[0].type = KDBUS_ITEM_NAME;
893   memcpy (cmd->items[0].str, name, len);
894
895   ret = ioctl(worker->fd, KDBUS_CMD_NAME_RELEASE, cmd);
896   if (ret < 0)
897     {
898       if (errno == ESRCH)
899         status = G_BUS_RELEASE_NAME_FLAGS_NON_EXISTENT;
900       else if (errno == EADDRINUSE)
901         status = G_BUS_RELEASE_NAME_FLAGS_NOT_OWNER;
902       else
903         {
904           g_set_error (error, G_IO_ERROR,
905                        g_io_error_from_errno (errno),
906                        _("Error while releasing name: %s"),
907                        g_strerror (errno));
908           return NULL;
909         }
910     }
911
912   result = g_variant_new ("(u)", status);
913
914   return result;
915 }
916
917
918 /**
919  * _g_kdbus_GetBusId:
920  *
921  */
922 GVariant *
923 _g_kdbus_GetBusId (GKDBusWorker  *worker,
924                    GError          **error)
925 {
926   GVariant *result;
927   GString  *result_str;
928   guint     cnt;
929
930   result_str = g_string_new (NULL);
931
932   for (cnt=0; cnt<16; cnt++)
933     g_string_append_printf (result_str, "%02x", worker->bus_id[cnt]);
934
935   result = g_variant_new ("(s)", result_str->str);
936   g_string_free (result_str, TRUE);
937
938   return result;
939 }
940
941
942 /**
943  * _g_kdbus_GetListNames:
944  *
945  */
946 GVariant *
947 _g_kdbus_GetListNames (GKDBusWorker  *worker,
948                        guint             list_name_type,
949                        GError          **error)
950 {
951   GVariant *result;
952   GVariantBuilder *builder;
953   struct kdbus_info *name_list, *name;
954   struct kdbus_cmd_list cmd = {
955     .size = sizeof(cmd)
956   };
957
958   guint64 prev_id;
959   gint ret;
960
961   prev_id = 0;
962
963   if (list_name_type)
964     cmd.flags = KDBUS_LIST_ACTIVATORS;                /* ListActivatableNames */
965   else
966     cmd.flags = KDBUS_LIST_UNIQUE | KDBUS_LIST_NAMES; /* ListNames */
967
968   ret = ioctl(worker->fd, KDBUS_CMD_LIST, &cmd);
969   if (ret < 0)
970     {
971       g_set_error (error,
972                    G_DBUS_ERROR,
973                    G_DBUS_ERROR_FAILED,
974                    _("Error listing names"));
975       return NULL;
976     }
977
978   name_list = (struct kdbus_info *) ((guint8 *) worker->kdbus_buffer + cmd.offset);
979   builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
980
981   KDBUS_FOREACH(name, name_list, cmd.list_size)
982     {
983       struct kdbus_item *item;
984       const gchar *item_name = "";
985
986       if ((cmd.flags & KDBUS_LIST_UNIQUE) && name->id != prev_id)
987         {
988           GString *unique_name;
989
990           unique_name = g_string_new (NULL);
991           g_string_printf (unique_name, ":1.%llu", name->id);
992           g_variant_builder_add (builder, "s", unique_name->str);
993           g_string_free (unique_name,TRUE);
994           prev_id = name->id;
995         }
996
997        KDBUS_ITEM_FOREACH(item, name, items)
998          if (item->type == KDBUS_ITEM_OWNED_NAME)
999            item_name = item->name.name;
1000
1001         if (g_dbus_is_name (item_name))
1002           g_variant_builder_add (builder, "s", item_name);
1003     }
1004
1005   result = g_variant_new ("(as)", builder);
1006   g_variant_builder_unref (builder);
1007
1008   g_kdbus_free_data (worker, cmd.offset);
1009   return result;
1010 }
1011
1012
1013 /**
1014  * _g_kdbus_NameHasOwner_internal:
1015  *
1016  */
1017 static gboolean
1018 g_kdbus_NameHasOwner_internal (GKDBusWorker       *worker,
1019                                const gchar  *name,
1020                                GError      **error)
1021 {
1022   struct kdbus_cmd_info *cmd;
1023   gssize size, len;
1024   gint ret;
1025
1026   if (g_dbus_is_unique_name(name))
1027     {
1028        size = G_STRUCT_OFFSET (struct kdbus_cmd_info, items);
1029        cmd = g_alloca0 (size);
1030        cmd->id = g_ascii_strtoull (name+3, NULL, 10);
1031     }
1032   else
1033     {
1034        len = strlen(name) + 1;
1035        size = G_STRUCT_OFFSET (struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(len);
1036        cmd = g_alloca0 (size);
1037        cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
1038        cmd->items[0].type = KDBUS_ITEM_NAME;
1039        memcpy (cmd->items[0].str, name, len);
1040     }
1041   cmd->size = size;
1042
1043   ret = ioctl(worker->fd, KDBUS_CMD_CONN_INFO, cmd);
1044   g_kdbus_free_data (worker, cmd->offset);
1045
1046   if (ret < 0)
1047     return FALSE;
1048   else
1049     return TRUE;
1050 }
1051
1052
1053 /**
1054  * _g_kdbus_GetListQueuedOwners:
1055  *
1056  */
1057 GVariant *
1058 _g_kdbus_GetListQueuedOwners (GKDBusWorker  *worker,
1059                               const gchar   *name,
1060                               GError       **error)
1061 {
1062   GVariant *result;
1063   GVariantBuilder *builder;
1064   GString *unique_name;
1065   gint ret;
1066
1067   struct kdbus_info *name_list, *kname;
1068   struct kdbus_cmd_list cmd = {
1069     .size = sizeof(cmd),
1070     .flags = KDBUS_LIST_QUEUED
1071   };
1072
1073   if (!g_dbus_is_name (name))
1074     {
1075       g_set_error (error,
1076                    G_DBUS_ERROR,
1077                    G_DBUS_ERROR_INVALID_ARGS,
1078                    "Given bus name \"%s\" is not valid", name);
1079       return NULL;
1080     }
1081
1082   if (!g_kdbus_NameHasOwner_internal (worker, name, error))
1083     {
1084       g_set_error (error,
1085                    G_DBUS_ERROR,
1086                    G_DBUS_ERROR_NAME_HAS_NO_OWNER,
1087                    "Could not get owner of name '%s': no such name", name);
1088       return NULL;
1089     }
1090
1091   ret = ioctl(worker->fd, KDBUS_CMD_LIST, &cmd);
1092   if (ret < 0)
1093     {
1094       g_set_error (error,
1095                    G_DBUS_ERROR,
1096                    G_DBUS_ERROR_FAILED,
1097                    _("Error listing names"));
1098       return NULL;
1099     }
1100
1101   name_list = (struct kdbus_info *) ((guint8 *) worker->kdbus_buffer + cmd.offset);
1102
1103   unique_name = g_string_new (NULL);
1104   builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
1105   KDBUS_FOREACH(kname, name_list, cmd.list_size)
1106     {
1107       struct kdbus_item *item;
1108       const char *item_name = "";
1109
1110       KDBUS_ITEM_FOREACH(item, kname, items)
1111         if (item->type == KDBUS_ITEM_NAME)
1112           item_name = item->str;
1113
1114       if (strcmp(item_name, name))
1115         continue;
1116
1117       g_string_printf (unique_name, ":1.%llu", kname->id);
1118       g_variant_builder_add (builder, "s", item_name);
1119     }
1120
1121   result = g_variant_new ("(as)", builder);
1122   g_variant_builder_unref (builder);
1123   g_string_free (unique_name,TRUE);
1124
1125   g_kdbus_free_data (worker, cmd.offset);
1126   return result;
1127 }
1128
1129
1130 /**
1131  * g_kdbus_GetConnInfo_internal:
1132  *
1133  */
1134 static GVariant *
1135 g_kdbus_GetConnInfo_internal (GKDBusWorker  *worker,
1136                               const gchar      *name,
1137                               guint64           flag,
1138                               GError          **error)
1139 {
1140   GVariant *result;
1141
1142   struct kdbus_cmd_info *cmd;
1143   struct kdbus_info *conn_info;
1144   struct kdbus_item *item;
1145   gssize size, len;
1146   gint ret;
1147
1148   result = NULL;
1149
1150   if (!g_dbus_is_name (name))
1151     {
1152       g_set_error (error,
1153                    G_DBUS_ERROR,
1154                    G_DBUS_ERROR_INVALID_ARGS,
1155                    "Given bus name \"%s\" is not valid", name);
1156       return NULL;
1157     }
1158
1159   if (!g_kdbus_NameHasOwner_internal (worker, name, error))
1160     {
1161       g_set_error (error,
1162                    G_DBUS_ERROR,
1163                    G_DBUS_ERROR_NAME_HAS_NO_OWNER,
1164                    "Could not get owner of name '%s': no such name", name);
1165       return NULL;
1166     }
1167
1168   if (g_dbus_is_unique_name(name))
1169     {
1170        size = G_STRUCT_OFFSET (struct kdbus_cmd_info, items);
1171        cmd = g_alloca0 (size);
1172        cmd->id = g_ascii_strtoull (name+3, NULL, 10);
1173     }
1174   else
1175     {
1176        len = strlen(name) + 1;
1177        size = G_STRUCT_OFFSET (struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(len);
1178        cmd = g_alloca0 (size);
1179        cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
1180        cmd->items[0].type = KDBUS_ITEM_NAME;
1181        memcpy (cmd->items[0].str, name, len);
1182     }
1183
1184   cmd->attach_flags = _KDBUS_ATTACH_ALL;
1185   cmd->size = size;
1186
1187   ret = ioctl(worker->fd, KDBUS_CMD_CONN_INFO, cmd);
1188   if (ret < 0)
1189     {
1190       g_set_error (error,
1191                    G_DBUS_ERROR,
1192                    G_DBUS_ERROR_FAILED,
1193                    _("Could not get connection info"));
1194       return NULL;
1195     }
1196
1197   conn_info = (struct kdbus_info *) ((guint8 *) worker->kdbus_buffer + cmd->offset);
1198
1199   /*
1200   if (conn_info->flags & KDBUS_HELLO_ACTIVATOR)
1201     {}
1202   */
1203
1204   if (flag == G_BUS_CREDS_UNIQUE_NAME)
1205     {
1206        GString *unique_name;
1207
1208        unique_name = g_string_new (NULL);
1209        g_string_printf (unique_name, ":1.%llu", (unsigned long long) conn_info->id);
1210        result = g_variant_new ("(s)", unique_name->str);
1211        g_string_free (unique_name,TRUE);
1212        goto exit;
1213     }
1214
1215   KDBUS_ITEM_FOREACH(item, conn_info, items)
1216    {
1217       switch (item->type)
1218         {
1219           case KDBUS_ITEM_PIDS:
1220
1221             if (flag == G_BUS_CREDS_PID)
1222               {
1223                 guint pid = item->pids.pid;
1224                 result = g_variant_new ("(u)", pid);
1225                 goto exit;
1226               }
1227
1228           case KDBUS_ITEM_CREDS:
1229
1230             if (flag == G_BUS_CREDS_UID)
1231               {
1232                 guint uid = item->creds.uid;
1233                 result = g_variant_new ("(u)", uid);
1234                 goto exit;
1235               }
1236
1237           case KDBUS_ITEM_SECLABEL:
1238           case KDBUS_ITEM_PID_COMM:
1239           case KDBUS_ITEM_TID_COMM:
1240           case KDBUS_ITEM_EXE:
1241           case KDBUS_ITEM_CMDLINE:
1242           case KDBUS_ITEM_CGROUP:
1243           case KDBUS_ITEM_CAPS:
1244           case KDBUS_ITEM_AUDIT:
1245           case KDBUS_ITEM_CONN_DESCRIPTION:
1246           case KDBUS_ITEM_AUXGROUPS:
1247           case KDBUS_ITEM_OWNED_NAME:
1248             break;
1249         }
1250    }
1251
1252 exit:
1253   g_kdbus_free_data (worker, cmd->offset);
1254   return result;
1255 }
1256
1257
1258 /**
1259  * _g_kdbus_GetNameOwner:
1260  *
1261  */
1262 GVariant *
1263 _g_kdbus_GetNameOwner (GKDBusWorker  *worker,
1264                        const gchar      *name,
1265                        GError          **error)
1266 {
1267   return g_kdbus_GetConnInfo_internal (worker,
1268                                        name,
1269                                        G_BUS_CREDS_UNIQUE_NAME,
1270                                        error);
1271 }
1272
1273
1274 /**
1275  * _g_kdbus_GetConnectionUnixProcessID:
1276  *
1277  */
1278 GVariant *
1279 _g_kdbus_GetConnectionUnixProcessID (GKDBusWorker  *worker,
1280                                      const gchar      *name,
1281                                      GError          **error)
1282 {
1283   return g_kdbus_GetConnInfo_internal (worker,
1284                                        name,
1285                                        G_BUS_CREDS_PID,
1286                                        error);
1287 }
1288
1289
1290 /**
1291  * _g_kdbus_GetConnectionUnixUser:
1292  *
1293  */
1294 GVariant *
1295 _g_kdbus_GetConnectionUnixUser (GKDBusWorker  *worker,
1296                                 const gchar      *name,
1297                                 GError          **error)
1298 {
1299   return g_kdbus_GetConnInfo_internal (worker,
1300                                        name,
1301                                        G_BUS_CREDS_UID,
1302                                        error);
1303 }
1304
1305
1306 /**
1307  * g_kdbus_bloom_add_data:
1308  * Based on bus-bloom.c from systemd
1309  * http://cgit.freedesktop.org/systemd/systemd/tree/src/libsystemd/sd-bus/bus-bloom.c
1310  */
1311 static void
1312 g_kdbus_bloom_add_data (GKDBusWorker  *worker,
1313                         guint64        bloom_data [],
1314                         const void    *data,
1315                         gsize          n)
1316 {
1317   guint8 hash[8];
1318   guint64 bit_num;
1319   guint bytes_num = 0;
1320   guint cnt_1, cnt_2;
1321   guint hash_index = 0;
1322
1323   guint c = 0;
1324   guint64 p = 0;
1325
1326   bit_num = worker->bloom_size * 8;
1327
1328   if (bit_num > 1)
1329     bytes_num = ((__builtin_clzll(bit_num) ^ 63U) + 7) / 8;
1330
1331   for (cnt_1 = 0; cnt_1 < (worker->bloom_n_hash); cnt_1++)
1332     {
1333       for (cnt_2 = 0, hash_index = 0; cnt_2 < bytes_num; cnt_2++)
1334         {
1335           if (c <= 0)
1336             {
1337               _g_siphash24(hash, data, n, hash_keys[hash_index++]);
1338               c += 8;
1339             }
1340
1341           p = (p << 8ULL) | (guint64) hash[8 - c];
1342           c--;
1343         }
1344
1345       p &= bit_num - 1;
1346       bloom_data[p >> 6] |= 1ULL << (p & 63);
1347     }
1348 }
1349
1350
1351 /**
1352  * g_kdbus_bloom_add_pair:
1353  *
1354  */
1355 static void
1356 g_kdbus_bloom_add_pair (GKDBusWorker  *worker,
1357                         guint64        bloom_data [],
1358                         const gchar   *parameter,
1359                         const gchar   *value)
1360 {
1361   gchar buf[1024];
1362   gsize size;
1363
1364   size = strlen(parameter) + strlen(value) + 1;
1365   if (size > 1024)
1366     return;
1367
1368   strcpy(stpcpy(stpcpy(buf, parameter), ":"), value);
1369   g_kdbus_bloom_add_data(worker, bloom_data, buf, size);
1370 }
1371
1372
1373 /**
1374  * g_kdbus_bloom_add_prefixes:
1375  *
1376  */
1377 static void
1378 g_kdbus_bloom_add_prefixes (GKDBusWorker  *worker,
1379                             guint64        bloom_data [],
1380                             const gchar   *parameter,
1381                             const gchar   *value,
1382                             gchar          separator)
1383 {
1384   gchar buf[1024];
1385   gsize size;
1386
1387   size = strlen(parameter) + strlen(value) + 1;
1388   if (size > 1024)
1389     return;
1390
1391   strcpy(stpcpy(stpcpy(buf, parameter), ":"), value);
1392
1393   for (;;)
1394     {
1395       gchar *last_sep;
1396       last_sep = strrchr(buf, separator);
1397       if (!last_sep || last_sep == buf)
1398         break;
1399
1400       *last_sep = 0;
1401       g_kdbus_bloom_add_data(worker, bloom_data, buf, last_sep-buf);
1402     }
1403 }
1404
1405
1406 /**
1407  * _g_kdbus_AddMatch:
1408  *
1409  */
1410 void
1411 _g_kdbus_AddMatch (GKDBusWorker  *worker,
1412                    const gchar   *match_rule,
1413                    guint64        cookie)
1414 {
1415   Match *match;
1416   MatchElement *element;
1417   const gchar *sender_name;
1418   gsize sender_len, size;
1419   struct kdbus_cmd_match *cmd;
1420   struct kdbus_item *item;
1421   guint64 *bloom;
1422   guint64 src_id;
1423   gchar *type;
1424   gint cnt, ret;
1425
1426   if (match_rule[0] == '-')
1427     return;
1428
1429   match = match_new (match_rule);
1430   if (!match)
1431     {
1432       match_free (match);
1433       return;
1434     }
1435
1436   sender_name = NULL;
1437   src_id = KDBUS_MATCH_ID_ANY;
1438
1439   bloom = g_alloca0 (worker->bloom_size);
1440   size = KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_cmd_match, items));
1441   match = match_new (match_rule);
1442
1443   for (cnt = 0; cnt < match->n_elements; cnt++)
1444     {
1445       element = &match->elements[cnt];
1446       switch (element->type)
1447         {
1448           case MATCH_ELEMENT_SENDER:
1449             if (g_dbus_is_unique_name(element->value))
1450               {
1451                 src_id = g_ascii_strtoull ((element->value)+3, NULL, 10);
1452                 size += KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, id) + sizeof(src_id));
1453               }
1454             else if (g_dbus_is_name (element->value))
1455               {
1456                 sender_name = element->value;
1457                 sender_len = strlen(element->value) + 1;
1458                 size += KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, str) + sender_len);
1459               }
1460             else
1461               {
1462                 g_critical ("Error while adding a match");
1463                 match_free (match);
1464                 return;
1465               }
1466             break;
1467
1468           case MATCH_ELEMENT_TYPE:
1469             g_kdbus_bloom_add_pair (worker, bloom, "message-type", element->value);
1470             break;
1471
1472           case MATCH_ELEMENT_INTERFACE:
1473             g_kdbus_bloom_add_pair (worker, bloom, "interface", element->value);
1474             break;
1475
1476           case MATCH_ELEMENT_MEMBER:
1477             g_kdbus_bloom_add_pair (worker, bloom, "member", element->value);
1478             break;
1479
1480           case MATCH_ELEMENT_PATH:
1481             g_kdbus_bloom_add_pair (worker, bloom, "path", element->value);
1482             break;
1483
1484           case MATCH_ELEMENT_PATH_NAMESPACE:
1485             if (g_strcmp0 (element->value, "/"))
1486               g_kdbus_bloom_add_pair (worker, bloom, "path-slash-prefix", element->value);
1487             break;
1488
1489           case MATCH_ELEMENT_ARGN:
1490             asprintf (&type, "arg%u", element->arg);
1491             g_kdbus_bloom_add_pair (worker, bloom, type, element->value);
1492             free (type);
1493             break;
1494
1495           case MATCH_ELEMENT_ARGNPATH:
1496             asprintf (&type, "arg%u-slash-prefix", element->arg);
1497             g_kdbus_bloom_add_pair (worker, bloom, type, element->value);
1498             free (type);
1499             break;
1500
1501           case MATCH_ELEMENT_ARG0NAMESPACE:
1502             g_kdbus_bloom_add_pair (worker, bloom, "arg0-dot-prefix", element->value);
1503             break;
1504
1505           case MATCH_ELEMENT_DESTINATION:
1506           case MATCH_ELEMENT_EAVESDROP:
1507             break;
1508         }
1509     }
1510
1511   size += KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, data64) + worker->bloom_size);
1512   cmd = g_alloca0 (size);
1513   cmd->size = size;
1514   cmd->cookie = cookie;
1515
1516   item = cmd->items;
1517   item->size = G_STRUCT_OFFSET(struct kdbus_item, data64) + worker->bloom_size;
1518   item->type = KDBUS_ITEM_BLOOM_MASK;
1519   memcpy(item->data64, bloom, worker->bloom_size);
1520   item = KDBUS_ITEM_NEXT(item);
1521
1522   if (src_id != KDBUS_MATCH_ID_ANY)
1523     {
1524       item->size = G_STRUCT_OFFSET (struct kdbus_item, id) + sizeof(src_id);
1525       item->type = KDBUS_ITEM_ID;
1526       item->id = src_id;
1527       item = KDBUS_ITEM_NEXT(item);
1528     }
1529
1530   if (sender_name)
1531     {
1532       item->size = G_STRUCT_OFFSET (struct kdbus_item, str) + sender_len;
1533       item->type = KDBUS_ITEM_NAME;
1534       memcpy (item->str, sender_name, sender_len);
1535     }
1536
1537   ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1538   if (ret < 0)
1539     g_warning ("Error while adding a match: %d", (int) errno);
1540
1541   match_free (match);
1542 }
1543
1544
1545 /**
1546  * _g_kdbus_RemoveMatch:
1547  *
1548  */
1549 void
1550 _g_kdbus_RemoveMatch (GKDBusWorker  *worker,
1551                       guint64        cookie)
1552 {
1553   struct kdbus_cmd_match cmd = {
1554     .size = sizeof(cmd),
1555     .cookie = cookie
1556   };
1557   gint ret;
1558
1559   g_print ("Unsubscribe match entry with cookie - %d\n", (int)cookie);
1560
1561   ret = ioctl(worker->fd, KDBUS_CMD_MATCH_REMOVE, &cmd);
1562   if (ret < 0)
1563     {
1564       g_warning ("Error while removing a match: %d\n", errno);
1565       return;
1566     }
1567 }
1568
1569
1570 /**
1571  * _g_kdbus_subscribe_name_owner_changed_internal:
1572  *
1573  */
1574 static void
1575 _g_kdbus_subscribe_name_owner_changed_internal (GKDBusWorker  *worker,
1576                                                 const gchar   *name,
1577                                                 const gchar   *old_name,
1578                                                 const gchar   *new_name,
1579                                                 guint64        cookie)
1580 {
1581   struct kdbus_item *item;
1582   struct kdbus_cmd_match *cmd;
1583   gssize size, len;
1584   gint ret;
1585   guint64 old_id = 0;
1586   guint64 new_id = KDBUS_MATCH_ID_ANY;
1587
1588   if (name)
1589     len = strlen(name) + 1;
1590   else
1591     len = 0;
1592
1593   size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
1594                       G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1595                       G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
1596
1597   cmd = g_alloca0 (size);
1598   cmd->size = size;
1599   cmd->cookie = cookie;
1600   item = cmd->items;
1601
1602   if (old_name == NULL)
1603     {
1604       old_id = KDBUS_MATCH_ID_ANY;
1605     }
1606   else
1607     {
1608       if (g_dbus_is_unique_name(old_name))
1609         old_id = strtoull (old_name + 3, NULL, 10);
1610       else
1611         return;
1612     }
1613
1614   if (new_name == NULL)
1615     {
1616       new_id = KDBUS_MATCH_ID_ANY;
1617     }
1618   else
1619     {
1620       if (g_dbus_is_unique_name(new_name))
1621         new_id = strtoull (new_name + 3, NULL, 10);
1622       else
1623         return;
1624     }
1625
1626   cmd = g_alloca0 (size);
1627   cmd->size = size;
1628   cmd->cookie = cookie;
1629   item = cmd->items;
1630
1631   item->type = KDBUS_ITEM_NAME_CHANGE;
1632   item->name_change.old_id.id = old_id;
1633   item->name_change.new_id.id = new_id;
1634
1635   if (name)
1636     memcpy(item->name_change.name, name, len);
1637
1638   item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1639                G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len;
1640   item = KDBUS_ITEM_NEXT(item);
1641
1642   ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1643   if (ret < 0)
1644     {
1645       g_warning ("ERROR - %d\n", (int) errno);
1646       return;
1647     }
1648 }
1649
1650
1651 /**
1652  * _g_kdbus_subscribe_name_acquired:
1653  *
1654  */
1655 void
1656 _g_kdbus_subscribe_name_acquired (GKDBusWorker  *worker,
1657                                   const gchar   *name,
1658                                   guint64        cookie)
1659 {
1660   struct kdbus_item *item;
1661   struct kdbus_cmd_match *cmd;
1662   gssize size, len;
1663   gint ret;
1664
1665   g_print ("Subscribe 'NameAcquired': name - %s ; cookie - %d\n", name, (int)cookie);
1666
1667   if (name)
1668     len = strlen(name) + 1;
1669   else
1670     len = 0;
1671
1672   size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
1673                       G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1674                       G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
1675
1676   cmd = g_alloca0 (size);
1677   cmd->size = size;
1678   cmd->cookie = cookie;
1679   item = cmd->items;
1680
1681   item->type = KDBUS_ITEM_NAME_ADD;
1682   item->name_change.old_id.id = KDBUS_MATCH_ID_ANY;
1683   item->name_change.new_id.id = worker->unique_id;
1684
1685   if (name)
1686     memcpy(item->name_change.name, name, len);
1687
1688   item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1689                G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len;
1690   item = KDBUS_ITEM_NEXT(item);
1691
1692   ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1693   if (ret < 0)
1694     {
1695       g_warning ("ERROR - %d\n", (int) errno);
1696       return;
1697     }
1698
1699   _g_kdbus_subscribe_name_owner_changed_internal (worker, name, NULL, worker->unique_name, cookie);
1700 }
1701
1702
1703 /**
1704  * _g_kdbus_subscribe_name_lost:
1705  *
1706  */
1707 void
1708 _g_kdbus_subscribe_name_lost (GKDBusWorker  *worker,
1709                               const gchar   *name,
1710                               guint64        cookie)
1711 {
1712   struct kdbus_item *item;
1713   struct kdbus_cmd_match *cmd;
1714   gssize size, len;
1715   gint ret;
1716
1717   g_print ("Subscribe 'NameLost': name - %s ; cookie - %d\n", name, (int)cookie);
1718
1719   if (name)
1720     len = strlen(name) + 1;
1721   else
1722     len = 0;
1723
1724   size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
1725                       G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1726                       G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
1727
1728   cmd = g_alloca0 (size);
1729   cmd->size = size;
1730   cmd->cookie = cookie;
1731   item = cmd->items;
1732
1733   item->type = KDBUS_ITEM_NAME_REMOVE;
1734   item->name_change.old_id.id = worker->unique_id;
1735   item->name_change.new_id.id = KDBUS_MATCH_ID_ANY;
1736
1737   if (name)
1738     memcpy(item->name_change.name, name, len);
1739
1740   item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1741                G_STRUCT_OFFSET(struct kdbus_notify_name_change, name) + len;
1742   item = KDBUS_ITEM_NEXT(item);
1743
1744   ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1745   if (ret < 0)
1746     {
1747       g_warning ("ERROR - %d\n", (int) errno);
1748       return;
1749     }
1750
1751   _g_kdbus_subscribe_name_owner_changed_internal (worker, name, worker->unique_name, NULL, cookie);
1752 }
1753
1754
1755 /**
1756  * _g_kdbus_subscribe_name_owner_changed:
1757  *
1758  */
1759 void
1760 _g_kdbus_subscribe_name_owner_changed (GKDBusWorker  *worker,
1761                                        const gchar   *name,
1762                                        guint64        cookie)
1763 {
1764   struct kdbus_item *item;
1765   struct kdbus_cmd_match *cmd;
1766   gssize size, len;
1767   gint ret;
1768
1769   if (name != NULL)
1770     if (!g_dbus_is_name (name))
1771       {
1772         g_warning ("ERROR\n");
1773         return;
1774       }
1775
1776   g_print ("Subscribe 'NameOwnerChanged': name - %s ; cookie - %d\n", name, (int)cookie);
1777
1778   /* 'name' argument is missing or is a unique name */
1779   if (name == NULL || g_dbus_is_unique_name (name))
1780     {
1781       size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
1782                           G_STRUCT_OFFSET (struct kdbus_item, id_change) +
1783                           sizeof (struct kdbus_notify_id_change));
1784
1785       cmd = g_alloca0 (size);
1786       cmd->size = size;
1787       cmd->cookie = cookie;
1788       item = cmd->items;
1789
1790       if (name)
1791         item->id_change.id = strtoull (name + 3, NULL, 10);
1792       else
1793         item->id_change.id = KDBUS_MATCH_ID_ANY;
1794
1795       item->size = G_STRUCT_OFFSET (struct kdbus_item, id_change) +
1796                    sizeof (struct kdbus_notify_id_change);
1797
1798       item->type = KDBUS_ITEM_ID_ADD;
1799       ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1800       if (ret < 0)
1801         {
1802           g_warning ("ERROR - %d\n", (int) errno);
1803           return;
1804         }
1805
1806       item->type = KDBUS_ITEM_ID_REMOVE;
1807       ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1808       if (ret < 0)
1809         {
1810           g_warning ("ERROR - %d\n", (int) errno);
1811           return;
1812         }
1813     }
1814
1815   /* 'name' argument is missing or is a well-known name */
1816   if (name == NULL || !g_dbus_is_unique_name (name))
1817     {
1818       if (name)
1819         len = strlen(name) + 1;
1820       else
1821         len = 0;
1822
1823       size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
1824                           G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1825                           G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
1826
1827       cmd = g_alloca0 (size);
1828       cmd->size = size;
1829       cmd->cookie = cookie;
1830       item = cmd->items;
1831
1832       item->name_change.old_id.id = KDBUS_MATCH_ID_ANY;
1833       item->name_change.new_id.id = KDBUS_MATCH_ID_ANY;
1834       item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1835                    G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len;
1836
1837       if (name)
1838         memcpy(item->name_change.name, name, len);
1839
1840       item->type = KDBUS_ITEM_NAME_ADD;
1841       ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1842       if (ret < 0)
1843         {
1844           g_warning ("ERROR - %d\n", (int) errno);
1845           return;
1846         }
1847
1848       item->type = KDBUS_ITEM_NAME_REMOVE;
1849       ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1850       if (ret < 0)
1851         {
1852           g_warning ("ERROR - %d\n", (int) errno);
1853           return;
1854         }
1855
1856       item->type = KDBUS_ITEM_NAME_CHANGE;
1857       ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1858       if (ret < 0)
1859         {
1860           g_warning ("ERROR - %d\n", (int) errno);
1861           return;
1862         }
1863     }
1864 }
1865
1866
1867 /**
1868  * g_kdbus_setup_bloom:
1869  * Based on bus-bloom.c from systemd
1870  * http://cgit.freedesktop.org/systemd/systemd/tree/src/libsystemd/sd-bus/bus-bloom.c
1871  */
1872 static void
1873 g_kdbus_setup_bloom (GKDBusWorker                     *worker,
1874                      GDBusMessage               *dbus_msg,
1875                      struct kdbus_bloom_filter  *bloom_filter)
1876 {
1877   GVariant *body;
1878
1879   const gchar *message_type;
1880   const gchar *interface;
1881   const gchar *member;
1882   const gchar *path;
1883
1884   void *bloom_data;
1885
1886   body = g_dbus_message_get_body (dbus_msg);
1887   message_type = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, g_dbus_message_get_message_type (dbus_msg));
1888   interface = g_dbus_message_get_interface (dbus_msg);
1889   member = g_dbus_message_get_member (dbus_msg);
1890   path = g_dbus_message_get_path (dbus_msg);
1891
1892   bloom_data = bloom_filter->data;
1893   memset (bloom_data, 0, worker->bloom_size);
1894   bloom_filter->generation = 0;
1895
1896   g_kdbus_bloom_add_pair(worker, bloom_data, "message-type", message_type);
1897
1898   if (interface)
1899     g_kdbus_bloom_add_pair(worker, bloom_data, "interface", interface);
1900
1901   if (member)
1902     g_kdbus_bloom_add_pair(worker, bloom_data, "member", member);
1903
1904   if (path)
1905     {
1906       g_kdbus_bloom_add_pair(worker, bloom_data, "path", path);
1907       g_kdbus_bloom_add_pair(worker, bloom_data, "path-slash-prefix", path);
1908       g_kdbus_bloom_add_prefixes(worker, bloom_data, "path-slash-prefix", path, '/');
1909     }
1910
1911   if (body != NULL)
1912     {
1913       const GVariantType *body_type;
1914       const GVariantType *arg_type;
1915       guint cnt;
1916
1917       body_type = g_variant_get_type (body);
1918
1919       for (arg_type = g_variant_type_first (body_type), cnt = 0;
1920            arg_type;
1921            arg_type = g_variant_type_next (arg_type), cnt++)
1922         {
1923           gchar type_char = g_variant_type_peek_string (arg_type)[0];
1924           gchar buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1925           const gchar *str;
1926           GVariant *child;
1927           gchar *e;
1928
1929           if (type_char != 's' && type_char != 'o')
1930             /* XXX: kdbus docs say "stop after first non-string" but I
1931              * think they're wrong (vs. dbus-1 compat)...
1932              */
1933             continue;
1934
1935           child = g_variant_get_child_value (body, cnt);
1936           str = g_variant_get_string (child, NULL);
1937
1938           e = stpcpy(buf, "arg");
1939           if (cnt < 10)
1940             *(e++) = '0' + (char) cnt;
1941           else
1942             {
1943               *(e++) = '0' + (char) (cnt / 10);
1944               *(e++) = '0' + (char) (cnt % 10);
1945             }
1946
1947           /* We add this one for both strings and object paths */
1948           strcpy(e, "-slash-prefix");
1949           g_kdbus_bloom_add_prefixes(worker, bloom_data, buf, str, '/');
1950
1951           /* But the others are only for strings */
1952           if (type_char == 's')
1953             {
1954               strcpy(e, "-dot-prefix");
1955               g_kdbus_bloom_add_prefixes(worker, bloom_data, buf, str, '.');
1956
1957               *e = 0;
1958               g_kdbus_bloom_add_pair(worker, bloom_data, buf, str);
1959             }
1960
1961           g_variant_unref (child);
1962         }
1963     }
1964 }
1965
1966
1967 /**
1968  * g_kdbus_translate_id_change:
1969  *
1970  */
1971 static void
1972 g_kdbus_translate_id_change (GKDBusWorker       *worker,
1973                              struct kdbus_item  *item)
1974 {
1975   GDBusMessage *signal_message;
1976   gchar *name;
1977
1978   signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
1979                                               "org.freedesktop.DBus",
1980                                               "NameOwnerChanged");
1981
1982   name = g_strdup_printf (":1.%"G_GUINT64_FORMAT, (guint64) item->id_change.id);
1983
1984   g_dbus_message_set_sender (signal_message, "org.freedesktop.DBus");
1985   g_dbus_message_set_body (signal_message,
1986                            g_variant_new ("(sss)",
1987                                           name,
1988                                           item->type == KDBUS_ITEM_ID_ADD ? "" : name,
1989                                           item->type == KDBUS_ITEM_ID_ADD ? name : ""));
1990
1991   (* worker->message_received_callback) (signal_message, worker->user_data);
1992
1993   g_free (name);
1994   g_object_unref (signal_message);
1995 }
1996
1997
1998 /**
1999  * g_kdbus_translate_name_change:
2000  *
2001  */
2002 static void
2003 g_kdbus_translate_name_change (GKDBusWorker       *worker,
2004                                struct kdbus_item  *item)
2005 {
2006   GDBusMessage *signal_message;
2007
2008   signal_message = NULL;
2009
2010   /* NameAcquired */
2011   if ((item->type == KDBUS_ITEM_NAME_ADD) ||
2012       (item->type == KDBUS_ITEM_NAME_CHANGE && ((guint64)item->name_change.new_id.id == worker->unique_id)))
2013     {
2014       signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
2015                                                   "org.freedesktop.DBus",
2016                                                   "NameAcquired");
2017
2018       g_dbus_message_set_sender (signal_message, "org.freedesktop.DBus");
2019       g_dbus_message_set_body (signal_message,
2020                                g_variant_new ("(s)", item->name_change.name));
2021
2022       (* worker->message_received_callback) (signal_message, worker->user_data);
2023       g_object_unref (signal_message);
2024     }
2025
2026   /* NameLost */
2027   if ((item->type == KDBUS_ITEM_NAME_REMOVE) ||
2028       (item->type == KDBUS_ITEM_NAME_CHANGE && ((guint64)item->name_change.old_id.id == worker->unique_id)))
2029     {
2030       signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
2031                                                   "org.freedesktop.DBus",
2032                                                   "NameLost");
2033
2034       g_dbus_message_set_sender (signal_message, "org.freedesktop.DBus");
2035       g_dbus_message_set_body (signal_message,
2036                                g_variant_new ("(s)", item->name_change.name));
2037
2038       (* worker->message_received_callback) (signal_message, worker->user_data);
2039       g_object_unref (signal_message);
2040     }
2041
2042   /* NameOwnerChanged */
2043   if (1)
2044     {
2045       gchar *old_name;
2046       gchar *new_name;
2047
2048       old_name = NULL;
2049       new_name = NULL;
2050
2051       /* old_name */
2052       if (!(item->type == KDBUS_ITEM_NAME_ADD || (item->name_change.old_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))))
2053         old_name = g_strdup_printf (":1.%"G_GUINT64_FORMAT, (guint64) item->name_change.old_id.id);
2054
2055       /* new_name */
2056       if (!(item->type == KDBUS_ITEM_NAME_REMOVE || (item->name_change.new_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))))
2057         new_name = g_strdup_printf (":1.%"G_GUINT64_FORMAT, (guint64) item->name_change.new_id.id);
2058       else
2059         if (old_name == NULL)
2060           return;
2061
2062       /* send signal */
2063       signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
2064                                                   "org.freedesktop.DBus",
2065                                                   "NameOwnerChanged");
2066       g_dbus_message_set_sender (signal_message, "org.freedesktop.DBus");
2067       g_dbus_message_set_body (signal_message,
2068                                g_variant_new ("(sss)",
2069                                               item->name_change.name,
2070                                               old_name ? old_name : "",
2071                                               new_name ? new_name : ""));
2072
2073       (* worker->message_received_callback) (signal_message, worker->user_data);
2074
2075       g_free (old_name);
2076       g_free (new_name);
2077       g_object_unref (signal_message);
2078     }
2079 }
2080
2081
2082 /**
2083  *
2084  *
2085  */
2086 static void
2087 g_kdbus_translate_kernel_reply (GKDBusWorker       *worker,
2088                                 struct kdbus_item  *item)
2089 {
2090   g_error ("TODO: translate_kernel_reply\n");
2091 }
2092
2093
2094 /**
2095  * g_kdbus_decode_kernel_msg:
2096  *
2097  */
2098 static void
2099 g_kdbus_decode_kernel_msg (GKDBusWorker           *worker,
2100                            struct kdbus_msg *msg)
2101 {
2102   struct kdbus_item *item = NULL;
2103
2104   KDBUS_ITEM_FOREACH(item, msg, items)
2105     {
2106      switch (item->type)
2107         {
2108           case KDBUS_ITEM_ID_ADD:
2109           case KDBUS_ITEM_ID_REMOVE:
2110             g_kdbus_translate_id_change (worker, item);
2111             break;
2112
2113           case KDBUS_ITEM_NAME_ADD:
2114           case KDBUS_ITEM_NAME_REMOVE:
2115           case KDBUS_ITEM_NAME_CHANGE:
2116             g_kdbus_translate_name_change (worker, item);
2117             break;
2118
2119           case KDBUS_ITEM_REPLY_TIMEOUT:
2120           case KDBUS_ITEM_REPLY_DEAD:
2121             g_kdbus_translate_kernel_reply (worker, item);
2122             break;
2123
2124           case KDBUS_ITEM_TIMESTAMP:
2125             break;
2126
2127           default:
2128             g_warning ("Unknown field in kernel message - %lld", item->type);
2129        }
2130     }
2131 }
2132
2133
2134 /**
2135  * g_kdbus_decode_dbus_msg:
2136  *
2137  */
2138 static GDBusMessage *
2139 g_kdbus_decode_dbus_msg (GKDBusWorker           *worker,
2140                          struct kdbus_msg *msg)
2141 {
2142   GDBusMessage *message;
2143   struct kdbus_item *item;
2144   gssize data_size = 0;
2145   GArray *body_vectors;
2146   gsize body_size;
2147   GVariant *body;
2148   gchar *tmp;
2149   guint i;
2150   GVariant *parts[2];
2151   GVariantIter *fields_iter;
2152   guint8 endianness, type, flags, version;
2153   guint64 key;
2154   GVariant *value;
2155   guint64 serial;
2156
2157   message = g_dbus_message_new ();
2158
2159   body_vectors = g_array_new (FALSE, FALSE, sizeof (GVariantVector));
2160
2161   tmp = g_strdup_printf (":1.%"G_GUINT64_FORMAT, (guint64) msg->src_id);
2162   g_dbus_message_set_sender (message, tmp);
2163   g_free (tmp);
2164
2165   item = msg->items;
2166   body_size = 0;
2167
2168   KDBUS_ITEM_FOREACH(item, msg, items)
2169     {
2170       if (item->size <= KDBUS_ITEM_HEADER_SIZE)
2171         g_error("[KDBUS] %llu bytes - invalid data record\n", item->size);
2172
2173       data_size = item->size - KDBUS_ITEM_HEADER_SIZE;
2174
2175       switch (item->type)
2176         {
2177          /* KDBUS_ITEM_DST_NAME */
2178          case KDBUS_ITEM_DST_NAME:
2179            /* Classic D-Bus doesn't make this known to the receiver, so
2180             * we don't do it here either (for compatibility with the
2181             * fallback case).
2182             */
2183            break;
2184
2185         /* KDBUS_ITEM_PALOAD_OFF */
2186         case KDBUS_ITEM_PAYLOAD_OFF:
2187           {
2188             GVariantVector vector;
2189             gsize flavour;
2190
2191             /* We want to make sure the bytes are aligned the same as
2192              * they would be if they appeared in a contiguously
2193              * allocated chunk of aligned memory.
2194              *
2195              * We decide what the alignment 'should' be by consulting
2196              * body_size, which has been tracking the total size of the
2197              * message up to this point.
2198              *
2199              * We then play around with the pointer by removing as many
2200              * bytes as required to get it to the proper alignment (and
2201              * copy extra bytes accordingly).  This means that we will
2202              * grab some extra data in the 'bytes', but it won't be
2203              * shared with GVariant (which means there is no chance of
2204              * it being accidentally retransmitted).
2205              *
2206              * The kernel does the same thing, so make sure we get the
2207              * expected result.  Because of the kernel doing the same,
2208              * the result is that we will always be rounding-down to a
2209              * multiple of 8 for the pointer, which means that the
2210              * pointer will always be valid, assuming the original
2211              * address was.
2212              *
2213              * We could fix this with a new GBytes constructor that took
2214              * 'flavour' as a parameter, but it's not worth it...
2215              */
2216             flavour = body_size & 7;
2217             g_assert ((item->vec.offset & 7) == flavour);
2218
2219             vector.gbytes = g_bytes_new (((guchar *) msg) + item->vec.offset - flavour, item->vec.size + flavour);
2220             vector.data.pointer = g_bytes_get_data (vector.gbytes, NULL);
2221             vector.data.pointer += flavour;
2222             vector.size = item->vec.size;
2223
2224             g_array_append_val (body_vectors, vector);
2225             body_size += vector.size;
2226           }
2227           break;
2228
2229         /* KDBUS_ITEM_PAYLOAD_MEMFD */
2230         case KDBUS_ITEM_PAYLOAD_MEMFD:
2231           {
2232             GVariantVector vector;
2233             const guchar *data;
2234             gsize size;
2235
2236             vector.gbytes = g_bytes_new_take_zero_copy_fd (item->memfd.fd);
2237             data = g_bytes_get_data (vector.gbytes, &size);
2238
2239             g_assert (item->memfd.start + item->memfd.size <= size);
2240
2241             vector.data.pointer = data + item->memfd.start;
2242             vector.size = item->memfd.size;
2243
2244             g_array_append_val (body_vectors, vector);
2245             body_size += vector.size;
2246           }
2247           break;
2248
2249         /* KDBUS_ITEM_FDS */
2250         case KDBUS_ITEM_FDS:
2251           {
2252             GUnixFDList *fd_list;
2253
2254             fd_list = g_unix_fd_list_new_from_array (item->fds, data_size / sizeof (int));
2255             g_dbus_message_set_unix_fd_list (message, fd_list);
2256             g_object_unref (fd_list);
2257           }
2258           break;
2259
2260         /* All of the following items, like CMDLINE,
2261            CGROUP, etc. need some GDBUS API extensions and
2262            should be implemented in the future */
2263         case KDBUS_ITEM_TIMESTAMP:
2264           {
2265             /* g_print ("time: seq %llu mon %llu real %llu\n",
2266                      item->timestamp.seqnum, item->timestamp.monotonic_ns, item->timestamp.realtime_ns); */
2267
2268             //g_dbus_message_set_timestamp (message, item->timestamp.monotonic_ns / 1000);
2269             //g_dbus_message_set_serial (message, item->timestamp.seqnum);
2270             break;
2271           }
2272
2273         case KDBUS_ITEM_CREDS:
2274           {
2275             /* g_print ("creds: u%llu eu %llu su%llu fsu%llu g%llu eg%llu sg%llu fsg%llu\n",
2276                      item->creds.uid, item->creds.euid, item->creds.suid, item->creds.fsuid,
2277                      item->creds.gid, item->creds.egid, item->creds.sgid, item->creds.fsgid); */
2278             break;
2279           }
2280
2281         case KDBUS_ITEM_PIDS:
2282         case KDBUS_ITEM_PID_COMM:
2283         case KDBUS_ITEM_TID_COMM:
2284         case KDBUS_ITEM_EXE:
2285         case KDBUS_ITEM_CMDLINE:
2286         case KDBUS_ITEM_CGROUP:
2287         case KDBUS_ITEM_AUDIT:
2288         case KDBUS_ITEM_CAPS:
2289         case KDBUS_ITEM_SECLABEL:
2290         case KDBUS_ITEM_CONN_DESCRIPTION:
2291         case KDBUS_ITEM_AUXGROUPS:
2292         case KDBUS_ITEM_OWNED_NAME:
2293         case KDBUS_ITEM_NAME:
2294           //g_print ("unhandled %04x\n", (int) item->type);
2295           break;
2296
2297         default:
2298           g_error ("[KDBUS] DBUS_PAYLOAD: Unknown filed - %lld", item->type);
2299           break;
2300         }
2301     }
2302
2303   body = GLIB_PRIVATE_CALL(g_variant_from_vectors) (G_VARIANT_TYPE ("((yyyyuta{tv})v)"),
2304                                                     (GVariantVector *) body_vectors->data,
2305                                                     body_vectors->len, body_size, FALSE);
2306   g_assert (body);
2307
2308   for (i = 0; i < body_vectors->len; i++)
2309     g_bytes_unref (g_array_index (body_vectors, GVariantVector, i).gbytes);
2310
2311   g_array_free (body_vectors, TRUE);
2312
2313   parts[0] = g_variant_get_child_value (body, 0);
2314   parts[1] = g_variant_get_child_value (body, 1);
2315   g_variant_unref (body);
2316
2317   g_variant_get (parts[0], "(yyyyuta{tv})", &endianness, &type, &flags, &version, NULL, &serial, &fields_iter);
2318   g_variant_unref (parts[0]);
2319
2320   while (g_variant_iter_loop (fields_iter, "{tv}", &key, &value))
2321     g_dbus_message_set_header (message, key, value);
2322
2323   g_dbus_message_set_flags (message, flags);
2324   g_dbus_message_set_serial (message, serial);
2325   g_dbus_message_set_message_type (message, type);
2326
2327   body = g_variant_get_variant (parts[1]);
2328   if (!g_variant_is_of_type (body, G_VARIANT_TYPE ("()")))
2329     g_dbus_message_set_body (message, body);
2330   else
2331     g_dbus_message_set_body (message, NULL);
2332
2333   g_variant_unref (body);
2334   g_variant_unref (parts[1]);
2335
2336   //g_print ("Received:\n%s\n", g_dbus_message_print (message, 2));
2337
2338   (* worker->message_received_callback) (message, worker->user_data);
2339
2340   g_object_unref (message);
2341
2342   return 0;
2343 }
2344
2345
2346 /**
2347  * _g_kdbus_receive:
2348  *
2349  */
2350 static gssize
2351 _g_kdbus_receive (GKDBusWorker        *kdbus,
2352                   GCancellable  *cancellable,
2353                   GError       **error)
2354 {
2355   struct kdbus_cmd_recv recv;
2356   struct kdbus_msg *msg;
2357
2358   memset (&recv, 0, sizeof recv);
2359   recv.size = sizeof (recv);
2360
2361   if (g_cancellable_set_error_if_cancelled (cancellable, error))
2362     return -1;
2363
2364 again:
2365     if (ioctl(kdbus->fd, KDBUS_CMD_RECV, &recv) < 0)
2366       {
2367         if (errno == EINTR)
2368           goto again;
2369
2370         if (errno == EAGAIN)
2371           return 0;
2372
2373         g_warning ("in holding pattern over %d %d\n", kdbus->fd, errno);
2374         while (1)
2375           sleep(1);
2376
2377         g_set_error (error, G_IO_ERROR,
2378                      g_io_error_from_errno (errno),
2379                      _("Error while receiving message: %s"),
2380                      g_strerror (errno));
2381         return -1;
2382       }
2383
2384    msg = (struct kdbus_msg *)((guint8 *)kdbus->kdbus_buffer + recv.msg.offset);
2385
2386    if (msg->payload_type == KDBUS_PAYLOAD_DBUS)
2387      g_kdbus_decode_dbus_msg (kdbus, msg);
2388    else if (msg->payload_type == KDBUS_PAYLOAD_KERNEL)
2389      g_kdbus_decode_kernel_msg (kdbus, msg);
2390    else
2391      {
2392        g_set_error (error,
2393                     G_DBUS_ERROR,
2394                     G_DBUS_ERROR_FAILED,
2395                     _("Received unknown payload type"));
2396        return -1;
2397      }
2398
2399   g_kdbus_free_data (kdbus, recv.msg.offset);
2400
2401   return 0;
2402 }
2403
2404 static gboolean
2405 g_kdbus_msg_append_item (struct kdbus_msg *msg,
2406                          gsize             type,
2407                          gconstpointer     data,
2408                          gsize             size)
2409 {
2410   struct kdbus_item *item;
2411   gsize item_size;
2412
2413   item_size = size + G_STRUCT_OFFSET(struct kdbus_item, data);
2414
2415   if (msg->size + item_size > KDBUS_MSG_MAX_SIZE)
2416     return FALSE;
2417
2418   /* align */
2419   msg->size += (-msg->size) & 7;
2420   item = (struct kdbus_item *) ((guchar *) msg + msg->size);
2421   item->type = type;
2422   item->size = item_size;
2423   memcpy (item->data, data, size);
2424
2425   msg->size += item_size;
2426
2427   return TRUE;
2428 }
2429
2430 static gboolean
2431 g_kdbus_msg_append_payload_vec (struct kdbus_msg *msg,
2432                                 gconstpointer     data,
2433                                 gsize             size)
2434 {
2435   struct kdbus_vec vec = {
2436     .size = size,
2437     .address = (gsize) data
2438   };
2439
2440   return g_kdbus_msg_append_item (msg, KDBUS_ITEM_PAYLOAD_VEC, &vec, sizeof vec);
2441 }
2442
2443 static gboolean
2444 g_kdbus_msg_append_payload_memfd (struct kdbus_msg *msg,
2445                                   gint              fd,
2446                                   gsize             offset,
2447                                   gsize             size)
2448 {
2449   struct kdbus_memfd mfd = {
2450    .start = offset,
2451    .size = size,
2452    .fd = fd,
2453   };
2454
2455   return g_kdbus_msg_append_item (msg, KDBUS_ITEM_PAYLOAD_MEMFD, &mfd, sizeof mfd);
2456 }
2457
2458 static struct kdbus_bloom_filter *
2459 g_kdbus_msg_append_bloom (struct kdbus_msg *msg,
2460                           gsize             size)
2461 {
2462   struct kdbus_item *bloom_item;
2463   gsize bloom_item_size;
2464
2465   bloom_item_size = G_STRUCT_OFFSET (struct kdbus_item, bloom_filter) +
2466                     G_STRUCT_OFFSET (struct kdbus_bloom_filter, data) +
2467                     size;
2468   if (msg->size + bloom_item_size > KDBUS_MSG_MAX_SIZE)
2469     return NULL;
2470
2471   /* align */
2472   msg->size += (-msg->size) & 7;
2473   bloom_item = (struct kdbus_item *) ((guchar *) msg + msg->size);
2474
2475   /* set size and type */
2476   bloom_item->size = bloom_item_size;
2477   bloom_item->type = KDBUS_ITEM_BLOOM_FILTER;
2478
2479   msg->size += bloom_item->size;
2480   return &bloom_item->bloom_filter;
2481 }
2482
2483 #if 0
2484 #include "dbusheader.h"
2485
2486 void dump_header (gconstpointer data, gsize size) ;
2487 void
2488 dump_header (gconstpointer data,
2489              gsize size)
2490 {
2491   GDBusMessageHeaderFieldsIterator iter;
2492   GDBusMessageHeader header;
2493
2494   header = g_dbus_message_header_new (data, size);
2495   g_print ("header e/%c t/%u f/x%x v/%u s/%"G_GUINT64_FORMAT"\n",
2496            g_dbus_message_header_get_endian (header),
2497            g_dbus_message_header_get_type (header),
2498            g_dbus_message_header_get_flags (header),
2499            g_dbus_message_header_get_version (header),
2500            g_dbus_message_header_get_serial (header));
2501
2502   iter = g_dbus_message_header_iterate_fields (header);
2503
2504   while (g_dbus_message_header_fields_iterator_next (&iter))
2505     {
2506       const gchar *string;
2507       guint64 reply_to;
2508       guint64 key;
2509
2510       key = g_dbus_message_header_fields_iterator_get_key (iter);
2511
2512       switch (key)
2513         {
2514           case G_DBUS_MESSAGE_HEADER_FIELD_PATH:
2515             if (g_dbus_message_header_fields_iterator_get_value_as_object_path (iter, &string))
2516               g_print ("  path: %s\n", string);
2517             else
2518               g_print ("  path: <<invalid string>>\n");
2519             break;
2520
2521           case G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE:
2522             if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2523               g_print ("  interface: %s\n", string);
2524             else
2525               g_print ("  interface: <<invalid string>>\n");
2526             break;
2527
2528           case G_DBUS_MESSAGE_HEADER_FIELD_MEMBER:
2529             if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2530               g_print ("  member: %s\n", string);
2531             else
2532               g_print ("  member: <<invalid string>>\n");
2533             break;
2534
2535           case G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME:
2536             if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2537               g_print ("  error: %s\n", string);
2538             else
2539               g_print ("  error: <<invalid string>>\n");
2540             break;
2541
2542           case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL:
2543             if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2544               g_print ("  serial: %s\n", string);
2545             else
2546               g_print ("  serial: <<invalid string>>\n");
2547             break;
2548
2549           case G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION:
2550             if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2551               g_print ("  destination: %s\n", string);
2552             else
2553               g_print ("  destination: <<invalid string>>\n");
2554             break;
2555
2556           case G_DBUS_MESSAGE_HEADER_FIELD_SENDER:
2557             if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2558               g_print ("  sender: %s\n", string);
2559             else
2560               g_print ("  sender: <<invalid string>>\n");
2561             break;
2562
2563           default:
2564             g_print ("unknown field code %"G_GUINT64_FORMAT"\n", key);
2565             g_assert_not_reached ();
2566         }
2567     }
2568
2569   g_print ("\n");
2570
2571 }
2572 #endif
2573
2574 /**
2575  * _g_kdbus_send:
2576  * Returns: size of data sent or -1 when error
2577  */
2578 static gboolean
2579 _g_kdbus_send (GKDBusWorker        *kdbus,
2580                GDBusMessage  *message,
2581                GError       **error)
2582 {
2583   struct kdbus_msg *msg = alloca (KDBUS_MSG_MAX_SIZE);
2584   GVariantVectors body_vectors;
2585   struct kdbus_cmd_send send;
2586   const gchar *dst_name;
2587
2588   g_return_val_if_fail (G_IS_KDBUS_WORKER (kdbus), -1);
2589
2590   /* fill in as we go... */
2591   memset (msg, 0, sizeof (struct kdbus_msg));
2592   msg->size = sizeof (struct kdbus_msg);
2593   msg->payload_type = KDBUS_PAYLOAD_DBUS;
2594   msg->src_id = kdbus->unique_id;
2595   msg->cookie = g_dbus_message_get_serial(message);
2596
2597   /* Message destination */
2598   {
2599     dst_name = g_dbus_message_get_destination (message);
2600
2601     if (dst_name != NULL)
2602       {
2603         if (g_dbus_is_unique_name (dst_name))
2604           {
2605             if (dst_name[1] != '1' || dst_name[2] != '.')
2606               {
2607                 g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
2608                              "Invalid unique D-Bus name '%s'", dst_name);
2609                 return FALSE;
2610               }
2611
2612             /* We already know that it passes the checks for unique
2613              * names, so no need to perform error checking on strtoull.
2614              */
2615             msg->dst_id = strtoull (dst_name + 3, NULL, 10);
2616             dst_name = NULL;
2617           }
2618         else
2619           {
2620             g_kdbus_msg_append_item (msg, KDBUS_ITEM_DST_NAME, dst_name, strlen (dst_name) + 1);
2621             msg->dst_id = KDBUS_DST_ID_NAME;
2622           }
2623       }
2624     else
2625       msg->dst_id = KDBUS_DST_ID_BROADCAST;
2626   }
2627
2628   /* File descriptors */
2629   {
2630     GUnixFDList *fd_list;
2631
2632     fd_list = g_dbus_message_get_unix_fd_list (message);
2633
2634     if (fd_list != NULL)
2635       {
2636         const gint *fds;
2637         gint n_fds;
2638
2639         fds = g_unix_fd_list_peek_fds (fd_list, &n_fds);
2640
2641         if (n_fds)
2642           g_kdbus_msg_append_item (msg, KDBUS_ITEM_FDS, fds, sizeof (gint) * n_fds);
2643       }
2644   }
2645
2646   /* Message body */
2647   {
2648     struct dbus_fixed_header fh;
2649     GHashTableIter header_iter;
2650     GVariantBuilder builder;
2651     gpointer key, value;
2652     GVariant *parts[3];
2653     GVariant *body;
2654
2655     fh.endian = (G_BYTE_ORDER == G_LITTLE_ENDIAN) ? 'l': 'B';
2656     fh.type = g_dbus_message_get_message_type (message);
2657     fh.flags = g_dbus_message_get_flags (message);
2658     fh.version = 2;
2659     fh.reserved = 0;
2660     fh.serial = g_dbus_message_get_serial (message);
2661     parts[0] = g_variant_new_from_data (DBUS_FIXED_HEADER_TYPE, &fh, sizeof fh, TRUE, NULL, NULL);
2662
2663     g_dbus_message_init_header_iter (message, &header_iter);
2664     g_variant_builder_init (&builder, DBUS_EXTENDED_HEADER_TYPE);
2665
2666     /* We set the sender field to the correct value for ourselves */
2667     g_variant_builder_add (&builder, "{tv}",
2668                            (guint64) G_DBUS_MESSAGE_HEADER_FIELD_SENDER,
2669                            g_variant_new_printf (":1.%"G_GUINT64_FORMAT, kdbus->unique_id));
2670
2671     while (g_hash_table_iter_next (&header_iter, &key, &value))
2672       {
2673         guint64 key_int = (gsize) key;
2674
2675         switch (key_int)
2676           {
2677             /* These are the normal header fields that get passed
2678              * straight through.
2679              */
2680             case G_DBUS_MESSAGE_HEADER_FIELD_PATH:
2681             case G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE:
2682             case G_DBUS_MESSAGE_HEADER_FIELD_MEMBER:
2683             case G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME:
2684             case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL:
2685             case G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION:
2686               g_variant_builder_add (&builder, "{tv}", key_int, value);
2687               /* This is a little bit gross.
2688                *
2689                * We must send the header part of the message in a single
2690                * vector as per kdbus rules, but the GVariant serialiser
2691                * code will split any item >= 128 bytes into its own
2692                * vector to save the copy.
2693                *
2694                * No header field should be that big anyway... right?
2695                */
2696               g_assert_cmpint (g_variant_get_size (value), <, 128);
2697               continue;
2698
2699             /* We send this one unconditionally, but set it ourselves */
2700             case G_DBUS_MESSAGE_HEADER_FIELD_SENDER:
2701               continue;
2702
2703             /* We don't send these at all in GVariant format */
2704             case G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE:
2705             case G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS:
2706               continue;
2707
2708             default:
2709               g_assert_not_reached ();
2710           }
2711       }
2712     parts[1] = g_variant_builder_end (&builder);
2713
2714     body = g_dbus_message_get_body (message);
2715     if (!body)
2716       body = g_variant_new ("()");
2717     parts[2] = g_variant_new_variant (body);
2718
2719     body = g_variant_ref_sink (g_variant_new_tuple (parts, G_N_ELEMENTS (parts)));
2720     GLIB_PRIVATE_CALL(g_variant_to_vectors) (body, &body_vectors);
2721
2722     /* Sanity check to make sure the header is really contiguous:
2723      *
2724      *  - we must have at least one vector in the output
2725      *  - the first vector must completely contain at least the header
2726      */
2727     g_assert_cmpint (body_vectors.vectors->len, >, 0);
2728     g_assert_cmpint (g_array_index (body_vectors.vectors, GVariantVector, 0).size, >=,
2729                      g_variant_get_size (parts[0]) + g_variant_get_size (parts[1]));
2730
2731     g_variant_unref (body);
2732   }
2733
2734   {
2735     guint i;
2736
2737     for (i = 0; i < body_vectors.vectors->len; i++)
2738       {
2739         GVariantVector vector = g_array_index (body_vectors.vectors, GVariantVector, i);
2740
2741         if (vector.gbytes)
2742           {
2743             gint fd;
2744
2745             fd = g_bytes_get_zero_copy_fd (vector.gbytes);
2746
2747             if (fd >= 0)
2748               {
2749                 const guchar *bytes_data;
2750                 gsize bytes_size;
2751
2752                 bytes_data = g_bytes_get_data (vector.gbytes, &bytes_size);
2753
2754                 if (bytes_data <= vector.data.pointer && vector.data.pointer + vector.size <= bytes_data + bytes_size)
2755                   {
2756                     if (!g_kdbus_msg_append_payload_memfd (msg, fd, vector.data.pointer - bytes_data, vector.size))
2757                       goto need_compact;
2758                   }
2759                 else
2760                   {
2761                     if (!g_kdbus_msg_append_payload_vec (msg, vector.data.pointer, vector.size))
2762                       goto need_compact;
2763                   }
2764               }
2765             else
2766               {
2767                 if (!g_kdbus_msg_append_payload_vec (msg, vector.data.pointer, vector.size))
2768                   goto need_compact;
2769               }
2770           }
2771         else
2772           if (!g_kdbus_msg_append_payload_vec (msg, body_vectors.extra_bytes->data + vector.data.offset, vector.size))
2773             goto need_compact;
2774       }
2775   }
2776
2777   /*
2778    * set message flags
2779    */
2780   msg->flags = ((g_dbus_message_get_flags (message) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_EXPECT_REPLY) |
2781                 ((g_dbus_message_get_flags (message) & G_DBUS_MESSAGE_FLAGS_NO_AUTO_START) ? KDBUS_MSG_NO_AUTO_START : 0);
2782
2783   if ((msg->flags) & KDBUS_MSG_EXPECT_REPLY)
2784     msg->timeout_ns = 1000LU * g_get_monotonic_time() + KDBUS_TIMEOUT_NS;
2785   else
2786     msg->cookie_reply = g_dbus_message_get_reply_serial(message);
2787
2788   if (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_SIGNAL)
2789     msg->flags |= KDBUS_MSG_SIGNAL;
2790
2791   /*
2792    * append bloom filter item for broadcast signals
2793    */
2794   if (msg->dst_id == KDBUS_DST_ID_BROADCAST)
2795     {
2796       struct kdbus_bloom_filter *bloom_filter;
2797
2798       bloom_filter = g_kdbus_msg_append_bloom (msg, kdbus->bloom_size);
2799       if (bloom_filter == NULL)
2800         goto need_compact;
2801       g_kdbus_setup_bloom (kdbus, message, bloom_filter);
2802     }
2803
2804   send.size = sizeof (send);
2805   send.flags = 0;
2806   send.msg_address = (gsize) msg;
2807
2808   /*
2809    * send message
2810    */
2811   if (ioctl(kdbus->fd, KDBUS_CMD_SEND, &send))
2812     {
2813       if (errno == ENXIO || errno == ESRCH)
2814         {
2815           g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
2816                        "Destination '%s' not known", dst_name);
2817         }
2818       else if (errno == EADDRNOTAVAIL)
2819         {
2820           g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
2821                        "No support for activation for name: %s", dst_name);
2822         }
2823       else if (errno == EXFULL)
2824         {
2825           g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_LIMITS_EXCEEDED,
2826                        "The memory pool of the receiver is full");
2827         }
2828       else if (errno == ENOBUFS)
2829         {
2830           g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_LIMITS_EXCEEDED,
2831                        "Too many pending messages on the receiver side");
2832         }
2833       else
2834         {
2835           g_error ("WTF? %d\n", errno);
2836           g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
2837                        "%s", strerror(errno));
2838         }
2839       return FALSE;
2840     }
2841
2842   return TRUE;
2843
2844 need_compact:
2845   /* We end up here if:
2846    *  - too many kdbus_items
2847    *  - too large kdbus_msg size
2848    *  - too much vector data
2849    *
2850    * We need to compact the message before sending it.
2851    */
2852   g_assert_not_reached ();
2853 }
2854
2855 GKDBusWorker *
2856 g_kdbus_worker_new (const gchar  *address,
2857                     GError      **error)
2858 {
2859   GKDBusWorker *worker;
2860
2861   worker = g_object_new (G_TYPE_KDBUS_WORKER, NULL);
2862   if (!_g_kdbus_open (worker, address, error))
2863     {
2864       g_object_unref (worker);
2865       return NULL;
2866     }
2867
2868   return worker;
2869 }
2870
2871 void
2872 g_kdbus_worker_associate (GKDBusWorker                            *worker,
2873                           GDBusCapabilityFlags                     capabilities,
2874                           GDBusWorkerMessageReceivedCallback       message_received_callback,
2875                           GDBusWorkerMessageAboutToBeSentCallback  message_about_to_be_sent_callback,
2876                           GDBusWorkerDisconnectedCallback          disconnected_callback,
2877                           gpointer                                 user_data)
2878 {
2879   worker->capabilities = capabilities;
2880   worker->message_received_callback = message_received_callback;
2881   worker->message_about_to_be_sent_callback = message_about_to_be_sent_callback;
2882   worker->disconnected_callback = disconnected_callback;
2883   worker->user_data = user_data;
2884 }
2885
2886 void
2887 g_kdbus_worker_unfreeze (GKDBusWorker *worker)
2888 {
2889   gchar *name;
2890
2891   if (worker->source != NULL)
2892     return;
2893
2894   worker->context = g_main_context_ref_thread_default ();
2895   worker->source = g_unix_fd_source_new (worker->fd, G_IO_IN);
2896
2897   g_source_set_callback (worker->source, (GSourceFunc) kdbus_ready, worker, NULL);
2898   name = g_strdup_printf ("kdbus worker");
2899   g_source_set_name (worker->source, name);
2900   g_free (name);
2901
2902   g_source_attach (worker->source, worker->context);
2903 }
2904
2905 gboolean
2906 g_kdbus_worker_send_message (GKDBusWorker  *worker,
2907                              GDBusMessage  *message,
2908                              GError       **error)
2909 {
2910   return _g_kdbus_send (worker, message, error);
2911 }
2912
2913 /* TODO */
2914 void
2915 g_kdbus_worker_flush_sync (GKDBusWorker *worker)
2916 {
2917   g_warning ("TODO: Implement sync flush");
2918 }
2919
2920 void
2921 g_kdbus_worker_stop (GKDBusWorker *worker)
2922 {
2923   g_warning ("TODO: Implement worker stop");
2924 }
2925
2926 void
2927 g_kdbus_worker_close (GKDBusWorker       *worker,
2928                       GCancellable       *cancellable,
2929                       GSimpleAsyncResult *result)
2930 {
2931 }