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