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