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