7127130be7b9b87ec3cd0b2f102331e5dbad0a95
[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 = 0; /* KDBUS_HELLO_ACCEPT_FD */
558   kdbus->flags = KDBUS_HELLO_ACCEPT_FD;
559   kdbus->attach_flags_send = _KDBUS_ATTACH_ALL;
560   kdbus->attach_flags_recv = _KDBUS_ATTACH_ALL;
561 }
562
563 static gboolean
564 kdbus_ready (gint         fd,
565              GIOCondition condition,
566              gpointer     user_data)
567 {
568   GKDBusWorker *kdbus = user_data;
569   GError *error = NULL;
570
571   _g_kdbus_receive (kdbus, NULL, &error);
572   g_assert_no_error (error);
573
574   return G_SOURCE_CONTINUE;
575 }
576
577 gboolean
578 _g_kdbus_open (GKDBusWorker  *worker,
579                const gchar   *address,
580                GError       **error)
581 {
582   g_return_val_if_fail (G_IS_KDBUS_WORKER (worker), FALSE);
583
584   worker->fd = open(address, O_RDWR|O_NOCTTY|O_CLOEXEC);
585   if (worker->fd<0)
586     {
587       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Can't open kdbus endpoint"));
588       return FALSE;
589     }
590
591   worker->closed = FALSE;
592
593   return TRUE;
594 }
595
596
597 /**
598  * g_kdbus_free_data:
599  *
600  */
601 static gboolean
602 g_kdbus_free_data (GKDBusWorker      *kdbus,
603                    guint64      offset)
604 {
605   struct kdbus_cmd_free cmd = {
606     .size = sizeof(cmd),
607     .offset = offset,
608     .flags = 0
609   };
610   int ret;
611
612   ret = ioctl (kdbus->fd, KDBUS_CMD_FREE, &cmd);
613   if (ret < 0)
614     return FALSE;
615
616   return TRUE;
617 }
618
619
620 /**
621  * g_kdbus_translate_nameowner_flags:
622  *
623  */
624 static void
625 g_kdbus_translate_nameowner_flags (GBusNameOwnerFlags   flags,
626                                    guint64             *kdbus_flags)
627 {
628   guint64 new_flags;
629
630   new_flags = 0;
631
632   if (flags & G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT)
633     new_flags |= KDBUS_NAME_ALLOW_REPLACEMENT;
634
635   if (flags & G_BUS_NAME_OWNER_FLAGS_REPLACE)
636     new_flags |= KDBUS_NAME_REPLACE_EXISTING;
637
638   if (!(flags & G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE))
639     new_flags |= KDBUS_NAME_QUEUE;
640
641   *kdbus_flags = new_flags;
642 }
643
644
645 /**
646  * _g_kdbus_close:
647  *
648  */
649 void
650 _g_kdbus_close (GKDBusWorker *kdbus)
651 {
652   g_return_val_if_fail (G_IS_KDBUS_WORKER (kdbus), FALSE);
653
654   if (kdbus->closed)
655     return;
656
657   g_source_destroy (kdbus->source);
658   kdbus->source = 0;
659
660   g_main_context_unref (kdbus->context);
661   kdbus->context = NULL;
662
663   close (kdbus->fd);
664   kdbus->fd = -1;
665
666   kdbus->closed = TRUE;
667 }
668
669 /**
670  * _g_kdbus_is_closed:
671  *
672  */
673 gboolean
674 _g_kdbus_is_closed (GKDBusWorker  *kdbus)
675 {
676   g_return_val_if_fail (G_IS_KDBUS_WORKER (kdbus), FALSE);
677
678   return kdbus->closed;
679 }
680
681
682 /**
683  * _g_kdbus_Hello:
684  *
685  */
686 GVariant *
687 _g_kdbus_Hello (GKDBusWorker *worker,
688                 GError    **error)
689 {
690   struct kdbus_cmd_hello *cmd;
691   struct kdbus_bloom_parameter *bloom;
692   struct kdbus_item *item, *items;
693
694   gchar *conn_name;
695   size_t size, conn_name_size;
696
697   conn_name = "gdbus-kdbus";
698   conn_name_size = strlen (conn_name);
699
700   size = KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_cmd_hello, items)) +
701          KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, str) + conn_name_size + 1);
702
703   cmd = g_alloca0 (size);
704   cmd->flags = worker->flags;
705   cmd->attach_flags_send = worker->attach_flags_send;
706   cmd->attach_flags_recv = worker->attach_flags_recv;
707   cmd->size = size;
708   cmd->pool_size = KDBUS_POOL_SIZE;
709
710   item = cmd->items;
711   item->size = G_STRUCT_OFFSET (struct kdbus_item, str) + conn_name_size + 1;
712   item->type = KDBUS_ITEM_CONN_DESCRIPTION;
713   memcpy (item->str, conn_name, conn_name_size+1);
714   item = KDBUS_ITEM_NEXT (item);
715
716   if (ioctl(worker->fd, KDBUS_CMD_HELLO, cmd))
717     {
718       g_set_error (error, G_IO_ERROR,
719                    g_io_error_from_errno (errno),
720                    _("Failed to send HELLO: %s"),
721                    g_strerror (errno));
722       return NULL;
723     }
724
725   worker->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, worker->fd, 0);
726   if (worker->kdbus_buffer == MAP_FAILED)
727     {
728       g_set_error (error, G_IO_ERROR,
729                    g_io_error_from_errno (errno),
730                    _("mmap error: %s"),
731                    g_strerror (errno));
732       return NULL;
733     }
734
735   if (cmd->bus_flags > 0xFFFFFFFFULL)
736     {
737       g_set_error_literal (error,
738                            G_IO_ERROR,
739                            G_IO_ERROR_FAILED,
740                            _("Incompatible HELLO flags"));
741       return NULL;
742     }
743
744   memcpy (worker->bus_id, cmd->id128, 16);
745
746   worker->unique_id = cmd->id;
747   asprintf(&worker->unique_name, ":1.%llu", (unsigned long long) cmd->id);
748
749   /* read bloom filters parameters */
750   bloom = NULL;
751   items = (void*)(worker->kdbus_buffer + cmd->offset);
752   KDBUS_FOREACH(item, items, cmd->items_size)
753     {
754       switch (item->type)
755         {
756           case KDBUS_ITEM_BLOOM_PARAMETER:
757             bloom = &item->bloom_parameter;
758           break;
759         }
760     }
761
762   if (bloom != NULL)
763     {
764       worker->bloom_size = (gsize) bloom->size;
765       worker->bloom_n_hash = (guint) bloom->n_hash;
766     }
767
768   return g_variant_new ("(s)", worker->unique_name);
769 }
770
771
772 /**
773  * _g_kdbus_RequestName:
774  *
775  */
776 GVariant *
777 _g_kdbus_RequestName (GKDBusWorker        *worker,
778                       const gchar         *name,
779                       GBusNameOwnerFlags   flags,
780                       GError             **error)
781 {
782   GVariant *result;
783   struct kdbus_cmd *cmd;
784   guint64 kdbus_flags;
785   gssize len, size;
786   gint status, ret;
787
788   status = G_BUS_REQUEST_NAME_FLAGS_PRIMARY_OWNER;
789
790   if (!g_dbus_is_name (name))
791     {
792       g_set_error (error,
793                    G_DBUS_ERROR,
794                    G_DBUS_ERROR_INVALID_ARGS,
795                    "Given bus name \"%s\" is not valid", name);
796       return NULL;
797     }
798
799   if (*name == ':')
800     {
801       g_set_error (error,
802                    G_DBUS_ERROR,
803                    G_DBUS_ERROR_INVALID_ARGS,
804                    "Cannot acquire a service starting with ':' such as \"%s\"", name);
805       return NULL;
806     }
807
808   g_kdbus_translate_nameowner_flags (flags, &kdbus_flags);
809
810   len = strlen(name) + 1;
811   size = G_STRUCT_OFFSET (struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(len);
812   cmd = g_alloca0 (size);
813   cmd->size = size;
814   cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
815   cmd->items[0].type = KDBUS_ITEM_NAME;
816   cmd->flags = kdbus_flags;
817   memcpy (cmd->items[0].str, name, len);
818
819   ret = ioctl(worker->fd, KDBUS_CMD_NAME_ACQUIRE, cmd);
820   if (ret < 0)
821     {
822       if (errno == EEXIST)
823         status = G_BUS_REQUEST_NAME_FLAGS_EXISTS;
824       else if (errno == EALREADY)
825         status = G_BUS_REQUEST_NAME_FLAGS_ALREADY_OWNER;
826       else
827         {
828           g_set_error (error, G_IO_ERROR,
829                        g_io_error_from_errno (errno),
830                        _("Error while acquiring name: %s"),
831                        g_strerror (errno));
832           return NULL;
833         }
834     }
835
836   if (cmd->return_flags & KDBUS_NAME_IN_QUEUE)
837     status = G_BUS_REQUEST_NAME_FLAGS_IN_QUEUE;
838
839   result = g_variant_new ("(u)", status);
840
841   return result;
842 }
843
844
845 /**
846  * _g_kdbus_ReleaseName:
847  *
848  */
849 GVariant *
850 _g_kdbus_ReleaseName (GKDBusWorker     *worker,
851                       const gchar         *name,
852                       GError             **error)
853 {
854   GVariant *result;
855   struct kdbus_cmd *cmd;
856   gssize len, size;
857   gint status, ret;
858
859   status = G_BUS_RELEASE_NAME_FLAGS_RELEASED;
860
861   if (!g_dbus_is_name (name))
862     {
863       g_set_error (error,
864                    G_DBUS_ERROR,
865                    G_DBUS_ERROR_INVALID_ARGS,
866                    "Given bus name \"%s\" is not valid", name);
867       return NULL;
868     }
869
870   if (*name == ':')
871     {
872       g_set_error (error,
873                    G_DBUS_ERROR,
874                    G_DBUS_ERROR_INVALID_ARGS,
875                    "Cannot release a service starting with ':' such as \"%s\"", name);
876       return NULL;
877     }
878
879   len = strlen(name) + 1;
880   size = G_STRUCT_OFFSET (struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(len);
881   cmd = g_alloca0 (size);
882   cmd->size = size;
883   cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
884   cmd->items[0].type = KDBUS_ITEM_NAME;
885   memcpy (cmd->items[0].str, name, len);
886
887   ret = ioctl(worker->fd, KDBUS_CMD_NAME_RELEASE, cmd);
888   if (ret < 0)
889     {
890       if (errno == ESRCH)
891         status = G_BUS_RELEASE_NAME_FLAGS_NON_EXISTENT;
892       else if (errno == EADDRINUSE)
893         status = G_BUS_RELEASE_NAME_FLAGS_NOT_OWNER;
894       else
895         {
896           g_set_error (error, G_IO_ERROR,
897                        g_io_error_from_errno (errno),
898                        _("Error while releasing name: %s"),
899                        g_strerror (errno));
900           return NULL;
901         }
902     }
903
904   result = g_variant_new ("(u)", status);
905
906   return result;
907 }
908
909
910 /**
911  * _g_kdbus_GetBusId:
912  *
913  */
914 GVariant *
915 _g_kdbus_GetBusId (GKDBusWorker  *worker,
916                    GError          **error)
917 {
918   GVariant *result;
919   GString  *result_str;
920   guint     cnt;
921
922   result_str = g_string_new (NULL);
923
924   for (cnt=0; cnt<16; cnt++)
925     g_string_append_printf (result_str, "%02x", worker->bus_id[cnt]);
926
927   result = g_variant_new ("(s)", result_str->str);
928   g_string_free (result_str, TRUE);
929
930   return result;
931 }
932
933
934 /**
935  * _g_kdbus_GetListNames:
936  *
937  */
938 GVariant *
939 _g_kdbus_GetListNames (GKDBusWorker  *worker,
940                        guint             list_name_type,
941                        GError          **error)
942 {
943   GVariant *result;
944   GVariantBuilder *builder;
945   struct kdbus_info *name_list, *name;
946   struct kdbus_cmd_list cmd = {
947     .size = sizeof(cmd)
948   };
949
950   guint64 prev_id;
951   gint ret;
952
953   prev_id = 0;
954
955   if (list_name_type)
956     cmd.flags = KDBUS_LIST_ACTIVATORS;                /* ListActivatableNames */
957   else
958     cmd.flags = KDBUS_LIST_UNIQUE | KDBUS_LIST_NAMES; /* ListNames */
959
960   ret = ioctl(worker->fd, KDBUS_CMD_LIST, &cmd);
961   if (ret < 0)
962     {
963       g_set_error (error,
964                    G_DBUS_ERROR,
965                    G_DBUS_ERROR_FAILED,
966                    _("Error listing names"));
967       return NULL;
968     }
969
970   name_list = (struct kdbus_info *) ((guint8 *) worker->kdbus_buffer + cmd.offset);
971   builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
972
973   KDBUS_FOREACH(name, name_list, cmd.list_size)
974     {
975       struct kdbus_item *item;
976       const gchar *item_name = "";
977
978       if ((cmd.flags & KDBUS_LIST_UNIQUE) && name->id != prev_id)
979         {
980           GString *unique_name;
981
982           unique_name = g_string_new (NULL);
983           g_string_printf (unique_name, ":1.%llu", name->id);
984           g_variant_builder_add (builder, "s", unique_name->str);
985           g_string_free (unique_name,TRUE);
986           prev_id = name->id;
987         }
988
989        KDBUS_ITEM_FOREACH(item, name, items)
990          if (item->type == KDBUS_ITEM_OWNED_NAME)
991            item_name = item->name.name;
992
993         if (g_dbus_is_name (item_name))
994           g_variant_builder_add (builder, "s", item_name);
995     }
996
997   result = g_variant_new ("(as)", builder);
998   g_variant_builder_unref (builder);
999
1000   g_kdbus_free_data (worker, cmd.offset);
1001   return result;
1002 }
1003
1004
1005 /**
1006  * _g_kdbus_NameHasOwner_internal:
1007  *
1008  */
1009 static gboolean
1010 g_kdbus_NameHasOwner_internal (GKDBusWorker       *worker,
1011                                const gchar  *name,
1012                                GError      **error)
1013 {
1014   struct kdbus_cmd_info *cmd;
1015   gssize size, len;
1016   gint ret;
1017
1018   if (g_dbus_is_unique_name(name))
1019     {
1020        size = G_STRUCT_OFFSET (struct kdbus_cmd_info, items);
1021        cmd = g_alloca0 (size);
1022        cmd->id = g_ascii_strtoull (name+3, NULL, 10);
1023     }
1024   else
1025     {
1026        len = strlen(name) + 1;
1027        size = G_STRUCT_OFFSET (struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(len);
1028        cmd = g_alloca0 (size);
1029        cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
1030        cmd->items[0].type = KDBUS_ITEM_NAME;
1031        memcpy (cmd->items[0].str, name, len);
1032     }
1033   cmd->size = size;
1034
1035   ret = ioctl(worker->fd, KDBUS_CMD_CONN_INFO, cmd);
1036   g_kdbus_free_data (worker, cmd->offset);
1037
1038   if (ret < 0)
1039     return FALSE;
1040   else
1041     return TRUE;
1042 }
1043
1044
1045 /**
1046  * _g_kdbus_GetListQueuedOwners:
1047  *
1048  */
1049 GVariant *
1050 _g_kdbus_GetListQueuedOwners (GKDBusWorker  *worker,
1051                               const gchar   *name,
1052                               GError       **error)
1053 {
1054   GVariant *result;
1055   GVariantBuilder *builder;
1056   GString *unique_name;
1057   gint ret;
1058
1059   struct kdbus_info *name_list, *kname;
1060   struct kdbus_cmd_list cmd = {
1061     .size = sizeof(cmd),
1062     .flags = KDBUS_LIST_QUEUED
1063   };
1064
1065   if (!g_dbus_is_name (name))
1066     {
1067       g_set_error (error,
1068                    G_DBUS_ERROR,
1069                    G_DBUS_ERROR_INVALID_ARGS,
1070                    "Given bus name \"%s\" is not valid", name);
1071       return NULL;
1072     }
1073
1074   if (!g_kdbus_NameHasOwner_internal (worker, name, error))
1075     {
1076       g_set_error (error,
1077                    G_DBUS_ERROR,
1078                    G_DBUS_ERROR_NAME_HAS_NO_OWNER,
1079                    "Could not get owner of name '%s': no such name", name);
1080       return NULL;
1081     }
1082
1083   ret = ioctl(worker->fd, KDBUS_CMD_LIST, &cmd);
1084   if (ret < 0)
1085     {
1086       g_set_error (error,
1087                    G_DBUS_ERROR,
1088                    G_DBUS_ERROR_FAILED,
1089                    _("Error listing names"));
1090       return NULL;
1091     }
1092
1093   name_list = (struct kdbus_info *) ((guint8 *) worker->kdbus_buffer + cmd.offset);
1094
1095   unique_name = g_string_new (NULL);
1096   builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
1097   KDBUS_FOREACH(kname, name_list, cmd.list_size)
1098     {
1099       struct kdbus_item *item;
1100       const char *item_name = "";
1101
1102       KDBUS_ITEM_FOREACH(item, kname, items)
1103         if (item->type == KDBUS_ITEM_NAME)
1104           item_name = item->str;
1105
1106       if (strcmp(item_name, name))
1107         continue;
1108
1109       g_string_printf (unique_name, ":1.%llu", kname->id);
1110       g_variant_builder_add (builder, "s", item_name);
1111     }
1112
1113   result = g_variant_new ("(as)", builder);
1114   g_variant_builder_unref (builder);
1115   g_string_free (unique_name,TRUE);
1116
1117   g_kdbus_free_data (worker, cmd.offset);
1118   return result;
1119 }
1120
1121
1122 /**
1123  * g_kdbus_GetConnInfo_internal:
1124  *
1125  */
1126 static GVariant *
1127 g_kdbus_GetConnInfo_internal (GKDBusWorker  *worker,
1128                               const gchar      *name,
1129                               guint64           flag,
1130                               GError          **error)
1131 {
1132   GVariant *result;
1133
1134   struct kdbus_cmd_info *cmd;
1135   struct kdbus_info *conn_info;
1136   struct kdbus_item *item;
1137   gssize size, len;
1138   gint ret;
1139
1140   result = NULL;
1141
1142   if (!g_dbus_is_name (name))
1143     {
1144       g_set_error (error,
1145                    G_DBUS_ERROR,
1146                    G_DBUS_ERROR_INVALID_ARGS,
1147                    "Given bus name \"%s\" is not valid", name);
1148       return NULL;
1149     }
1150
1151   if (!g_kdbus_NameHasOwner_internal (worker, name, error))
1152     {
1153       g_set_error (error,
1154                    G_DBUS_ERROR,
1155                    G_DBUS_ERROR_NAME_HAS_NO_OWNER,
1156                    "Could not get owner of name '%s': no such name", name);
1157       return NULL;
1158     }
1159
1160   if (g_dbus_is_unique_name(name))
1161     {
1162        size = G_STRUCT_OFFSET (struct kdbus_cmd_info, items);
1163        cmd = g_alloca0 (size);
1164        cmd->id = g_ascii_strtoull (name+3, NULL, 10);
1165     }
1166   else
1167     {
1168        len = strlen(name) + 1;
1169        size = G_STRUCT_OFFSET (struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(len);
1170        cmd = g_alloca0 (size);
1171        cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
1172        cmd->items[0].type = KDBUS_ITEM_NAME;
1173        memcpy (cmd->items[0].str, name, len);
1174     }
1175
1176   cmd->attach_flags = _KDBUS_ATTACH_ALL;
1177   cmd->size = size;
1178
1179   ret = ioctl(worker->fd, KDBUS_CMD_CONN_INFO, cmd);
1180   if (ret < 0)
1181     {
1182       g_set_error (error,
1183                    G_DBUS_ERROR,
1184                    G_DBUS_ERROR_FAILED,
1185                    _("Could not get connection info"));
1186       return NULL;
1187     }
1188
1189   conn_info = (struct kdbus_info *) ((guint8 *) worker->kdbus_buffer + cmd->offset);
1190
1191   /*
1192   if (conn_info->flags & KDBUS_HELLO_ACTIVATOR)
1193     {}
1194   */
1195
1196   if (flag == G_BUS_CREDS_UNIQUE_NAME)
1197     {
1198        GString *unique_name;
1199
1200        unique_name = g_string_new (NULL);
1201        g_string_printf (unique_name, ":1.%llu", (unsigned long long) conn_info->id);
1202        result = g_variant_new ("(s)", unique_name->str);
1203        g_string_free (unique_name,TRUE);
1204        goto exit;
1205     }
1206
1207   KDBUS_ITEM_FOREACH(item, conn_info, items)
1208    {
1209       switch (item->type)
1210         {
1211           case KDBUS_ITEM_PIDS:
1212
1213             if (flag == G_BUS_CREDS_PID)
1214               {
1215                 guint pid = item->pids.pid;
1216                 result = g_variant_new ("(u)", pid);
1217                 goto exit;
1218               }
1219
1220           case KDBUS_ITEM_CREDS:
1221
1222             if (flag == G_BUS_CREDS_UID)
1223               {
1224                 guint uid = item->creds.uid;
1225                 result = g_variant_new ("(u)", uid);
1226                 goto exit;
1227               }
1228
1229           case KDBUS_ITEM_SECLABEL:
1230           case KDBUS_ITEM_PID_COMM:
1231           case KDBUS_ITEM_TID_COMM:
1232           case KDBUS_ITEM_EXE:
1233           case KDBUS_ITEM_CMDLINE:
1234           case KDBUS_ITEM_CGROUP:
1235           case KDBUS_ITEM_CAPS:
1236           case KDBUS_ITEM_AUDIT:
1237           case KDBUS_ITEM_CONN_DESCRIPTION:
1238           case KDBUS_ITEM_AUXGROUPS:
1239           case KDBUS_ITEM_OWNED_NAME:
1240             break;
1241         }
1242    }
1243
1244 exit:
1245   g_kdbus_free_data (worker, cmd->offset);
1246   return result;
1247 }
1248
1249
1250 /**
1251  * _g_kdbus_GetNameOwner:
1252  *
1253  */
1254 GVariant *
1255 _g_kdbus_GetNameOwner (GKDBusWorker  *worker,
1256                        const gchar      *name,
1257                        GError          **error)
1258 {
1259   return g_kdbus_GetConnInfo_internal (worker,
1260                                        name,
1261                                        G_BUS_CREDS_UNIQUE_NAME,
1262                                        error);
1263 }
1264
1265
1266 /**
1267  * _g_kdbus_GetConnectionUnixProcessID:
1268  *
1269  */
1270 GVariant *
1271 _g_kdbus_GetConnectionUnixProcessID (GKDBusWorker  *worker,
1272                                      const gchar      *name,
1273                                      GError          **error)
1274 {
1275   return g_kdbus_GetConnInfo_internal (worker,
1276                                        name,
1277                                        G_BUS_CREDS_PID,
1278                                        error);
1279 }
1280
1281
1282 /**
1283  * _g_kdbus_GetConnectionUnixUser:
1284  *
1285  */
1286 GVariant *
1287 _g_kdbus_GetConnectionUnixUser (GKDBusWorker  *worker,
1288                                 const gchar      *name,
1289                                 GError          **error)
1290 {
1291   return g_kdbus_GetConnInfo_internal (worker,
1292                                        name,
1293                                        G_BUS_CREDS_UID,
1294                                        error);
1295 }
1296
1297
1298 /**
1299  * g_kdbus_bloom_add_data:
1300  * Based on bus-bloom.c from systemd
1301  * http://cgit.freedesktop.org/systemd/systemd/tree/src/libsystemd/sd-bus/bus-bloom.c
1302  */
1303 static void
1304 g_kdbus_bloom_add_data (GKDBusWorker  *worker,
1305                         guint64        bloom_data [],
1306                         const void    *data,
1307                         gsize          n)
1308 {
1309   guint8 hash[8];
1310   guint64 bit_num;
1311   guint bytes_num = 0;
1312   guint cnt_1, cnt_2;
1313   guint hash_index = 0;
1314
1315   guint c = 0;
1316   guint64 p = 0;
1317
1318   bit_num = worker->bloom_size * 8;
1319
1320   if (bit_num > 1)
1321     bytes_num = ((__builtin_clzll(bit_num) ^ 63U) + 7) / 8;
1322
1323   for (cnt_1 = 0; cnt_1 < (worker->bloom_n_hash); cnt_1++)
1324     {
1325       for (cnt_2 = 0, hash_index = 0; cnt_2 < bytes_num; cnt_2++)
1326         {
1327           if (c <= 0)
1328             {
1329               _g_siphash24(hash, data, n, hash_keys[hash_index++]);
1330               c += 8;
1331             }
1332
1333           p = (p << 8ULL) | (guint64) hash[8 - c];
1334           c--;
1335         }
1336
1337       p &= bit_num - 1;
1338       bloom_data[p >> 6] |= 1ULL << (p & 63);
1339     }
1340 }
1341
1342
1343 /**
1344  * g_kdbus_bloom_add_pair:
1345  *
1346  */
1347 static void
1348 g_kdbus_bloom_add_pair (GKDBusWorker  *worker,
1349                         guint64        bloom_data [],
1350                         const gchar   *parameter,
1351                         const gchar   *value)
1352 {
1353   gchar buf[1024];
1354   gsize size;
1355
1356   size = strlen(parameter) + strlen(value) + 1;
1357   if (size > 1024)
1358     return;
1359
1360   strcpy(stpcpy(stpcpy(buf, parameter), ":"), value);
1361   g_kdbus_bloom_add_data(worker, bloom_data, buf, size);
1362 }
1363
1364
1365 /**
1366  * g_kdbus_bloom_add_prefixes:
1367  *
1368  */
1369 static void
1370 g_kdbus_bloom_add_prefixes (GKDBusWorker  *worker,
1371                             guint64        bloom_data [],
1372                             const gchar   *parameter,
1373                             const gchar   *value,
1374                             gchar          separator)
1375 {
1376   gchar buf[1024];
1377   gsize size;
1378
1379   size = strlen(parameter) + strlen(value) + 1;
1380   if (size > 1024)
1381     return;
1382
1383   strcpy(stpcpy(stpcpy(buf, parameter), ":"), value);
1384
1385   for (;;)
1386     {
1387       gchar *last_sep;
1388       last_sep = strrchr(buf, separator);
1389       if (!last_sep || last_sep == buf)
1390         break;
1391
1392       *last_sep = 0;
1393       g_kdbus_bloom_add_data(worker, bloom_data, buf, last_sep-buf);
1394     }
1395 }
1396
1397
1398 /**
1399  * _g_kdbus_AddMatch:
1400  *
1401  */
1402 void
1403 _g_kdbus_AddMatch (GKDBusWorker  *worker,
1404                    const gchar   *match_rule,
1405                    guint64        cookie)
1406 {
1407   Match *match;
1408   MatchElement *element;
1409   const gchar *sender_name;
1410   gsize sender_len, size;
1411   struct kdbus_cmd_match *cmd;
1412   struct kdbus_item *item;
1413   guint64 *bloom;
1414   guint64 src_id;
1415   gchar *type;
1416   gint cnt, ret;
1417
1418   if (match_rule[0] == '-')
1419     return;
1420
1421   match = match_new (match_rule);
1422   if (!match)
1423     {
1424       match_free (match);
1425       return;
1426     }
1427
1428   sender_name = NULL;
1429   src_id = KDBUS_MATCH_ID_ANY;
1430
1431   bloom = g_alloca0 (worker->bloom_size);
1432   size = KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_cmd_match, items));
1433   match = match_new (match_rule);
1434
1435   for (cnt = 0; cnt < match->n_elements; cnt++)
1436     {
1437       element = &match->elements[cnt];
1438       switch (element->type)
1439         {
1440           case MATCH_ELEMENT_SENDER:
1441             if (g_dbus_is_unique_name(element->value))
1442               {
1443                 src_id = g_ascii_strtoull ((element->value)+3, NULL, 10);
1444                 size += KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, id) + sizeof(src_id));
1445               }
1446             else if (g_dbus_is_name (element->value))
1447               {
1448                 sender_name = element->value;
1449                 sender_len = strlen(element->value) + 1;
1450                 size += KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, str) + sender_len);
1451               }
1452             else
1453               {
1454                 g_critical ("Error while adding a match");
1455                 match_free (match);
1456                 return;
1457               }
1458             break;
1459
1460           case MATCH_ELEMENT_TYPE:
1461             g_kdbus_bloom_add_pair (worker, bloom, "message-type", element->value);
1462             break;
1463
1464           case MATCH_ELEMENT_INTERFACE:
1465             g_kdbus_bloom_add_pair (worker, bloom, "interface", element->value);
1466             break;
1467
1468           case MATCH_ELEMENT_MEMBER:
1469             g_kdbus_bloom_add_pair (worker, bloom, "member", element->value);
1470             break;
1471
1472           case MATCH_ELEMENT_PATH:
1473             g_kdbus_bloom_add_pair (worker, bloom, "path", element->value);
1474             break;
1475
1476           case MATCH_ELEMENT_PATH_NAMESPACE:
1477             if (g_strcmp0 (element->value, "/"))
1478               g_kdbus_bloom_add_pair (worker, bloom, "path-slash-prefix", element->value);
1479             break;
1480
1481           case MATCH_ELEMENT_ARGN:
1482             asprintf (&type, "arg%u", element->arg);
1483             g_kdbus_bloom_add_pair (worker, bloom, type, element->value);
1484             free (type);
1485             break;
1486
1487           case MATCH_ELEMENT_ARGNPATH:
1488             asprintf (&type, "arg%u-slash-prefix", element->arg);
1489             g_kdbus_bloom_add_pair (worker, bloom, type, element->value);
1490             free (type);
1491             break;
1492
1493           case MATCH_ELEMENT_ARG0NAMESPACE:
1494             g_kdbus_bloom_add_pair (worker, bloom, "arg0-dot-prefix", element->value);
1495             break;
1496
1497           case MATCH_ELEMENT_DESTINATION:
1498           case MATCH_ELEMENT_EAVESDROP:
1499             break;
1500         }
1501     }
1502
1503   size += KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, data64) + worker->bloom_size);
1504   cmd = g_alloca0 (size);
1505   cmd->size = size;
1506   cmd->cookie = cookie;
1507
1508   item = cmd->items;
1509   item->size = G_STRUCT_OFFSET(struct kdbus_item, data64) + worker->bloom_size;
1510   item->type = KDBUS_ITEM_BLOOM_MASK;
1511   memcpy(item->data64, bloom, worker->bloom_size);
1512   item = KDBUS_ITEM_NEXT(item);
1513
1514   if (src_id != KDBUS_MATCH_ID_ANY)
1515     {
1516       item->size = G_STRUCT_OFFSET (struct kdbus_item, id) + sizeof(src_id);
1517       item->type = KDBUS_ITEM_ID;
1518       item->id = src_id;
1519       item = KDBUS_ITEM_NEXT(item);
1520     }
1521
1522   if (sender_name)
1523     {
1524       item->size = G_STRUCT_OFFSET (struct kdbus_item, str) + sender_len;
1525       item->type = KDBUS_ITEM_NAME;
1526       memcpy (item->str, sender_name, sender_len);
1527     }
1528
1529   ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1530   if (ret < 0)
1531     g_critical ("Error while adding a match: %d", (int) errno);
1532
1533   match_free (match);
1534 }
1535
1536
1537 /**
1538  * _g_kdbus_RemoveMatch:
1539  *
1540  */
1541 void
1542 _g_kdbus_RemoveMatch (GKDBusWorker  *worker,
1543                       guint64        cookie)
1544 {
1545   struct kdbus_cmd_match cmd = {
1546     .size = sizeof(cmd),
1547     .cookie = cookie
1548   };
1549   gint ret;
1550
1551   g_print ("Unsubscribe match entry with cookie - %d\n", (int)cookie);
1552   ret = ioctl(worker->fd, KDBUS_CMD_MATCH_REMOVE, &cmd);
1553   if (ret < 0)
1554     g_warning ("Error while removing a match: %d\n", errno);
1555 }
1556
1557
1558 /**
1559  * _g_kdbus_subscribe_name_owner_changed_internal:
1560  *
1561  */
1562 static void
1563 _g_kdbus_subscribe_name_owner_changed_internal (GKDBusWorker  *worker,
1564                                                 const gchar   *name,
1565                                                 const gchar   *old_name,
1566                                                 const gchar   *new_name,
1567                                                 guint64        cookie)
1568 {
1569   struct kdbus_item *item;
1570   struct kdbus_cmd_match *cmd;
1571   gssize size, len;
1572   gint ret;
1573   guint64 old_id = 0;
1574   guint64 new_id = KDBUS_MATCH_ID_ANY;
1575
1576   if (name)
1577     len = strlen(name) + 1;
1578   else
1579     len = 0;
1580
1581   size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
1582                       G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1583                       G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
1584
1585   cmd = g_alloca0 (size);
1586   cmd->size = size;
1587   cmd->cookie = cookie;
1588   item = cmd->items;
1589
1590   if (old_name == NULL)
1591     {
1592       old_id = KDBUS_MATCH_ID_ANY;
1593     }
1594   else
1595     {
1596       if (g_dbus_is_unique_name(old_name))
1597         old_id = strtoull (old_name + 3, NULL, 10);
1598       else
1599         return;
1600     }
1601
1602   if (new_name == NULL)
1603     {
1604       new_id = KDBUS_MATCH_ID_ANY;
1605     }
1606   else
1607     {
1608       if (g_dbus_is_unique_name(new_name))
1609         new_id = strtoull (new_name + 3, NULL, 10);
1610       else
1611         return;
1612     }
1613
1614   cmd = g_alloca0 (size);
1615   cmd->size = size;
1616   cmd->cookie = cookie;
1617   item = cmd->items;
1618
1619   /* KDBUS_ITEM_NAME_CHANGE */
1620   item->type = KDBUS_ITEM_NAME_CHANGE;
1621   item->name_change.old_id.id = old_id;
1622   item->name_change.new_id.id = new_id;
1623
1624   if (name)
1625     memcpy(item->name_change.name, name, len);
1626
1627   item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1628                G_STRUCT_OFFSET(struct kdbus_notify_name_change, name) + len;
1629   item = KDBUS_ITEM_NEXT(item);
1630
1631   ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1632   if (ret < 0)
1633     g_warning ("ERROR - %d\n", (int) errno);
1634 }
1635
1636
1637 /**
1638  * _g_kdbus_subscribe_name_acquired:
1639  *
1640  */
1641 void
1642 _g_kdbus_subscribe_name_acquired (GKDBusWorker  *worker,
1643                                   const gchar   *name,
1644                                   guint64        cookie)
1645 {
1646   struct kdbus_item *item;
1647   struct kdbus_cmd_match *cmd;
1648   gssize size, len;
1649   gint ret;
1650
1651   g_print ("Subscribe 'NameAcquired': name - %s ; cookie - %d\n", name, (int)cookie);
1652   if (name)
1653     len = strlen(name) + 1;
1654   else
1655     len = 0;
1656
1657   size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
1658                       G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1659                       G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
1660
1661   cmd = g_alloca0 (size);
1662   cmd->size = size;
1663   cmd->cookie = cookie;
1664   item = cmd->items;
1665
1666   /* KDBUS_ITEM_NAME_ADD */
1667   item->type = KDBUS_ITEM_NAME_ADD;
1668   item->name_change.old_id.id = KDBUS_MATCH_ID_ANY;
1669   item->name_change.new_id.id = worker->unique_id;
1670
1671   if (name)
1672     memcpy(item->name_change.name, name, len);
1673
1674   item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1675                G_STRUCT_OFFSET(struct kdbus_notify_name_change, name) + len;
1676   item = KDBUS_ITEM_NEXT(item);
1677
1678   ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1679   if (ret < 0)
1680     g_warning ("ERROR - %d\n", (int) errno);
1681
1682   _g_kdbus_subscribe_name_owner_changed_internal (worker, name, NULL, worker->unique_name, cookie);
1683 }
1684
1685
1686 /**
1687  * _g_kdbus_subscribe_name_lost:
1688  *
1689  */
1690 void
1691 _g_kdbus_subscribe_name_lost (GKDBusWorker  *worker,
1692                               const gchar   *name,
1693                               guint64        cookie)
1694 {
1695   struct kdbus_item *item;
1696   struct kdbus_cmd_match *cmd;
1697   gssize size, len;
1698   gint ret;
1699
1700   g_print ("Subscribe 'NameLost': name - %s ; cookie - %d\n", name, (int)cookie);
1701   if (name)
1702     len = strlen(name) + 1;
1703   else
1704     len = 0;
1705
1706   size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
1707                       G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1708                       G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
1709
1710   cmd = g_alloca0 (size);
1711   cmd->size = size;
1712   cmd->cookie = cookie;
1713   item = cmd->items;
1714
1715   /* KDBUS_ITEM_NAME_REMOVE */
1716   item->type = KDBUS_ITEM_NAME_REMOVE;
1717   item->name_change.old_id.id = worker->unique_id;
1718   item->name_change.new_id.id = KDBUS_MATCH_ID_ANY;
1719
1720   if (name)
1721     memcpy(item->name_change.name, name, len);
1722
1723   item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1724                G_STRUCT_OFFSET(struct kdbus_notify_name_change, name) + len;
1725   item = KDBUS_ITEM_NEXT(item);
1726
1727   ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1728   if (ret < 0)
1729     g_warning ("ERROR - %d\n", (int) errno);
1730
1731   _g_kdbus_subscribe_name_owner_changed_internal (worker, name, worker->unique_name, NULL, cookie);
1732 }
1733
1734
1735 /**
1736  *
1737  *
1738  */
1739 void
1740 _g_kdbus_subscribe_name_owner_changed (GKDBusWorker  *worker,
1741                                        const gchar   *name,
1742                                        guint64        cookie)
1743 {
1744   g_print ("NameOwnerChanged subscription\n");
1745 }
1746
1747
1748 /**
1749  * g_kdbus_setup_bloom:
1750  * Based on bus-bloom.c from systemd
1751  * http://cgit.freedesktop.org/systemd/systemd/tree/src/libsystemd/sd-bus/bus-bloom.c
1752  */
1753 static void
1754 g_kdbus_setup_bloom (GKDBusWorker                     *worker,
1755                      GDBusMessage               *dbus_msg,
1756                      struct kdbus_bloom_filter  *bloom_filter)
1757 {
1758   GVariant *body;
1759
1760   const gchar *message_type;
1761   const gchar *interface;
1762   const gchar *member;
1763   const gchar *path;
1764
1765   void *bloom_data;
1766
1767   body = g_dbus_message_get_body (dbus_msg);
1768   message_type = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, g_dbus_message_get_message_type (dbus_msg));
1769   interface = g_dbus_message_get_interface (dbus_msg);
1770   member = g_dbus_message_get_member (dbus_msg);
1771   path = g_dbus_message_get_path (dbus_msg);
1772
1773   bloom_data = bloom_filter->data;
1774   memset (bloom_data, 0, worker->bloom_size);
1775   bloom_filter->generation = 0;
1776
1777   g_kdbus_bloom_add_pair(worker, bloom_data, "message-type", message_type);
1778
1779   if (interface)
1780     g_kdbus_bloom_add_pair(worker, bloom_data, "interface", interface);
1781
1782   if (member)
1783     g_kdbus_bloom_add_pair(worker, bloom_data, "member", member);
1784
1785   if (path)
1786     {
1787       g_kdbus_bloom_add_pair(worker, bloom_data, "path", path);
1788       g_kdbus_bloom_add_pair(worker, bloom_data, "path-slash-prefix", path);
1789       g_kdbus_bloom_add_prefixes(worker, bloom_data, "path-slash-prefix", path, '/');
1790     }
1791
1792   if (body != NULL)
1793     {
1794       const GVariantType *body_type;
1795       const GVariantType *arg_type;
1796       guint cnt;
1797
1798       body_type = g_variant_get_type (body);
1799
1800       for (arg_type = g_variant_type_first (body_type), cnt = 0;
1801            arg_type;
1802            arg_type = g_variant_type_next (arg_type), cnt++)
1803         {
1804           gchar type_char = g_variant_type_peek_string (arg_type)[0];
1805           gchar buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1806           const gchar *str;
1807           GVariant *child;
1808           gchar *e;
1809
1810           if (type_char != 's' && type_char != 'o')
1811             /* XXX: kdbus docs say "stop after first non-string" but I
1812              * think they're wrong (vs. dbus-1 compat)...
1813              */
1814             continue;
1815
1816           child = g_variant_get_child_value (body, cnt);
1817           str = g_variant_get_string (child, NULL);
1818
1819           e = stpcpy(buf, "arg");
1820           if (cnt < 10)
1821             *(e++) = '0' + (char) cnt;
1822           else
1823             {
1824               *(e++) = '0' + (char) (cnt / 10);
1825               *(e++) = '0' + (char) (cnt % 10);
1826             }
1827
1828           /* We add this one for both strings and object paths */
1829           strcpy(e, "-slash-prefix");
1830           g_kdbus_bloom_add_prefixes(worker, bloom_data, buf, str, '/');
1831
1832           /* But the others are only for strings */
1833           if (type_char == 's')
1834             {
1835               strcpy(e, "-dot-prefix");
1836               g_kdbus_bloom_add_prefixes(worker, bloom_data, buf, str, '.');
1837
1838               *e = 0;
1839               g_kdbus_bloom_add_pair(worker, bloom_data, buf, str);
1840             }
1841
1842           g_variant_unref (child);
1843         }
1844     }
1845 }
1846
1847
1848 /**
1849  *
1850  *
1851  */
1852 static void
1853 g_kdbus_translate_id_change (GKDBusWorker       *worker,
1854                              struct kdbus_item  *item)
1855 {
1856   g_error ("TODO: translate_id_change\n");
1857 }
1858
1859
1860 /**
1861  *
1862  *
1863  */
1864 static void
1865 g_kdbus_translate_name_change (GKDBusWorker       *worker,
1866                                struct kdbus_item  *item)
1867 {
1868   GDBusMessage *signal_message;
1869
1870   signal_message = NULL;
1871
1872   /* NameAcquired */
1873   if ((item->type == KDBUS_ITEM_NAME_ADD) ||
1874       (item->type == KDBUS_ITEM_NAME_CHANGE && ((guint64)item->name_change.new_id.id == worker->unique_id)))
1875     {
1876       signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
1877                                                   "org.freedesktop.DBus",
1878                                                   "NameAcquired");
1879
1880       g_dbus_message_set_sender (signal_message, "org.freedesktop.DBus");
1881       g_dbus_message_set_body (signal_message,
1882                                g_variant_new ("(s)", item->name_change.name));
1883
1884       (* worker->message_received_callback) (signal_message, worker->user_data);
1885       g_object_unref (signal_message);
1886     }
1887
1888   /* NameLost */
1889   if ((item->type == KDBUS_ITEM_NAME_REMOVE) ||
1890       (item->type == KDBUS_ITEM_NAME_CHANGE && ((guint64)item->name_change.old_id.id == worker->unique_id)))
1891     {
1892       GDBusMessage *signal_message;
1893
1894       signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
1895                                                   "org.freedesktop.DBus",
1896                                                   "NameLost");
1897
1898       g_dbus_message_set_sender (signal_message, "org.freedesktop.DBus");
1899       g_dbus_message_set_body (signal_message,
1900                                g_variant_new ("(s)", item->name_change.name));
1901
1902       (* worker->message_received_callback) (signal_message, worker->user_data);
1903       g_object_unref (signal_message);
1904     }
1905
1906   /* NameOwnerChanged */
1907   /* TODO */
1908 }
1909
1910
1911 /**
1912  *
1913  *
1914  */
1915 static void
1916 g_kdbus_translate_kernel_reply (GKDBusWorker       *worker,
1917                                 struct kdbus_item  *item)
1918 {
1919   g_error ("TODO: translate_kernel_reply\n");
1920 }
1921
1922
1923 /**
1924  * g_kdbus_decode_kernel_msg:
1925  *
1926  */
1927 static void
1928 g_kdbus_decode_kernel_msg (GKDBusWorker           *worker,
1929                            struct kdbus_msg *msg)
1930 {
1931   struct kdbus_item *item = NULL;
1932
1933   KDBUS_ITEM_FOREACH(item, msg, items)
1934     {
1935      switch (item->type)
1936         {
1937           case KDBUS_ITEM_ID_ADD:
1938           case KDBUS_ITEM_ID_REMOVE:
1939             g_kdbus_translate_id_change (worker, item);
1940             break;
1941
1942           case KDBUS_ITEM_NAME_ADD:
1943           case KDBUS_ITEM_NAME_REMOVE:
1944           case KDBUS_ITEM_NAME_CHANGE:
1945             g_kdbus_translate_name_change (worker, item);
1946             break;
1947
1948           case KDBUS_ITEM_REPLY_TIMEOUT:
1949           case KDBUS_ITEM_REPLY_DEAD:
1950             g_kdbus_translate_kernel_reply (worker, item);
1951             break;
1952
1953           case KDBUS_ITEM_TIMESTAMP:
1954             break;
1955
1956           default:
1957             g_warning ("Unknown field in kernel message - %lld", item->type);
1958        }
1959     }
1960 }
1961
1962
1963 /**
1964  * g_kdbus_decode_dbus_msg:
1965  *
1966  */
1967 static GDBusMessage *
1968 g_kdbus_decode_dbus_msg (GKDBusWorker           *worker,
1969                          struct kdbus_msg *msg)
1970 {
1971   GDBusMessage *message;
1972   struct kdbus_item *item;
1973   gssize data_size = 0;
1974   GArray *body_vectors;
1975   gsize body_size;
1976   GVariant *body;
1977   gchar *tmp;
1978   guint i;
1979   GVariant *parts[2];
1980   GVariantIter *fields_iter;
1981   guint8 endianness, type, flags, version;
1982   guint64 key;
1983   GVariant *value;
1984   guint64 serial;
1985
1986
1987   message = g_dbus_message_new ();
1988
1989   body_vectors = g_array_new (FALSE, FALSE, sizeof (GVariantVector));
1990
1991   tmp = g_strdup_printf (":1.%"G_GUINT64_FORMAT, (guint64) msg->src_id);
1992   g_dbus_message_set_sender (message, tmp);
1993   g_free (tmp);
1994
1995   item = msg->items;
1996   body_size = 0;
1997
1998   KDBUS_ITEM_FOREACH(item, msg, items)
1999     {
2000       if (item->size <= KDBUS_ITEM_HEADER_SIZE)
2001         g_error("[KDBUS] %llu bytes - invalid data record\n", item->size);
2002
2003       data_size = item->size - KDBUS_ITEM_HEADER_SIZE;
2004
2005       switch (item->type)
2006         {
2007          /* KDBUS_ITEM_DST_NAME */
2008          case KDBUS_ITEM_DST_NAME:
2009            /* Classic D-Bus doesn't make this known to the receiver, so
2010             * we don't do it here either (for compatibility with the
2011             * fallback case).
2012             */
2013            break;
2014
2015         /* KDBUS_ITEM_PALOAD_OFF */
2016         case KDBUS_ITEM_PAYLOAD_OFF:
2017           {
2018             GVariantVector vector;
2019             gsize flavour;
2020
2021             /* We want to make sure the bytes are aligned the same as
2022              * they would be if they appeared in a contiguously
2023              * allocated chunk of aligned memory.
2024              *
2025              * We decide what the alignment 'should' be by consulting
2026              * body_size, which has been tracking the total size of the
2027              * message up to this point.
2028              *
2029              * We then play around with the pointer by removing as many
2030              * bytes as required to get it to the proper alignment (and
2031              * copy extra bytes accordingly).  This means that we will
2032              * grab some extra data in the 'bytes', but it won't be
2033              * shared with GVariant (which means there is no chance of
2034              * it being accidentally retransmitted).
2035              *
2036              * The kernel does the same thing, so make sure we get the
2037              * expected result.  Because of the kernel doing the same,
2038              * the result is that we will always be rounding-down to a
2039              * multiple of 8 for the pointer, which means that the
2040              * pointer will always be valid, assuming the original
2041              * address was.
2042              *
2043              * We could fix this with a new GBytes constructor that took
2044              * 'flavour' as a parameter, but it's not worth it...
2045              */
2046             flavour = body_size & 7;
2047             g_assert ((item->vec.offset & 7) == flavour);
2048
2049             vector.gbytes = g_bytes_new (((guchar *) msg) + item->vec.offset - flavour, item->vec.size + flavour);
2050             vector.data.pointer = g_bytes_get_data (vector.gbytes, NULL);
2051             vector.data.pointer += flavour;
2052             vector.size = item->vec.size;
2053
2054             g_array_append_val (body_vectors, vector);
2055             body_size += vector.size;
2056           }
2057           break;
2058
2059         /* KDBUS_ITEM_PAYLOAD_MEMFD */
2060         case KDBUS_ITEM_PAYLOAD_MEMFD:
2061           {
2062             GVariantVector vector;
2063             const guchar *data;
2064             gsize size;
2065
2066             vector.gbytes = g_bytes_new_take_zero_copy_fd (item->memfd.fd);
2067             data = g_bytes_get_data (vector.gbytes, &size);
2068
2069             g_assert (item->memfd.start + item->memfd.size <= size);
2070
2071             vector.data.pointer = data + item->memfd.start;
2072             vector.size = item->memfd.size;
2073
2074             g_array_append_val (body_vectors, vector);
2075             body_size += vector.size;
2076           }
2077           break;
2078
2079         /* KDBUS_ITEM_FDS */
2080         case KDBUS_ITEM_FDS:
2081           {
2082             GUnixFDList *fd_list;
2083
2084             fd_list = g_unix_fd_list_new_from_array (item->fds, data_size / sizeof (int));
2085             g_dbus_message_set_unix_fd_list (message, fd_list);
2086             g_object_unref (fd_list);
2087           }
2088           break;
2089
2090         /* All of the following items, like CMDLINE,
2091            CGROUP, etc. need some GDBUS API extensions and
2092            should be implemented in the future */
2093         case KDBUS_ITEM_TIMESTAMP:
2094           {
2095             /* g_print ("time: seq %llu mon %llu real %llu\n",
2096                      item->timestamp.seqnum, item->timestamp.monotonic_ns, item->timestamp.realtime_ns); */
2097
2098             //g_dbus_message_set_timestamp (message, item->timestamp.monotonic_ns / 1000);
2099             //g_dbus_message_set_serial (message, item->timestamp.seqnum);
2100             break;
2101           }
2102
2103         case KDBUS_ITEM_CREDS:
2104           {
2105             /* g_print ("creds: u%llu eu %llu su%llu fsu%llu g%llu eg%llu sg%llu fsg%llu\n",
2106                      item->creds.uid, item->creds.euid, item->creds.suid, item->creds.fsuid,
2107                      item->creds.gid, item->creds.egid, item->creds.sgid, item->creds.fsgid); */
2108             break;
2109           }
2110
2111         case KDBUS_ITEM_PIDS:
2112         case KDBUS_ITEM_PID_COMM:
2113         case KDBUS_ITEM_TID_COMM:
2114         case KDBUS_ITEM_EXE:
2115         case KDBUS_ITEM_CMDLINE:
2116         case KDBUS_ITEM_CGROUP:
2117         case KDBUS_ITEM_AUDIT:
2118         case KDBUS_ITEM_CAPS:
2119         case KDBUS_ITEM_SECLABEL:
2120         case KDBUS_ITEM_CONN_DESCRIPTION:
2121         case KDBUS_ITEM_AUXGROUPS:
2122         case KDBUS_ITEM_OWNED_NAME:
2123         case KDBUS_ITEM_NAME:
2124           //g_print ("unhandled %04x\n", (int) item->type);
2125           break;
2126
2127         default:
2128           g_error ("[KDBUS] DBUS_PAYLOAD: Unknown filed - %lld", item->type);
2129           break;
2130         }
2131     }
2132
2133   body = GLIB_PRIVATE_CALL(g_variant_from_vectors) (G_VARIANT_TYPE ("((yyyyuta{tv})v)"),
2134                                                     (GVariantVector *) body_vectors->data,
2135                                                     body_vectors->len, body_size, FALSE);
2136   g_assert (body);
2137
2138   for (i = 0; i < body_vectors->len; i++)
2139     g_bytes_unref (g_array_index (body_vectors, GVariantVector, i).gbytes);
2140
2141   g_array_free (body_vectors, TRUE);
2142
2143   parts[0] = g_variant_get_child_value (body, 0);
2144   parts[1] = g_variant_get_child_value (body, 1);
2145   g_variant_unref (body);
2146
2147   g_variant_get (parts[0], "(yyyyuta{tv})", &endianness, &type, &flags, &version, NULL, &serial, &fields_iter);
2148   g_variant_unref (parts[0]);
2149
2150   while (g_variant_iter_loop (fields_iter, "{tv}", &key, &value))
2151     g_dbus_message_set_header (message, key, value);
2152
2153   g_dbus_message_set_flags (message, flags);
2154   g_dbus_message_set_serial (message, serial);
2155   g_dbus_message_set_message_type (message, type);
2156
2157   //if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE) != NULL)
2158   //  {
2159       body = g_variant_get_variant (parts[1]);
2160       g_dbus_message_set_body (message, body);
2161       g_variant_unref (body);
2162   //  }
2163   g_variant_unref (parts[1]);
2164
2165   //g_print ("Received:\n%s\n", g_dbus_message_print (message, 2));
2166
2167   (* worker->message_received_callback) (message, worker->user_data);
2168
2169   g_object_unref (message);
2170
2171   return 0;
2172 }
2173
2174
2175 /**
2176  * _g_kdbus_receive:
2177  *
2178  */
2179 static gssize
2180 _g_kdbus_receive (GKDBusWorker        *kdbus,
2181                   GCancellable  *cancellable,
2182                   GError       **error)
2183 {
2184   struct kdbus_cmd_recv recv;
2185   struct kdbus_msg *msg;
2186
2187   memset (&recv, 0, sizeof recv);
2188   recv.size = sizeof (recv);
2189
2190   if (g_cancellable_set_error_if_cancelled (cancellable, error))
2191     return -1;
2192
2193 again:
2194     if (ioctl(kdbus->fd, KDBUS_CMD_RECV, &recv) < 0)
2195       {
2196         if (errno == EINTR)
2197           goto again;
2198
2199         if (errno == EAGAIN)
2200           return 0;
2201
2202         g_warning ("in holding pattern over %d %d\n", kdbus->fd, errno);
2203         while (1)
2204           sleep(1);
2205
2206         g_set_error (error, G_IO_ERROR,
2207                      g_io_error_from_errno (errno),
2208                      _("Error while receiving message: %s"),
2209                      g_strerror (errno));
2210         return -1;
2211       }
2212
2213    msg = (struct kdbus_msg *)((guint8 *)kdbus->kdbus_buffer + recv.msg.offset);
2214
2215    if (msg->payload_type == KDBUS_PAYLOAD_DBUS)
2216      g_kdbus_decode_dbus_msg (kdbus, msg);
2217    else if (msg->payload_type == KDBUS_PAYLOAD_KERNEL)
2218      g_kdbus_decode_kernel_msg (kdbus, msg);
2219    else
2220      {
2221        g_set_error (error,
2222                     G_DBUS_ERROR,
2223                     G_DBUS_ERROR_FAILED,
2224                     _("Received unknown payload type"));
2225        return -1;
2226      }
2227
2228   g_kdbus_free_data (kdbus, recv.msg.offset);
2229
2230   return 0;
2231 }
2232
2233 static gboolean
2234 g_kdbus_msg_append_item (struct kdbus_msg *msg,
2235                          gsize             type,
2236                          gconstpointer     data,
2237                          gsize             size)
2238 {
2239   struct kdbus_item *item;
2240   gsize item_size;
2241
2242   item_size = size + G_STRUCT_OFFSET(struct kdbus_item, data);
2243
2244   if (msg->size + item_size > KDBUS_MSG_MAX_SIZE)
2245     return FALSE;
2246
2247   /* align */
2248   msg->size += (-msg->size) & 7;
2249   item = (struct kdbus_item *) ((guchar *) msg + msg->size);
2250   item->type = type;
2251   item->size = item_size;
2252   memcpy (item->data, data, size);
2253
2254   msg->size += item_size;
2255
2256   return TRUE;
2257 }
2258
2259 static gboolean
2260 g_kdbus_msg_append_payload_vec (struct kdbus_msg *msg,
2261                                 gconstpointer     data,
2262                                 gsize             size)
2263 {
2264   struct kdbus_vec vec = {
2265     .size = size,
2266     .address = (gsize) data
2267   };
2268
2269   return g_kdbus_msg_append_item (msg, KDBUS_ITEM_PAYLOAD_VEC, &vec, sizeof vec);
2270 }
2271
2272 static gboolean
2273 g_kdbus_msg_append_payload_memfd (struct kdbus_msg *msg,
2274                                   gint              fd,
2275                                   gsize             offset,
2276                                   gsize             size)
2277 {
2278   struct kdbus_memfd mfd = {
2279    .start = offset,
2280    .size = size,
2281    .fd = fd,
2282   };
2283
2284   return g_kdbus_msg_append_item (msg, KDBUS_ITEM_PAYLOAD_MEMFD, &mfd, sizeof mfd);
2285 }
2286
2287 static struct kdbus_bloom_filter *
2288 g_kdbus_msg_append_bloom (struct kdbus_msg *msg,
2289                           gsize             size)
2290 {
2291   struct kdbus_item *bloom_item;
2292
2293   /* align */
2294   msg->size += (-msg->size) & 7;
2295   bloom_item = (struct kdbus_item *) ((guchar *) msg + msg->size);
2296
2297   /* set size and type */
2298   bloom_item->size = G_STRUCT_OFFSET (struct kdbus_item, bloom_filter) +
2299                      G_STRUCT_OFFSET (struct kdbus_bloom_filter, data) +
2300                      size;
2301   bloom_item->type = KDBUS_ITEM_BLOOM_FILTER;
2302
2303   msg->size += bloom_item->size;
2304   return &bloom_item->bloom_filter;
2305 }
2306
2307 #if 0
2308 #include "dbusheader.h"
2309
2310 void dump_header (gconstpointer data, gsize size) ;
2311 void
2312 dump_header (gconstpointer data,
2313              gsize size)
2314 {
2315   GDBusMessageHeaderFieldsIterator iter;
2316   GDBusMessageHeader header;
2317
2318   header = g_dbus_message_header_new (data, size);
2319   g_print ("header e/%c t/%u f/x%x v/%u s/%"G_GUINT64_FORMAT"\n",
2320            g_dbus_message_header_get_endian (header),
2321            g_dbus_message_header_get_type (header),
2322            g_dbus_message_header_get_flags (header),
2323            g_dbus_message_header_get_version (header),
2324            g_dbus_message_header_get_serial (header));
2325
2326   iter = g_dbus_message_header_iterate_fields (header);
2327
2328   while (g_dbus_message_header_fields_iterator_next (&iter))
2329     {
2330       const gchar *string;
2331       guint64 reply_to;
2332       guint64 key;
2333
2334       key = g_dbus_message_header_fields_iterator_get_key (iter);
2335
2336       switch (key)
2337         {
2338           case G_DBUS_MESSAGE_HEADER_FIELD_PATH:
2339             if (g_dbus_message_header_fields_iterator_get_value_as_object_path (iter, &string))
2340               g_print ("  path: %s\n", string);
2341             else
2342               g_print ("  path: <<invalid string>>\n");
2343             break;
2344
2345           case G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE:
2346             if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2347               g_print ("  interface: %s\n", string);
2348             else
2349               g_print ("  interface: <<invalid string>>\n");
2350             break;
2351
2352           case G_DBUS_MESSAGE_HEADER_FIELD_MEMBER:
2353             if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2354               g_print ("  member: %s\n", string);
2355             else
2356               g_print ("  member: <<invalid string>>\n");
2357             break;
2358
2359           case G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME:
2360             if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2361               g_print ("  error: %s\n", string);
2362             else
2363               g_print ("  error: <<invalid string>>\n");
2364             break;
2365
2366           case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL:
2367             if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2368               g_print ("  serial: %s\n", string);
2369             else
2370               g_print ("  serial: <<invalid string>>\n");
2371             break;
2372
2373           case G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION:
2374             if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2375               g_print ("  destination: %s\n", string);
2376             else
2377               g_print ("  destination: <<invalid string>>\n");
2378             break;
2379
2380           case G_DBUS_MESSAGE_HEADER_FIELD_SENDER:
2381             if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2382               g_print ("  sender: %s\n", string);
2383             else
2384               g_print ("  sender: <<invalid string>>\n");
2385             break;
2386
2387           default:
2388             g_print ("unknown field code %"G_GUINT64_FORMAT"\n", key);
2389             g_assert_not_reached ();
2390         }
2391     }
2392
2393   g_print ("\n");
2394
2395 }
2396 #endif
2397
2398 /**
2399  * _g_kdbus_send:
2400  * Returns: size of data sent or -1 when error
2401  */
2402 static gboolean
2403 _g_kdbus_send (GKDBusWorker        *kdbus,
2404                GDBusMessage  *message,
2405                GError       **error)
2406 {
2407   struct kdbus_msg *msg = alloca (KDBUS_MSG_MAX_SIZE);
2408   GVariantVectors body_vectors;
2409   struct kdbus_cmd_send send;
2410   const gchar *dst_name;
2411
2412   g_return_val_if_fail (G_IS_KDBUS_WORKER (kdbus), -1);
2413
2414   /* fill in as we go... */
2415   memset (msg, 0, sizeof (struct kdbus_msg));
2416   msg->size = sizeof (struct kdbus_msg);
2417   msg->payload_type = KDBUS_PAYLOAD_DBUS;
2418   msg->src_id = kdbus->unique_id;
2419   msg->cookie = g_dbus_message_get_serial(message);
2420
2421   /* Message destination */
2422   {
2423     dst_name = g_dbus_message_get_destination (message);
2424
2425     if (dst_name != NULL)
2426       {
2427         if (g_dbus_is_unique_name (dst_name))
2428           {
2429             if (dst_name[1] != '1' || dst_name[2] != '.')
2430               {
2431                 g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
2432                              "Invalid unique D-Bus name '%s'", dst_name);
2433                 return FALSE;
2434               }
2435
2436             /* We already know that it passes the checks for unique
2437              * names, so no need to perform error checking on strtoull.
2438              */
2439             msg->dst_id = strtoull (dst_name + 3, NULL, 10);
2440             dst_name = NULL;
2441           }
2442         else
2443           {
2444             g_kdbus_msg_append_item (msg, KDBUS_ITEM_DST_NAME, dst_name, strlen (dst_name) + 1);
2445             msg->dst_id = KDBUS_DST_ID_NAME;
2446           }
2447       }
2448     else
2449       msg->dst_id = KDBUS_DST_ID_BROADCAST;
2450   }
2451
2452   /* File descriptors */
2453   {
2454     GUnixFDList *fd_list;
2455
2456     fd_list = g_dbus_message_get_unix_fd_list (message);
2457
2458     if (fd_list != NULL)
2459       {
2460         const gint *fds;
2461         gint n_fds;
2462
2463         fds = g_unix_fd_list_peek_fds (fd_list, &n_fds);
2464
2465         if (n_fds)
2466           g_kdbus_msg_append_item (msg, KDBUS_ITEM_FDS, fds, sizeof (gint) * n_fds);
2467       }
2468   }
2469
2470   /* Message body */
2471   {
2472     struct dbus_fixed_header fh;
2473     GHashTableIter header_iter;
2474     GVariantBuilder builder;
2475     gpointer key, value;
2476     GVariant *parts[3];
2477     GVariant *body;
2478
2479     fh.endian = (G_BYTE_ORDER == G_LITTLE_ENDIAN) ? 'l': 'B';
2480     fh.type = g_dbus_message_get_message_type (message);
2481     fh.flags = g_dbus_message_get_flags (message);
2482     fh.version = 2;
2483     fh.reserved = 0;
2484     fh.serial = g_dbus_message_get_serial (message);
2485     parts[0] = g_variant_new_from_data (DBUS_FIXED_HEADER_TYPE, &fh, sizeof fh, TRUE, NULL, NULL);
2486
2487     g_dbus_message_init_header_iter (message, &header_iter);
2488     g_variant_builder_init (&builder, DBUS_EXTENDED_HEADER_TYPE);
2489
2490     /* We set the sender field to the correct value for ourselves */
2491     g_variant_builder_add (&builder, "{tv}",
2492                            (guint64) G_DBUS_MESSAGE_HEADER_FIELD_SENDER,
2493                            g_variant_new_printf (":1.%"G_GUINT64_FORMAT, kdbus->unique_id));
2494
2495     while (g_hash_table_iter_next (&header_iter, &key, &value))
2496       {
2497         guint64 key_int = (gsize) key;
2498
2499         switch (key_int)
2500           {
2501             /* These are the normal header fields that get passed
2502              * straight through.
2503              */
2504             case G_DBUS_MESSAGE_HEADER_FIELD_PATH:
2505             case G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE:
2506             case G_DBUS_MESSAGE_HEADER_FIELD_MEMBER:
2507             case G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME:
2508             case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL:
2509             case G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION:
2510               g_variant_builder_add (&builder, "{tv}", key_int, value);
2511               /* This is a little bit gross.
2512                *
2513                * We must send the header part of the message in a single
2514                * vector as per kdbus rules, but the GVariant serialiser
2515                * code will split any item >= 128 bytes into its own
2516                * vector to save the copy.
2517                *
2518                * No header field should be that big anyway... right?
2519                */
2520               g_assert_cmpint (g_variant_get_size (value), <, 128);
2521               continue;
2522
2523             /* We send this one unconditionally, but set it ourselves */
2524             case G_DBUS_MESSAGE_HEADER_FIELD_SENDER:
2525               continue;
2526
2527             /* We don't send these at all in GVariant format */
2528             case G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE:
2529             case G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS:
2530               continue;
2531
2532             default:
2533               g_assert_not_reached ();
2534           }
2535       }
2536     parts[1] = g_variant_builder_end (&builder);
2537
2538     body = g_dbus_message_get_body (message);
2539     if (!body)
2540       body = g_variant_new ("()");
2541     parts[2] = g_variant_new_variant (body);
2542
2543     body = g_variant_ref_sink (g_variant_new_tuple (parts, G_N_ELEMENTS (parts)));
2544     GLIB_PRIVATE_CALL(g_variant_to_vectors) (body, &body_vectors);
2545
2546     /* Sanity check to make sure the header is really contiguous:
2547      *
2548      *  - we must have at least one vector in the output
2549      *  - the first vector must completely contain at least the header
2550      */
2551     g_assert_cmpint (body_vectors.vectors->len, >, 0);
2552     g_assert_cmpint (g_array_index (body_vectors.vectors, GVariantVector, 0).size, >=,
2553                      g_variant_get_size (parts[0]) + g_variant_get_size (parts[1]));
2554
2555     g_variant_unref (body);
2556   }
2557
2558   {
2559     guint i;
2560
2561     for (i = 0; i < body_vectors.vectors->len; i++)
2562       {
2563         GVariantVector vector = g_array_index (body_vectors.vectors, GVariantVector, i);
2564
2565         if (vector.gbytes)
2566           {
2567             gint fd;
2568
2569             fd = g_bytes_get_zero_copy_fd (vector.gbytes);
2570
2571             if (fd >= 0)
2572               {
2573                 const guchar *bytes_data;
2574                 gsize bytes_size;
2575
2576                 bytes_data = g_bytes_get_data (vector.gbytes, &bytes_size);
2577
2578                 if (bytes_data <= vector.data.pointer && vector.data.pointer + vector.size <= bytes_data + bytes_size)
2579                   {
2580                     if (!g_kdbus_msg_append_payload_memfd (msg, fd, vector.data.pointer - bytes_data, vector.size))
2581                       goto need_compact;
2582                   }
2583                 else
2584                   {
2585                     if (!g_kdbus_msg_append_payload_vec (msg, vector.data.pointer, vector.size))
2586                       goto need_compact;
2587                   }
2588               }
2589             else
2590               {
2591                 if (!g_kdbus_msg_append_payload_vec (msg, vector.data.pointer, vector.size))
2592                   goto need_compact;
2593               }
2594           }
2595         else
2596           if (!g_kdbus_msg_append_payload_vec (msg, body_vectors.extra_bytes->data + vector.data.offset, vector.size))
2597             goto need_compact;
2598       }
2599   }
2600
2601   /*
2602    * set message flags
2603    */
2604   msg->flags = ((g_dbus_message_get_flags (message) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_EXPECT_REPLY) |
2605                 ((g_dbus_message_get_flags (message) & G_DBUS_MESSAGE_FLAGS_NO_AUTO_START) ? KDBUS_MSG_NO_AUTO_START : 0);
2606
2607   if ((msg->flags) & KDBUS_MSG_EXPECT_REPLY)
2608     msg->timeout_ns = 1000LU * g_get_monotonic_time() + KDBUS_TIMEOUT_NS;
2609   else
2610     msg->cookie_reply = g_dbus_message_get_reply_serial(message);
2611
2612   if (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_SIGNAL)
2613     msg->flags |= KDBUS_MSG_SIGNAL;
2614
2615   /*
2616    *
2617    */
2618   if (msg->dst_id == KDBUS_DST_ID_BROADCAST)
2619     {
2620       struct kdbus_bloom_filter *bloom_filter;
2621
2622       bloom_filter = g_kdbus_msg_append_bloom (msg, kdbus->bloom_size);
2623       g_kdbus_setup_bloom (kdbus, message, bloom_filter);
2624     }
2625
2626   send.size = sizeof (send);
2627   send.flags = 0;
2628   send.msg_address = (gsize) msg;
2629
2630   /*
2631    * send message
2632    */
2633   if (ioctl(kdbus->fd, KDBUS_CMD_SEND, &send))
2634     {
2635       if (errno == ENXIO || errno == ESRCH)
2636         {
2637           g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
2638                        "Destination '%s' not known", dst_name);
2639         }
2640       else if (errno == EADDRNOTAVAIL)
2641         {
2642           g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
2643                        "No support for activation for name: %s", dst_name);
2644         }
2645       else if (errno == EXFULL)
2646         {
2647           g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_LIMITS_EXCEEDED,
2648                        "The memory pool of the receiver is full");
2649         }
2650       else
2651         {
2652           g_error ("WTF? %d\n", errno);
2653           g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
2654                        "%s", strerror(errno));
2655         }
2656       return FALSE;
2657     }
2658
2659   return TRUE;
2660
2661 need_compact:
2662   /* We end up here if:
2663    *  - too many kdbus_items
2664    *  - too large kdbus_msg size
2665    *  - too much vector data
2666    *
2667    * We need to compact the message before sending it.
2668    */
2669   g_assert_not_reached ();
2670 }
2671
2672 GKDBusWorker *
2673 g_kdbus_worker_new (const gchar  *address,
2674                     GError      **error)
2675 {
2676   GKDBusWorker *worker;
2677
2678   worker = g_object_new (G_TYPE_KDBUS_WORKER, NULL);
2679   if (!_g_kdbus_open (worker, address, error))
2680     {
2681       g_object_unref (worker);
2682       return NULL;
2683     }
2684
2685   return worker;
2686 }
2687
2688 void
2689 g_kdbus_worker_associate (GKDBusWorker                            *worker,
2690                           GDBusCapabilityFlags                     capabilities,
2691                           GDBusWorkerMessageReceivedCallback       message_received_callback,
2692                           GDBusWorkerMessageAboutToBeSentCallback  message_about_to_be_sent_callback,
2693                           GDBusWorkerDisconnectedCallback          disconnected_callback,
2694                           gpointer                                 user_data)
2695 {
2696   worker->capabilities = capabilities;
2697   worker->message_received_callback = message_received_callback;
2698   worker->message_about_to_be_sent_callback = message_about_to_be_sent_callback;
2699   worker->disconnected_callback = disconnected_callback;
2700   worker->user_data = user_data;
2701 }
2702
2703 void
2704 g_kdbus_worker_unfreeze (GKDBusWorker *worker)
2705 {
2706   gchar *name;
2707
2708   if (worker->source != NULL)
2709     return;
2710
2711   worker->context = g_main_context_ref_thread_default ();
2712   worker->source = g_unix_fd_source_new (worker->fd, G_IO_IN);
2713
2714   g_source_set_callback (worker->source, (GSourceFunc) kdbus_ready, worker, NULL);
2715   name = g_strdup_printf ("kdbus worker");
2716   g_source_set_name (worker->source, name);
2717   g_free (name);
2718
2719   g_source_attach (worker->source, worker->context);
2720 }
2721
2722 gboolean
2723 g_kdbus_worker_send_message (GKDBusWorker  *worker,
2724                              GDBusMessage  *message,
2725                              GError       **error)
2726 {
2727   return _g_kdbus_send (worker, message, error);
2728 }
2729
2730 void
2731 g_kdbus_worker_stop (GKDBusWorker *worker)
2732 {
2733 }
2734
2735 void
2736 g_kdbus_worker_flush_sync (GKDBusWorker *worker)
2737 {
2738 }
2739
2740 void
2741 g_kdbus_worker_close (GKDBusWorker       *worker,
2742                       GCancellable       *cancellable,
2743                       GSimpleAsyncResult *result)
2744 {
2745 }