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