[kdbus] Make SipHash function as a private utility function to kdbus
[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->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                    guint          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: %d", cookie);
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", cookie);
1514
1515   match_free (match);
1516 }
1517
1518
1519 /**
1520  * _g_kdbus_RemoveMatch:
1521  *
1522  */
1523 void
1524 _g_kdbus_RemoveMatch (GKDBusWorker  *worker,
1525                       guint          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", (int) 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; /* XXX why? */
1555   guint64 new_id = KDBUS_MATCH_ID_ANY;
1556
1557   len = strlen(name) + 1;
1558   size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
1559                       G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1560                       G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
1561
1562   cmd = g_alloca0 (size);
1563   cmd->size = size;
1564   cmd->cookie = cookie;
1565   item = cmd->items;
1566
1567   if (old_name[0] == 0)
1568     {
1569       old_id = KDBUS_MATCH_ID_ANY;
1570     }
1571   else
1572     {
1573       if (g_dbus_is_unique_name(old_name))
1574         old_id = old_id+3;
1575       else
1576         return;
1577     }
1578
1579   if (new_name[0] == 0)
1580     {
1581       new_id = KDBUS_MATCH_ID_ANY;
1582     }
1583   else
1584     {
1585       if (g_dbus_is_unique_name(new_name))
1586         new_id = new_id+3;
1587       else
1588         return;
1589     }
1590
1591   cmd = g_alloca0 (size);
1592   cmd->size = size;
1593   cmd->cookie = cookie;
1594   item = cmd->items;
1595
1596   /* KDBUS_ITEM_NAME_CHANGE */
1597   item->type = KDBUS_ITEM_NAME_CHANGE;
1598   item->name_change.old_id.id = old_id;
1599   item->name_change.new_id.id = new_id;
1600   memcpy(item->name_change.name, name, len);
1601   item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1602                G_STRUCT_OFFSET(struct kdbus_notify_name_change, name) + len;
1603   item = KDBUS_ITEM_NEXT(item);
1604
1605   ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1606   if (ret < 0)
1607     g_warning ("ERROR - %d\n", (int) errno);
1608 }
1609
1610
1611 /**
1612  * _g_kdbus_subscribe_name_acquired:
1613  *
1614  */
1615 void
1616 _g_kdbus_subscribe_name_acquired (GKDBusWorker  *worker,
1617                                   const gchar      *name)
1618 {
1619   struct kdbus_item *item;
1620   struct kdbus_cmd_match *cmd;
1621   gssize size, len;
1622   guint64 cookie;
1623   gint ret;
1624
1625   len = strlen(name) + 1;
1626   size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
1627                       G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1628                       G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
1629
1630   cookie = 0xbeefbeefbeefbeef;
1631   cmd = g_alloca0 (size);
1632   cmd->size = size;
1633   cmd->cookie = cookie;
1634   item = cmd->items;
1635
1636   /* KDBUS_ITEM_NAME_ADD */
1637   item->type = KDBUS_ITEM_NAME_ADD;
1638   item->name_change.old_id.id = KDBUS_MATCH_ID_ANY;
1639   item->name_change.new_id.id = worker->unique_id;
1640   memcpy(item->name_change.name, name, len);
1641   item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1642                G_STRUCT_OFFSET(struct kdbus_notify_name_change, name) + len;
1643   item = KDBUS_ITEM_NEXT(item);
1644
1645   ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1646   if (ret < 0)
1647     g_warning ("ERROR - %d\n", (int) errno);
1648
1649   _g_kdbus_subscribe_name_owner_changed (worker, name, "", worker->unique_name, cookie);
1650 }
1651
1652
1653 /**
1654  * _g_kdbus_subscribe_name_lost:
1655  *
1656  */
1657 void
1658 _g_kdbus_subscribe_name_lost (GKDBusWorker  *worker,
1659                               const gchar      *name)
1660 {
1661   struct kdbus_item *item;
1662   struct kdbus_cmd_match *cmd;
1663   gssize size, len;
1664   guint64 cookie;
1665   gint ret;
1666
1667   len = strlen(name) + 1;
1668   size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
1669                       G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1670                       G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
1671
1672   cookie = 0xdeafdeafdeafdeaf;
1673   cmd = g_alloca0 (size);
1674   cmd->size = size;
1675   cmd->cookie = cookie;
1676   item = cmd->items;
1677
1678   /* KDBUS_ITEM_NAME_REMOVE */
1679   item->type = KDBUS_ITEM_NAME_REMOVE;
1680   item->name_change.old_id.id = worker->unique_id;
1681   item->name_change.new_id.id = KDBUS_MATCH_ID_ANY;
1682   memcpy(item->name_change.name, name, len);
1683   item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1684                G_STRUCT_OFFSET(struct kdbus_notify_name_change, name) + len;
1685   item = KDBUS_ITEM_NEXT(item);
1686
1687   ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1688   if (ret < 0)
1689     g_warning ("ERROR - %d\n", (int) errno);
1690
1691   _g_kdbus_subscribe_name_owner_changed (worker, name, worker->unique_name, "", cookie);
1692 }
1693
1694
1695 /**
1696  * _g_kdbus_unsubscribe_name_acquired:
1697  *
1698  */
1699 void
1700 _g_kdbus_unsubscribe_name_acquired (GKDBusWorker  *worker)
1701 {
1702   guint64 cookie;
1703
1704   cookie = 0xbeefbeefbeefbeef;
1705   _g_kdbus_RemoveMatch (worker, cookie);
1706 }
1707
1708
1709 /**
1710  * _g_kdbus_unsubscribe_name_lost:
1711  *
1712  */
1713 void
1714 _g_kdbus_unsubscribe_name_lost (GKDBusWorker  *worker)
1715 {
1716   guint64 cookie;
1717
1718   cookie = 0xdeafdeafdeafdeaf;
1719   _g_kdbus_RemoveMatch (worker, cookie);
1720 }
1721
1722
1723 /**
1724  * g_kdbus_append_payload_bloom:
1725  *
1726  */
1727 static struct kdbus_bloom_filter *
1728 g_kdbus_append_bloom (struct kdbus_item **item,
1729                       gsize               size)
1730 {
1731   struct kdbus_item *bloom_item;
1732
1733   bloom_item = KDBUS_ALIGN8_PTR(*item);
1734   bloom_item->size = G_STRUCT_OFFSET (struct kdbus_item, bloom_filter) +
1735                      G_STRUCT_OFFSET (struct kdbus_bloom_filter, data) +
1736                      size;
1737
1738   bloom_item->type = KDBUS_ITEM_BLOOM_FILTER;
1739
1740   *item = KDBUS_ITEM_NEXT(bloom_item);
1741   return &bloom_item->bloom_filter;
1742 }
1743
1744
1745 /**
1746  * g_kdbus_setup_bloom:
1747  * Based on bus-bloom.c from systemd
1748  * http://cgit.freedesktop.org/systemd/systemd/tree/src/libsystemd/sd-bus/bus-bloom.c
1749  */
1750 static void
1751 g_kdbus_setup_bloom (GKDBusWorker                     *worker,
1752                      GDBusMessage               *dbus_msg,
1753                      struct kdbus_bloom_filter  *bloom_filter)
1754 {
1755   GVariant *body;
1756
1757   const gchar *message_type;
1758   const gchar *interface;
1759   const gchar *member;
1760   const gchar *path;
1761
1762   void *bloom_data;
1763
1764   body = g_dbus_message_get_body (dbus_msg);
1765   message_type = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, g_dbus_message_get_message_type (dbus_msg));
1766   interface = g_dbus_message_get_interface (dbus_msg);
1767   member = g_dbus_message_get_member (dbus_msg);
1768   path = g_dbus_message_get_path (dbus_msg);
1769
1770   bloom_data = bloom_filter->data;
1771   memset (bloom_data, 0, worker->bloom_size);
1772   bloom_filter->generation = 0;
1773
1774   g_kdbus_bloom_add_pair(worker, bloom_data, "message-type", message_type);
1775
1776   if (interface)
1777     g_kdbus_bloom_add_pair(worker, bloom_data, "interface", interface);
1778
1779   if (member)
1780     g_kdbus_bloom_add_pair(worker, bloom_data, "member", member);
1781
1782   if (path)
1783     {
1784       g_kdbus_bloom_add_pair(worker, bloom_data, "path", path);
1785       g_kdbus_bloom_add_pair(worker, bloom_data, "path-slash-prefix", path);
1786       g_kdbus_bloom_add_prefixes(worker, bloom_data, "path-slash-prefix", path, '/');
1787     }
1788
1789   if (body != NULL)
1790     {
1791       const GVariantType *body_type;
1792       const GVariantType *arg_type;
1793       guint cnt;
1794
1795       body_type = g_variant_get_type (body);
1796
1797       for (arg_type = g_variant_type_first (body_type), cnt = 0;
1798            arg_type;
1799            arg_type = g_variant_type_next (arg_type), cnt++)
1800         {
1801           gchar type_char = g_variant_type_peek_string (arg_type)[0];
1802           gchar buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1803           const gchar *str;
1804           GVariant *child;
1805           gchar *e;
1806
1807           if (type_char != 's' && type_char != 'o')
1808             /* XXX: kdbus docs say "stop after first non-string" but I
1809              * think they're wrong (vs. dbus-1 compat)...
1810              */
1811             continue;
1812
1813           child = g_variant_get_child_value (body, cnt);
1814           str = g_variant_get_string (child, NULL);
1815
1816           e = stpcpy(buf, "arg");
1817           if (cnt < 10)
1818             *(e++) = '0' + (char) cnt;
1819           else
1820             {
1821               *(e++) = '0' + (char) (cnt / 10);
1822               *(e++) = '0' + (char) (cnt % 10);
1823             }
1824
1825           /* We add this one for both strings and object paths */
1826           strcpy(e, "-slash-prefix");
1827           g_kdbus_bloom_add_prefixes(worker, bloom_data, buf, str, '/');
1828
1829           /* But the others are only for strings */
1830           if (type_char == 's')
1831             {
1832               strcpy(e, "-dot-prefix");
1833               g_kdbus_bloom_add_prefixes(worker, bloom_data, buf, str, '.');
1834
1835               *e = 0;
1836               g_kdbus_bloom_add_pair(worker, bloom_data, buf, str);
1837             }
1838
1839           g_variant_unref (child);
1840         }
1841     }
1842 }
1843
1844
1845 /*
1846  * TODO: g_kdbus_NameOwnerChanged_generate, g_kdbus_KernelMethodError_generate
1847  */
1848
1849 /**
1850  * g_kdbus_decode_kernel_msg:
1851  *
1852  */
1853 static void
1854 g_kdbus_decode_kernel_msg (GKDBusWorker           *worker,
1855                            struct kdbus_msg *msg)
1856 {
1857   struct kdbus_item *item = NULL;
1858
1859   KDBUS_ITEM_FOREACH(item, msg, items)
1860     {
1861      switch (item->type)
1862         {
1863           case KDBUS_ITEM_ID_ADD:
1864           case KDBUS_ITEM_ID_REMOVE:
1865           case KDBUS_ITEM_NAME_ADD:
1866           case KDBUS_ITEM_NAME_REMOVE:
1867           case KDBUS_ITEM_NAME_CHANGE:
1868             //size = g_kdbus_NameOwnerChanged_generate (worker, item);
1869             g_error ("'NameOwnerChanged'");
1870             break;
1871
1872           case KDBUS_ITEM_REPLY_TIMEOUT:
1873           case KDBUS_ITEM_REPLY_DEAD:
1874             //size = g_kdbus_KernelMethodError_generate (worker, item);
1875             g_error ("'KernelMethodError'");
1876             break;
1877
1878           default:
1879             g_warning ("Unknown field in kernel message - %lld", item->type);
1880        }
1881     }
1882
1883 #if 0
1884   /* Override information from the user header with data from the kernel */
1885   g_string_printf (worker->msg_sender, "org.freedesktop.DBus");
1886
1887   /* for destination */
1888   if (worker->kmsg->dst_id == KDBUS_DST_ID_BROADCAST)
1889     /* for broadcast messages we don't have to set destination */
1890     ;
1891   else if (worker->kmsg->dst_id == KDBUS_DST_ID_NAME)
1892     g_string_printf (worker->msg_destination, ":1.%" G_GUINT64_FORMAT, (guint64) worker->unique_id);
1893   else
1894    g_string_printf (worker->msg_destination, ":1.%" G_GUINT64_FORMAT, (guint64) worker->kmsg->dst_id);
1895
1896   return size;
1897 #endif
1898 }
1899
1900
1901 /**
1902  * g_kdbus_decode_dbus_msg:
1903  *
1904  */
1905 static GDBusMessage *
1906 g_kdbus_decode_dbus_msg (GKDBusWorker           *worker,
1907                          struct kdbus_msg *msg)
1908 {
1909   GDBusMessage *message;
1910   struct kdbus_item *item;
1911   gssize data_size = 0;
1912   GArray *body_vectors;
1913   gsize body_size;
1914   GVariant *body;
1915   gchar *tmp;
1916   guint i;
1917   GVariant *parts[2];
1918   GVariantIter *fields_iter;
1919   guint8 endianness, type, flags, version;
1920   guint64 key;
1921   GVariant *value;
1922   guint64 serial;
1923
1924
1925   message = g_dbus_message_new ();
1926
1927   body_vectors = g_array_new (FALSE, FALSE, sizeof (GVariantVector));
1928
1929   tmp = g_strdup_printf (":1.%"G_GUINT64_FORMAT, (guint64) msg->src_id);
1930   g_dbus_message_set_sender (message, tmp);
1931   g_free (tmp);
1932
1933   item = msg->items;
1934   body_size = 0;
1935
1936   KDBUS_ITEM_FOREACH(item, msg, items)
1937     {
1938       if (item->size <= KDBUS_ITEM_HEADER_SIZE)
1939         g_error("[KDBUS] %llu bytes - invalid data record\n", item->size);
1940
1941       data_size = item->size - KDBUS_ITEM_HEADER_SIZE;
1942
1943       switch (item->type)
1944         {
1945          /* KDBUS_ITEM_DST_NAME */
1946          case KDBUS_ITEM_DST_NAME:
1947            /* Classic D-Bus doesn't make this known to the receiver, so
1948             * we don't do it here either (for compatibility with the
1949             * fallback case).
1950             */
1951            break;
1952
1953         /* KDBUS_ITEM_PALOAD_OFF */
1954         case KDBUS_ITEM_PAYLOAD_OFF:
1955           {
1956             GVariantVector vector;
1957             gsize flavour;
1958
1959             /* We want to make sure the bytes are aligned the same as
1960              * they would be if they appeared in a contiguously
1961              * allocated chunk of aligned memory.
1962              *
1963              * We decide what the alignment 'should' be by consulting
1964              * body_size, which has been tracking the total size of the
1965              * message up to this point.
1966              *
1967              * We then play around with the pointer by removing as many
1968              * bytes as required to get it to the proper alignment (and
1969              * copy extra bytes accordingly).  This means that we will
1970              * grab some extra data in the 'bytes', but it won't be
1971              * shared with GVariant (which means there is no chance of
1972              * it being accidentally retransmitted).
1973              *
1974              * The kernel does the same thing, so make sure we get the
1975              * expected result.  Because of the kernel doing the same,
1976              * the result is that we will always be rounding-down to a
1977              * multiple of 8 for the pointer, which means that the
1978              * pointer will always be valid, assuming the original
1979              * address was.
1980              *
1981              * We could fix this with a new GBytes constructor that took
1982              * 'flavour' as a parameter, but it's not worth it...
1983              */
1984             flavour = body_size & 7;
1985             g_assert ((item->vec.offset & 7) == flavour);
1986
1987             vector.gbytes = g_bytes_new (((guchar *) msg) + item->vec.offset - flavour, item->vec.size + flavour);
1988             vector.data.pointer = g_bytes_get_data (vector.gbytes, NULL);
1989             vector.data.pointer += flavour;
1990             vector.size = item->vec.size;
1991
1992             g_array_append_val (body_vectors, vector);
1993             body_size += vector.size;
1994           }
1995           break;
1996
1997         /* KDBUS_ITEM_PAYLOAD_MEMFD */
1998         case KDBUS_ITEM_PAYLOAD_MEMFD:
1999           {
2000             GVariantVector vector;
2001             const guchar *data;
2002             gsize size;
2003
2004             vector.gbytes = g_bytes_new_take_zero_copy_fd (item->memfd.fd);
2005             data = g_bytes_get_data (vector.gbytes, &size);
2006
2007             g_assert (item->memfd.start + item->memfd.size <= size);
2008
2009             vector.data.pointer = data + item->memfd.start;
2010             vector.size = item->memfd.size;
2011
2012             g_array_append_val (body_vectors, vector);
2013             body_size += vector.size;
2014           }
2015           break;
2016
2017         /* KDBUS_ITEM_FDS */
2018         case KDBUS_ITEM_FDS:
2019           {
2020             GUnixFDList *fd_list;
2021
2022             fd_list = g_unix_fd_list_new_from_array (item->fds, data_size / sizeof (int));
2023             g_dbus_message_set_unix_fd_list (message, fd_list);
2024             g_object_unref (fd_list);
2025           }
2026           break;
2027
2028         /* All of the following items, like CMDLINE,
2029            CGROUP, etc. need some GDBUS API extensions and
2030            should be implemented in the future */
2031         case KDBUS_ITEM_TIMESTAMP:
2032           {
2033             g_print ("time: seq %llu mon %llu real %llu\n",
2034                      item->timestamp.seqnum, item->timestamp.monotonic_ns, item->timestamp.realtime_ns);
2035             //g_dbus_message_set_timestamp (message, item->timestamp.monotonic_ns / 1000);
2036             //g_dbus_message_set_serial (message, item->timestamp.seqnum);
2037             break;
2038           }
2039
2040         case KDBUS_ITEM_CREDS:
2041           {
2042             g_print ("creds: u%u eu %u su%u fsu%u g%u eg%u sg%u fsg%u\n",
2043                      item->creds.uid, item->creds.euid, item->creds.suid, item->creds.fsuid,
2044                      item->creds.gid, item->creds.egid, item->creds.sgid, item->creds.fsgid);
2045             break;
2046           }
2047
2048         case KDBUS_ITEM_PIDS:
2049         case KDBUS_ITEM_PID_COMM:
2050         case KDBUS_ITEM_TID_COMM:
2051         case KDBUS_ITEM_EXE:
2052         case KDBUS_ITEM_CMDLINE:
2053         case KDBUS_ITEM_CGROUP:
2054         case KDBUS_ITEM_AUDIT:
2055         case KDBUS_ITEM_CAPS:
2056         case KDBUS_ITEM_SECLABEL:
2057         case KDBUS_ITEM_CONN_DESCRIPTION:
2058         case KDBUS_ITEM_AUXGROUPS:
2059         case KDBUS_ITEM_OWNED_NAME:
2060         case KDBUS_ITEM_NAME:
2061           g_print ("unhandled %04x\n", (int) item->type);
2062           break;
2063
2064         default:
2065           g_error ("[KDBUS] DBUS_PAYLOAD: Unknown filed - %lld", item->type);
2066           break;
2067         }
2068     }
2069
2070   body = GLIB_PRIVATE_CALL(g_variant_from_vectors) (G_VARIANT_TYPE ("((yyyyuta{tv})v)"),
2071                                                     (GVariantVector *) body_vectors->data,
2072                                                     body_vectors->len, body_size, FALSE);
2073   g_assert (body);
2074
2075   for (i = 0; i < body_vectors->len; i++)
2076     g_bytes_unref (g_array_index (body_vectors, GVariantVector, i).gbytes);
2077
2078   g_array_free (body_vectors, TRUE);
2079
2080   parts[0] = g_variant_get_child_value (body, 0);
2081   parts[1] = g_variant_get_child_value (body, 1);
2082   g_variant_unref (body);
2083
2084   body = g_variant_get_variant (parts[1]);
2085   g_variant_unref (parts[1]);
2086   g_dbus_message_set_body (message, body);
2087   g_variant_unref (body);
2088
2089   g_variant_get (parts[0], "(yyyyuta{tv})", &endianness, &type, &flags, &version, NULL, &serial, &fields_iter);
2090   g_variant_unref (parts[0]);
2091
2092   while (g_variant_iter_loop (fields_iter, "{tv}", &key, &value))
2093     g_dbus_message_set_header (message, key, value);
2094
2095   g_dbus_message_set_flags (message, flags);
2096   g_dbus_message_set_serial (message, serial);
2097   g_dbus_message_set_message_type (message, type);
2098
2099   g_print ("Received:\n%s\n", g_dbus_message_print (message, 2));
2100
2101   (* worker->message_received_callback) (message, worker->user_data);
2102
2103   g_object_unref (message);
2104
2105   return 0;
2106 }
2107
2108
2109 /**
2110  * _g_kdbus_receive:
2111  *
2112  */
2113 static gssize
2114 _g_kdbus_receive (GKDBusWorker        *kdbus,
2115                   GCancellable  *cancellable,
2116                   GError       **error)
2117 {
2118   struct kdbus_cmd_recv recv;
2119   struct kdbus_msg *msg;
2120
2121   memset (&recv, 0, sizeof recv);
2122   recv.size = sizeof (recv);
2123
2124   if (g_cancellable_set_error_if_cancelled (cancellable, error))
2125     return -1;
2126
2127 again:
2128     if (ioctl(kdbus->fd, KDBUS_CMD_RECV, &recv) < 0)
2129       {
2130         if (errno == EINTR)
2131           goto again;
2132
2133         if (errno == EAGAIN)
2134           return 0;
2135
2136         g_warning ("in holding pattern over %d %d\n", kdbus->fd, errno);
2137         while (1)
2138           sleep(1);
2139
2140         g_set_error (error, G_IO_ERROR,
2141                      g_io_error_from_errno (errno),
2142                      _("Error while receiving message: %s"),
2143                      g_strerror (errno));
2144         return -1;
2145       }
2146
2147     g_print ("but sometimes that's okay\n");
2148
2149    msg = (struct kdbus_msg *)((guint8 *)kdbus->kdbus_buffer + recv.msg.offset);
2150
2151    if (msg->payload_type == KDBUS_PAYLOAD_DBUS)
2152      g_kdbus_decode_dbus_msg (kdbus, msg);
2153    else if (msg->payload_type == KDBUS_PAYLOAD_KERNEL)
2154      g_kdbus_decode_kernel_msg (kdbus, msg);
2155    else
2156      {
2157        g_set_error (error,
2158                     G_DBUS_ERROR,
2159                     G_DBUS_ERROR_FAILED,
2160                     _("Received unknown payload type"));
2161        return -1;
2162      }
2163
2164   ioctl(kdbus->fd, KDBUS_CMD_FREE, &recv.msg.offset);
2165
2166    return 0;
2167 }
2168
2169 static gboolean
2170 g_kdbus_msg_append_item (struct kdbus_msg *msg,
2171                          gsize             type,
2172                          gconstpointer     data,
2173                          gsize             size)
2174 {
2175   struct kdbus_item *item;
2176   gsize item_size;
2177
2178   item_size = size + G_STRUCT_OFFSET(struct kdbus_item, data);
2179
2180   if (msg->size + item_size > KDBUS_MSG_MAX_SIZE)
2181     return FALSE;
2182
2183   /* align */
2184   msg->size += (-msg->size) & 7;
2185   item = (struct kdbus_item *) ((guchar *) msg + msg->size);
2186   item->type = type;
2187   item->size = item_size;
2188   memcpy (item->data, data, size);
2189
2190   msg->size += item_size;
2191
2192   return TRUE;
2193 }
2194
2195 static gboolean
2196 g_kdbus_msg_append_payload_vec (struct kdbus_msg *msg,
2197                                 gconstpointer     data,
2198                                 gsize             size)
2199 {
2200   struct kdbus_vec vec = {
2201     .size = size,
2202     .address = (gsize) data
2203   };
2204
2205   return g_kdbus_msg_append_item (msg, KDBUS_ITEM_PAYLOAD_VEC, &vec, sizeof vec);
2206 }
2207
2208 static gboolean
2209 g_kdbus_msg_append_payload_memfd (struct kdbus_msg *msg,
2210                                   gint              fd,
2211                                   gsize             offset,
2212                                   gsize             size)
2213 {
2214   struct kdbus_memfd mfd = {
2215    .start = offset,
2216    .size = size,
2217    .fd = fd,
2218   };
2219
2220   return g_kdbus_msg_append_item (msg, KDBUS_ITEM_PAYLOAD_MEMFD, &mfd, sizeof mfd);
2221 }
2222
2223 #if 0
2224 #include "dbusheader.h"
2225
2226 void dump_header (gconstpointer data, gsize size) ;
2227 void
2228 dump_header (gconstpointer data,
2229              gsize size)
2230 {
2231   GDBusMessageHeaderFieldsIterator iter;
2232   GDBusMessageHeader header;
2233
2234   header = g_dbus_message_header_new (data, size);
2235   g_print ("header e/%c t/%u f/x%x v/%u s/%"G_GUINT64_FORMAT"\n",
2236            g_dbus_message_header_get_endian (header),
2237            g_dbus_message_header_get_type (header),
2238            g_dbus_message_header_get_flags (header),
2239            g_dbus_message_header_get_version (header),
2240            g_dbus_message_header_get_serial (header));
2241
2242   iter = g_dbus_message_header_iterate_fields (header);
2243
2244   while (g_dbus_message_header_fields_iterator_next (&iter))
2245     {
2246       const gchar *string;
2247       guint64 reply_to;
2248       guint64 key;
2249
2250       key = g_dbus_message_header_fields_iterator_get_key (iter);
2251
2252       switch (key)
2253         {
2254           case G_DBUS_MESSAGE_HEADER_FIELD_PATH:
2255             if (g_dbus_message_header_fields_iterator_get_value_as_object_path (iter, &string))
2256               g_print ("  path: %s\n", string);
2257             else
2258               g_print ("  path: <<invalid string>>\n");
2259             break;
2260
2261           case G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE:
2262             if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2263               g_print ("  interface: %s\n", string);
2264             else
2265               g_print ("  interface: <<invalid string>>\n");
2266             break;
2267
2268           case G_DBUS_MESSAGE_HEADER_FIELD_MEMBER:
2269             if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2270               g_print ("  member: %s\n", string);
2271             else
2272               g_print ("  member: <<invalid string>>\n");
2273             break;
2274
2275           case G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME:
2276             if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2277               g_print ("  error: %s\n", string);
2278             else
2279               g_print ("  error: <<invalid string>>\n");
2280             break;
2281
2282           case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL:
2283             if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2284               g_print ("  serial: %s\n", string);
2285             else
2286               g_print ("  serial: <<invalid string>>\n");
2287             break;
2288
2289           case G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION:
2290             if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2291               g_print ("  destination: %s\n", string);
2292             else
2293               g_print ("  destination: <<invalid string>>\n");
2294             break;
2295
2296           case G_DBUS_MESSAGE_HEADER_FIELD_SENDER:
2297             if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2298               g_print ("  sender: %s\n", string);
2299             else
2300               g_print ("  sender: <<invalid string>>\n");
2301             break;
2302
2303           default:
2304             g_print ("unknown field code %"G_GUINT64_FORMAT"\n", key);
2305             g_assert_not_reached ();
2306         }
2307     }
2308
2309   g_print ("\n");
2310
2311 }
2312 #endif
2313
2314 /**
2315  * _g_kdbus_send:
2316  * Returns: size of data sent or -1 when error
2317  */
2318 static gboolean
2319 _g_kdbus_send (GKDBusWorker        *kdbus,
2320                GDBusMessage  *message,
2321                GError       **error)
2322 {
2323   struct kdbus_msg *msg = alloca (KDBUS_MSG_MAX_SIZE);
2324   GVariantVectors body_vectors;
2325   struct kdbus_cmd_send send;
2326
2327   g_return_val_if_fail (G_IS_KDBUS_WORKER (kdbus), -1);
2328
2329   /* fill in as we go... */
2330   memset (msg, 0, sizeof (struct kdbus_msg));
2331   msg->size = sizeof (struct kdbus_msg);
2332   msg->payload_type = KDBUS_PAYLOAD_DBUS;
2333   msg->src_id = kdbus->unique_id;
2334   msg->cookie = g_dbus_message_get_serial(message);
2335
2336   /* Message destination */
2337   {
2338     const gchar *dst_name;
2339
2340     dst_name = g_dbus_message_get_destination (message);
2341
2342     if (dst_name != NULL)
2343       {
2344         if (g_dbus_is_unique_name (dst_name))
2345           {
2346             if (dst_name[1] != '1' || dst_name[2] != '.')
2347               {
2348                 g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
2349                              "Invalid unique D-Bus name '%s'", dst_name);
2350                 return FALSE;
2351               }
2352
2353             /* We already know that it passes the checks for unique
2354              * names, so no need to perform error checking on strtoull.
2355              */
2356             msg->dst_id = strtoull (dst_name + 3, NULL, 10);
2357             dst_name = NULL;
2358           }
2359         else
2360           {
2361             g_kdbus_msg_append_item (msg, KDBUS_ITEM_DST_NAME, dst_name, strlen (dst_name) + 1);
2362             msg->dst_id = KDBUS_DST_ID_NAME;
2363           }
2364       }
2365     else
2366       msg->dst_id = KDBUS_DST_ID_BROADCAST;
2367   }
2368
2369   /* File descriptors */
2370   {
2371     GUnixFDList *fd_list;
2372
2373     fd_list = g_dbus_message_get_unix_fd_list (message);
2374
2375     if (fd_list != NULL)
2376       {
2377         const gint *fds;
2378         gint n_fds;
2379
2380         fds = g_unix_fd_list_peek_fds (fd_list, &n_fds);
2381
2382         if (n_fds)
2383           g_kdbus_msg_append_item (msg, KDBUS_ITEM_FDS, fds, sizeof (gint) * n_fds);
2384       }
2385   }
2386
2387   /* Message body */
2388   {
2389     struct dbus_fixed_header fh;
2390     GHashTableIter header_iter;
2391     GVariantBuilder builder;
2392     gpointer key, value;
2393     GVariant *parts[3];
2394     GVariant *body;
2395
2396     fh.endian = (G_BYTE_ORDER == G_LITTLE_ENDIAN) ? 'l': 'B';
2397     fh.type = g_dbus_message_get_message_type (message);
2398     fh.flags = g_dbus_message_get_flags (message);
2399     fh.version = 2;
2400     fh.reserved = 0;
2401     fh.serial = g_dbus_message_get_serial (message);
2402     parts[0] = g_variant_new_from_data (DBUS_FIXED_HEADER_TYPE, &fh, sizeof fh, TRUE, NULL, NULL);
2403
2404     g_dbus_message_init_header_iter (message, &header_iter);
2405     g_variant_builder_init (&builder, DBUS_EXTENDED_HEADER_TYPE);
2406
2407     /* We set the sender field to the correct value for ourselves */
2408     g_variant_builder_add (&builder, "{tv}",
2409                            (guint64) G_DBUS_MESSAGE_HEADER_FIELD_SENDER,
2410                            g_variant_new_printf (":1.%"G_GUINT64_FORMAT, kdbus->unique_id));
2411
2412     while (g_hash_table_iter_next (&header_iter, &key, &value))
2413       {
2414         guint64 key_int = (gsize) key;
2415
2416         switch (key_int)
2417           {
2418             /* These are the normal header fields that get passed
2419              * straight through.
2420              */
2421             case G_DBUS_MESSAGE_HEADER_FIELD_PATH:
2422             case G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE:
2423             case G_DBUS_MESSAGE_HEADER_FIELD_MEMBER:
2424             case G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME:
2425             case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL:
2426             case G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION:
2427               g_variant_builder_add (&builder, "{tv}", key_int, value);
2428               /* This is a little bit gross.
2429                *
2430                * We must send the header part of the message in a single
2431                * vector as per kdbus rules, but the GVariant serialiser
2432                * code will split any item >= 128 bytes into its own
2433                * vector to save the copy.
2434                *
2435                * No header field should be that big anyway... right?
2436                */
2437               g_assert_cmpint (g_variant_get_size (value), <, 128);
2438               continue;
2439
2440             /* We send this one unconditionally, but set it ourselves */
2441             case G_DBUS_MESSAGE_HEADER_FIELD_SENDER:
2442               continue;
2443
2444             /* We don't send these at all in GVariant format */
2445             case G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE:
2446             case G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS:
2447               continue;
2448
2449             default:
2450               g_assert_not_reached ();
2451           }
2452       }
2453     parts[1] = g_variant_builder_end (&builder);
2454
2455     body = g_dbus_message_get_body (message);
2456     if (!body)
2457       body = g_variant_new ("()");
2458     parts[2] = g_variant_new_variant (body);
2459
2460     body = g_variant_ref_sink (g_variant_new_tuple (parts, G_N_ELEMENTS (parts)));
2461     GLIB_PRIVATE_CALL(g_variant_to_vectors) (body, &body_vectors);
2462
2463     /* Sanity check to make sure the header is really contiguous:
2464      *
2465      *  - we must have at least one vector in the output
2466      *  - the first vector must completely contain at least the header
2467      */
2468     g_assert_cmpint (body_vectors.vectors->len, >, 0);
2469     g_assert_cmpint (g_array_index (body_vectors.vectors, GVariantVector, 0).size, >=,
2470                      g_variant_get_size (parts[0]) + g_variant_get_size (parts[1]));
2471
2472     g_variant_unref (body);
2473   }
2474
2475   {
2476     guint i;
2477
2478     for (i = 0; i < body_vectors.vectors->len; i++)
2479       {
2480         GVariantVector vector = g_array_index (body_vectors.vectors, GVariantVector, i);
2481
2482         if (vector.gbytes)
2483           {
2484             gint fd;
2485
2486             fd = g_bytes_get_zero_copy_fd (vector.gbytes);
2487
2488             if (fd >= 0)
2489               {
2490                 const guchar *bytes_data;
2491                 gsize bytes_size;
2492
2493                 bytes_data = g_bytes_get_data (vector.gbytes, &bytes_size);
2494
2495                 if (bytes_data <= vector.data.pointer && vector.data.pointer + vector.size <= bytes_data + bytes_size)
2496                   {
2497                     if (!g_kdbus_msg_append_payload_memfd (msg, fd, vector.data.pointer - bytes_data, vector.size))
2498                       goto need_compact;
2499                   }
2500                 else
2501                   {
2502                     if (!g_kdbus_msg_append_payload_vec (msg, vector.data.pointer, vector.size))
2503                       goto need_compact;
2504                   }
2505               }
2506             else
2507               {
2508                 if (!g_kdbus_msg_append_payload_vec (msg, vector.data.pointer, vector.size))
2509                   goto need_compact;
2510               }
2511           }
2512         else
2513           if (!g_kdbus_msg_append_payload_vec (msg, body_vectors.extra_bytes->data + vector.data.offset, vector.size))
2514             goto need_compact;
2515       }
2516   }
2517
2518   /*
2519    * set message flags
2520    */
2521   msg->flags = ((g_dbus_message_get_flags (message) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_EXPECT_REPLY) |
2522                 ((g_dbus_message_get_flags (message) & G_DBUS_MESSAGE_FLAGS_NO_AUTO_START) ? KDBUS_MSG_NO_AUTO_START : 0);
2523
2524   if ((msg->flags) & KDBUS_MSG_EXPECT_REPLY)
2525     msg->timeout_ns = 1000LU * g_get_monotonic_time() + KDBUS_TIMEOUT_NS;
2526   else
2527     msg->cookie_reply = g_dbus_message_get_reply_serial(message);
2528
2529
2530   /*
2531   if (dst_id == KDBUS_DST_ID_BROADCAST)
2532     {
2533       struct kdbus_bloom_filter *bloom_filter;
2534
2535       bloom_filter = g_kdbus_append_bloom (&item, kdbus->bloom_size);
2536       g_kdbus_setup_bloom (kdbus, message, bloom_filter);
2537     }
2538     */
2539
2540   send.size = sizeof (send);
2541   send.flags = 0;
2542   send.msg_address = (gsize) msg;
2543
2544   /*
2545    * send message
2546    */
2547 //again:
2548   if (ioctl(kdbus->fd, KDBUS_CMD_SEND, &send))
2549     {
2550 /*
2551       GString *error_name;
2552       error_name = g_string_new (NULL);
2553
2554       if(errno == EINTR)
2555         {
2556           g_string_free (error_name,TRUE);
2557           goto again;
2558         }
2559       else if (errno == ENXIO)
2560         {
2561           g_string_printf (error_name, "Name %s does not exist", g_dbus_message_get_destination(dbus_msg));
2562           g_kdbus_generate_local_error (worker,
2563                                         dbus_msg,
2564                                         g_variant_new ("(s)",error_name->str),
2565                                         G_DBUS_ERROR_SERVICE_UNKNOWN);
2566           g_string_free (error_name,TRUE);
2567           return 0;
2568         }
2569       else if ((errno == ESRCH) || (errno == EADDRNOTAVAIL))
2570         {
2571           if (kmsg->flags & KDBUS_MSG_FLAGS_NO_AUTO_START)
2572             {
2573               g_string_printf (error_name, "Name %s does not exist", g_dbus_message_get_destination(dbus_msg));
2574               g_kdbus_generate_local_error (worker,
2575                                             dbus_msg,
2576                                             g_variant_new ("(s)",error_name->str),
2577                                             G_DBUS_ERROR_SERVICE_UNKNOWN);
2578               g_string_free (error_name,TRUE);
2579               return 0;
2580             }
2581           else
2582             {
2583               g_string_printf (error_name, "The name %s was not provided by any .service files", g_dbus_message_get_destination(dbus_msg));
2584               g_kdbus_generate_local_error (worker,
2585                                             dbus_msg,
2586                                             g_variant_new ("(s)",error_name->str),
2587                                             G_DBUS_ERROR_SERVICE_UNKNOWN);
2588               g_string_free (error_name,TRUE);
2589               return 0;
2590             }
2591         }
2592
2593       g_print ("[KDBUS] ioctl error sending kdbus message:%d (%m)\n",errno);
2594       g_set_error (error, G_IO_ERROR, g_io_error_from_errno(errno), _("Error sending message - KDBUS_CMD_MSG_SEND error"));
2595 */
2596       perror("ioctl send");
2597       g_error ("IOCTL SEND: %d\n",errno);
2598       return FALSE;
2599     }
2600
2601   return TRUE;
2602
2603 need_compact:
2604   /* We end up here if:
2605    *  - too many kdbus_items
2606    *  - too large kdbus_msg size
2607    *  - too much vector data
2608    *
2609    * We need to compact the message before sending it.
2610    */
2611   g_assert_not_reached ();
2612 }
2613
2614 GKDBusWorker *
2615 g_kdbus_worker_new (const gchar  *address,
2616                     GError      **error)
2617 {
2618   GKDBusWorker *worker;
2619
2620   worker = g_object_new (G_TYPE_KDBUS_WORKER, NULL);
2621   if (!_g_kdbus_open (worker, address, error))
2622     {
2623       g_object_unref (worker);
2624       return NULL;
2625     }
2626
2627   return worker;
2628 }
2629
2630 void
2631 g_kdbus_worker_associate (GKDBusWorker                            *worker,
2632                           GDBusCapabilityFlags                     capabilities,
2633                           GDBusWorkerMessageReceivedCallback       message_received_callback,
2634                           GDBusWorkerMessageAboutToBeSentCallback  message_about_to_be_sent_callback,
2635                           GDBusWorkerDisconnectedCallback          disconnected_callback,
2636                           gpointer                                 user_data)
2637 {
2638   worker->capabilities = capabilities;
2639   worker->message_received_callback = message_received_callback;
2640   worker->message_about_to_be_sent_callback = message_about_to_be_sent_callback;
2641   worker->disconnected_callback = disconnected_callback;
2642   worker->user_data = user_data;
2643 }
2644
2645 void
2646 g_kdbus_worker_unfreeze (GKDBusWorker *worker)
2647 {
2648   gchar *name;
2649
2650   if (worker->source != NULL)
2651     return;
2652
2653   worker->context = g_main_context_ref_thread_default ();
2654   worker->source = g_unix_fd_source_new (worker->fd, G_IO_IN);
2655
2656   g_source_set_callback (worker->source, (GSourceFunc) kdbus_ready, worker, NULL);
2657   name = g_strdup_printf ("kdbus worker");
2658   g_source_set_name (worker->source, name);
2659   g_free (name);
2660
2661   g_source_attach (worker->source, worker->context);
2662 }
2663
2664 gboolean
2665 g_kdbus_worker_send_message (GKDBusWorker  *worker,
2666                              GDBusMessage  *message,
2667                              GError       **error)
2668 {
2669   return _g_kdbus_send (worker, message, error);
2670 }
2671
2672 void
2673 g_kdbus_worker_stop (GKDBusWorker *worker)
2674 {
2675 }
2676
2677 void
2678 g_kdbus_worker_flush_sync (GKDBusWorker *worker)
2679 {
2680 }
2681
2682 void
2683 g_kdbus_worker_close (GKDBusWorker       *worker,
2684                       GCancellable       *cancellable,
2685                       GSimpleAsyncResult *result)
2686 {
2687 }