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