1
/*
2
 * AT-SPI - Assistive Technology Service Provider Interface
3
 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4
 *
5
 * Copyright 2008 Novell, Inc.
6
 * Copyright 2008 Codethink Ltd.
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, write to the
20
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21
 * Boston, MA 02110-1301, USA.
22
 */
23

            
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <string.h>
27

            
28
#include "droute-pairhash.h"
29
#include "droute.h"
30

            
31
#define CHUNKS_DEFAULT (512)
32

            
33
#define oom() g_error ("D-Bus out of memory, this message will fail anyway")
34

            
35
#if defined DROUTE_DEBUG
36
#define _DROUTE_DEBUG(format, args...) g_print (format, ##args)
37
#else
38
#define _DROUTE_DEBUG(format, args...)
39
#endif
40

            
41
struct _DRouteContext
42
{
43
  GPtrArray *registered_paths;
44

            
45
  gchar *introspect_string;
46
};
47

            
48
struct _DRoutePath
49
{
50
  DRouteContext *cnx;
51
  gchar *path;
52
  gboolean prefix;
53
  GStringChunk *chunks;
54
  GPtrArray *interfaces;
55
  GPtrArray *introspection;
56
  GHashTable *methods;
57
  GHashTable *properties;
58

            
59
  DRouteIntrospectChildrenFunction introspect_children_cb;
60
  void *introspect_children_data;
61
  void *user_data;
62
  DRouteGetDatumFunction get_datum;
63
  DRouteQueryInterfaceFunction query_interface_cb;
64
};
65

            
66
/*---------------------------------------------------------------------------*/
67

            
68
typedef struct PropertyPair
69
{
70
  DRoutePropertyFunction get;
71
  DRoutePropertyFunction set;
72
} PropertyPair;
73

            
74
/*---------------------------------------------------------------------------*/
75

            
76
static DBusHandlerResult
77
handle_message (DBusConnection *bus, DBusMessage *message, void *user_data);
78

            
79
static DBusMessage *
80
droute_object_does_not_exist_error (DBusMessage *message);
81

            
82
/*---------------------------------------------------------------------------*/
83

            
84
static DRoutePath *
85
323
path_new (DRouteContext *cnx,
86
          const char *path,
87
          gboolean prefix,
88
          void *user_data,
89
          DRouteIntrospectChildrenFunction introspect_children_cb,
90
          void *introspect_children_data,
91
          DRouteGetDatumFunction get_datum,
92
          DRouteQueryInterfaceFunction query_interface_cb)
93
{
94
  DRoutePath *new_path;
95

            
96
323
  new_path = g_new0 (DRoutePath, 1);
97
323
  new_path->cnx = cnx;
98
323
  new_path->path = g_strdup (path);
99
323
  new_path->prefix = prefix;
100
323
  new_path->chunks = g_string_chunk_new (CHUNKS_DEFAULT);
101
323
  new_path->interfaces = g_ptr_array_new ();
102
323
  new_path->introspection = g_ptr_array_new ();
103

            
104
323
  new_path->methods = g_hash_table_new_full ((GHashFunc) str_pair_hash,
105
                                             str_pair_equal,
106
                                             g_free,
107
                                             NULL);
108

            
109
323
  new_path->properties = g_hash_table_new_full ((GHashFunc) str_pair_hash,
110
                                                str_pair_equal,
111
                                                g_free,
112
                                                g_free);
113

            
114
323
  new_path->introspect_children_cb = introspect_children_cb;
115
323
  new_path->introspect_children_data = introspect_children_data;
116
323
  new_path->user_data = user_data;
117
323
  new_path->get_datum = get_datum;
118
323
  new_path->query_interface_cb = query_interface_cb;
119

            
120
323
  return new_path;
121
}
122

            
123
static void
124
323
path_free (DRoutePath *path, gpointer user_data)
125
{
126
323
  g_free (path->path);
127
323
  g_string_chunk_free (path->chunks);
128
323
  g_ptr_array_free (path->interfaces, TRUE);
129
323
  g_free (g_ptr_array_free (path->introspection, FALSE));
130
323
  g_hash_table_destroy (path->methods);
131
323
  g_hash_table_destroy (path->properties);
132
323
  g_free (path);
133
323
}
134

            
135
static void *
136
1117
path_get_datum (DRoutePath *path, const gchar *pathstr)
137
{
138
1117
  if (path->get_datum != NULL)
139
979
    return (path->get_datum) (pathstr, path->user_data);
140
  else
141
138
    return path->user_data;
142
}
143

            
144
/*---------------------------------------------------------------------------*/
145

            
146
DRouteContext *
147
162
droute_new ()
148
{
149
  DRouteContext *cnx;
150

            
151
162
  cnx = g_new0 (DRouteContext, 1);
152
162
  cnx->registered_paths = g_ptr_array_new ();
153

            
154
162
  return cnx;
155
}
156

            
157
void
158
162
droute_free (DRouteContext *cnx)
159
{
160
162
  g_ptr_array_foreach (cnx->registered_paths, (GFunc) path_free, NULL);
161
162
  g_ptr_array_free (cnx->registered_paths, TRUE);
162
162
  g_free (cnx);
163
162
}
164

            
165
/*---------------------------------------------------------------------------*/
166

            
167
/*---------------------------------------------------------------------------*/
168

            
169
static DBusObjectPathVTable droute_vtable = {
170
  NULL,
171
  &handle_message,
172
  NULL, NULL, NULL, NULL
173
};
174

            
175
DRoutePath *
176
162
droute_add_one (DRouteContext *cnx,
177
                const char *path,
178
                const void *data)
179
{
180
  DRoutePath *new_path;
181

            
182
162
  new_path = path_new (cnx, path, FALSE, (void *) data, NULL, NULL, NULL,
183
                       NULL);
184

            
185
162
  g_ptr_array_add (cnx->registered_paths, new_path);
186
162
  return new_path;
187
}
188

            
189
DRoutePath *
190
161
droute_add_many (DRouteContext *cnx,
191
                 const char *path,
192
                 const void *data,
193
                 DRouteIntrospectChildrenFunction introspect_children_cb,
194
                 void *introspect_children_data,
195
                 const DRouteGetDatumFunction get_datum,
196
                 const DRouteQueryInterfaceFunction query_interface_cb)
197
{
198
  DRoutePath *new_path;
199

            
200
161
  new_path = path_new (cnx, path, TRUE, (void *) data,
201
                       introspect_children_cb, introspect_children_data,
202
                       get_datum, query_interface_cb);
203

            
204
161
  g_ptr_array_add (cnx->registered_paths, new_path);
205
161
  return new_path;
206
}
207

            
208
/*---------------------------------------------------------------------------*/
209

            
210
void
211
2739
droute_path_add_interface (DRoutePath *path,
212
                           const char *name,
213
                           const char *introspect,
214
                           const DRouteMethod *methods,
215
                           const DRouteProperty *properties)
216
{
217
  gchar *itf;
218

            
219
2739
  g_return_if_fail (name != NULL);
220

            
221
2739
  itf = g_string_chunk_insert (path->chunks, name);
222
2739
  g_ptr_array_add (path->interfaces, itf);
223
2739
  g_ptr_array_add (path->introspection, (gpointer) introspect);
224

            
225
21427
  for (; methods != NULL && methods->name != NULL; methods++)
226
    {
227
      gchar *meth;
228

            
229
18688
      meth = g_string_chunk_insert (path->chunks, methods->name);
230
18688
      g_hash_table_insert (path->methods, str_pair_new (itf, meth), methods->func);
231
    }
232

            
233
9018
  for (; properties != NULL && properties->name != NULL; properties++)
234
    {
235
      gchar *prop;
236
      PropertyPair *pair;
237

            
238
6279
      prop = g_string_chunk_insert (path->chunks, properties->name);
239
6279
      pair = g_new (PropertyPair, 1);
240
6279
      pair->get = properties->get;
241
6279
      pair->set = properties->set;
242
6279
      g_hash_table_insert (path->properties, str_pair_new (itf, prop), pair);
243
    }
244
}
245

            
246
/*---------------------------------------------------------------------------*/
247

            
248
/* The data structures don't support an efficient implementation of GetAll
249
 * and I don't really care.
250
 */
251
static DBusMessage *
252
impl_prop_GetAll (DBusMessage *message,
253
                  DRoutePath *path,
254
                  const char *pathstr)
255
{
256
  DBusMessageIter iter, iter_dict, iter_dict_entry;
257
  DBusMessage *reply;
258
  DBusError error;
259
  GHashTableIter prop_iter;
260

            
261
  StrPair *key;
262
  PropertyPair *value;
263
  gchar *iface;
264

            
265
  void *datum = path_get_datum (path, pathstr);
266
  if (!datum)
267
    return droute_object_does_not_exist_error (message);
268

            
269
  dbus_error_init (&error);
270
  if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &iface, DBUS_TYPE_INVALID))
271
    {
272
      DBusMessage *ret;
273
      ret = dbus_message_new_error (message, DBUS_ERROR_FAILED, error.message);
274
      dbus_error_free (&error);
275
      return ret;
276
    }
277

            
278
  if (path->query_interface_cb &&
279
      !path->query_interface_cb (datum, iface))
280
    return dbus_message_new_error (message, DBUS_ERROR_UNKNOWN_PROPERTY, "Property unavailable");
281

            
282
  reply = dbus_message_new_method_return (message);
283
  if (!reply)
284
    oom ();
285

            
286
  dbus_message_iter_init_append (reply, &iter);
287
  if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{sv}", &iter_dict))
288
    oom ();
289

            
290
  g_hash_table_iter_init (&prop_iter, path->properties);
291
  while (g_hash_table_iter_next (&prop_iter, (gpointer *) &key, (gpointer *) &value))
292
    {
293
      if (!g_strcmp0 (key->one, iface))
294
        {
295
          if (!value->get)
296
            continue;
297
          if (!dbus_message_iter_open_container (&iter_dict, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict_entry))
298
            oom ();
299
          dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING,
300
                                          &key->two);
301
          (value->get) (&iter_dict_entry, datum);
302
          if (!dbus_message_iter_close_container (&iter_dict, &iter_dict_entry))
303
            oom ();
304
        }
305
    }
306

            
307
  if (!dbus_message_iter_close_container (&iter, &iter_dict))
308
    oom ();
309
  return reply;
310
}
311

            
312
static DBusMessage *
313
377
impl_prop_GetSet (DBusMessage *message,
314
                  DRoutePath *path,
315
                  const char *pathstr,
316
                  gboolean get)
317
{
318
377
  DBusMessage *reply = NULL;
319
  DBusError error;
320

            
321
  StrPair pair;
322
377
  PropertyPair *prop_funcs = NULL;
323

            
324
  void *datum;
325

            
326
377
  dbus_error_init (&error);
327
377
  if (!dbus_message_get_args (message,
328
                              &error,
329
                              DBUS_TYPE_STRING,
330
                              &(pair.one),
331
                              DBUS_TYPE_STRING,
332
                              &(pair.two),
333
                              DBUS_TYPE_INVALID))
334
    {
335
      DBusMessage *ret;
336
      ret = dbus_message_new_error (message, DBUS_ERROR_FAILED, error.message);
337
      dbus_error_free (&error);
338
      return ret;
339
    }
340

            
341
  _DROUTE_DEBUG ("DRoute (handle prop): %s|%s on %s\n", pair.one, pair.two, pathstr);
342

            
343
377
  prop_funcs = (PropertyPair *) g_hash_table_lookup (path->properties, &pair);
344
377
  if (!prop_funcs)
345
    {
346
      DBusMessage *ret;
347
      ret = dbus_message_new_error (message, DBUS_ERROR_UNKNOWN_PROPERTY, "Property unavailable");
348
      dbus_error_free (&error);
349
      return ret;
350
    }
351

            
352
377
  datum = path_get_datum (path, pathstr);
353
377
  if (!datum)
354
    return droute_object_does_not_exist_error (message);
355

            
356
377
  if (get && prop_funcs->get)
357
215
    {
358

            
359
      DBusMessageIter iter;
360

            
361
      _DROUTE_DEBUG ("DRoute (handle prop Get): %s|%s on %s\n", pair.one, pair.two, pathstr);
362

            
363
215
      reply = dbus_message_new_method_return (message);
364
215
      dbus_message_iter_init_append (reply, &iter);
365
215
      if (!(prop_funcs->get) (&iter, datum))
366
        {
367
          dbus_message_unref (reply);
368
          reply = dbus_message_new_error (message, DBUS_ERROR_FAILED, "Get failed");
369
        }
370
    }
371
162
  else if (!get && prop_funcs->set)
372
162
    {
373
      DBusMessageIter iter;
374

            
375
      _DROUTE_DEBUG ("DRoute (handle prop Get): %s|%s on %s\n", pair.one, pair.two, pathstr);
376

            
377
162
      dbus_message_iter_init (message, &iter);
378
      /* Skip the interface and property name */
379
162
      dbus_message_iter_next (&iter);
380
162
      dbus_message_iter_next (&iter);
381
162
      (prop_funcs->set) (&iter, datum);
382

            
383
162
      reply = dbus_message_new_method_return (message);
384
    }
385
  else if (!get)
386
    {
387
      reply = dbus_message_new_error (message, DBUS_ERROR_PROPERTY_READ_ONLY, "Property is read-only");
388
    }
389
  else
390
    {
391
      reply = dbus_message_new_error (message, DBUS_ERROR_FAILED, "Getter or setter unavailable");
392
    }
393

            
394
377
  return reply;
395
}
396

            
397
static DBusHandlerResult
398
handle_dbus (DBusConnection *bus,
399
             DBusMessage *message,
400
             const gchar *iface,
401
             const gchar *member,
402
             const gchar *pathstr)
403
{
404
  static int id = 1;
405
  char *id_str = (char *) g_malloc (40);
406
  DBusMessage *reply;
407

            
408
  if (strcmp (iface, DBUS_INTERFACE_DBUS) != 0 ||
409
      strcmp (member, "Hello") != 0)
410
    {
411
      g_free (id_str);
412
      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
413
    }
414

            
415
  /* TODO: Fix this hack (we don't handle wrap-around, for instance) */
416
  sprintf (id_str, ":1.%d", id++);
417
  reply = dbus_message_new_method_return (message);
418
  dbus_message_append_args (reply, DBUS_TYPE_STRING, &id_str, DBUS_TYPE_INVALID);
419
  dbus_connection_send (bus, reply, NULL);
420
  dbus_connection_flush (bus);
421
  dbus_message_unref (reply);
422
  g_free (id_str);
423
  return DBUS_HANDLER_RESULT_HANDLED;
424
}
425

            
426
static DBusHandlerResult
427
377
handle_properties (DBusConnection *bus,
428
                   DBusMessage *message,
429
                   DRoutePath *path,
430
                   const gchar *iface,
431
                   const gchar *member,
432
                   const gchar *pathstr)
433
{
434
377
  DBusMessage *reply = NULL;
435
377
  DBusHandlerResult result = DBUS_HANDLER_RESULT_HANDLED;
436

            
437
377
  if (!g_strcmp0 (member, "GetAll"))
438
    reply = impl_prop_GetAll (message, path, pathstr);
439
377
  else if (!g_strcmp0 (member, "Get"))
440
215
    reply = impl_prop_GetSet (message, path, pathstr, TRUE);
441
162
  else if (!g_strcmp0 (member, "Set"))
442
162
    reply = impl_prop_GetSet (message, path, pathstr, FALSE);
443
  else
444
    result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
445

            
446
377
  if (reply)
447
    {
448
377
      dbus_connection_send (bus, reply, NULL);
449
377
      dbus_message_unref (reply);
450
    }
451

            
452
377
  return result;
453
}
454

            
455
/*---------------------------------------------------------------------------*/
456

            
457
static const char *introspection_header =
458
    "<?xml version=\"1.0\"?>\n";
459

            
460
static const char *introspection_node_element =
461
    "<node name=\"%s\">\n";
462

            
463
static const char *introspection_footer =
464
    "</node>";
465

            
466
static DBusHandlerResult
467
handle_introspection (DBusConnection *bus,
468
                      DBusMessage *message,
469
                      DRoutePath *path,
470
                      const gchar *iface,
471
                      const gchar *member,
472
                      const gchar *pathstr)
473
{
474
  GString *output;
475
  gchar *final;
476
  gint i;
477
  void *datum = NULL;
478

            
479
  DBusMessage *reply;
480

            
481
  _DROUTE_DEBUG ("DRoute (handle introspection): %s\n", pathstr);
482

            
483
  if (g_strcmp0 (member, "Introspect"))
484
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
485

            
486
  output = g_string_new (introspection_header);
487

            
488
  g_string_append_printf (output, introspection_node_element, pathstr);
489

            
490
  if (!path->get_datum || (datum = path_get_datum (path, pathstr)) != NULL)
491
    {
492
      for (i = 0; i < path->introspection->len; i++)
493
        {
494
          gchar *interface = (gchar *) g_ptr_array_index (path->interfaces, i);
495
          gchar *introspect = (gchar *) g_ptr_array_index (path->introspection, i);
496
          if (path->query_interface_cb &&
497
              !path->query_interface_cb (datum, interface))
498
            continue;
499
          g_string_append (output, introspect);
500
        }
501
    }
502

            
503
  if (path->introspect_children_cb)
504
    {
505
      gchar *children = (*path->introspect_children_cb) (pathstr, path->introspect_children_data);
506
      if (children)
507
        {
508
          g_string_append (output, children);
509
          g_free (children);
510
        }
511
    }
512

            
513
  g_string_append (output, introspection_footer);
514
  final = g_string_free (output, FALSE);
515

            
516
  reply = dbus_message_new_method_return (message);
517
  if (!reply)
518
    oom ();
519
  dbus_message_append_args (reply, DBUS_TYPE_STRING, &final,
520
                            DBUS_TYPE_INVALID);
521
  dbus_connection_send (bus, reply, NULL);
522

            
523
  dbus_message_unref (reply);
524
  g_free (final);
525
  return DBUS_HANDLER_RESULT_HANDLED;
526
}
527

            
528
/*---------------------------------------------------------------------------*/
529

            
530
static DBusHandlerResult
531
741
handle_other (DBusConnection *bus,
532
              DBusMessage *message,
533
              DRoutePath *path,
534
              const gchar *iface,
535
              const gchar *member,
536
              const gchar *pathstr)
537
{
538
741
  gint result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
539

            
540
  StrPair pair;
541
  DRouteFunction func;
542
741
  DBusMessage *reply = NULL;
543

            
544
  void *datum;
545

            
546
741
  pair.one = iface;
547
741
  pair.two = member;
548

            
549
  _DROUTE_DEBUG ("DRoute (handle other): %s|%s on %s\n", member, iface, pathstr);
550

            
551
741
  func = (DRouteFunction) g_hash_table_lookup (path->methods, &pair);
552
741
  if (func != NULL)
553
    {
554
740
      datum = path_get_datum (path, pathstr);
555
740
      if (!datum)
556
        reply = droute_object_does_not_exist_error (message);
557
      else
558
740
        reply = (func) (bus, message, datum);
559

            
560
      /* All D-Bus method calls must have a reply.
561
       * If one is not provided presume that the caller has already
562
       * sent one.
563
       */
564
740
      if (reply)
565
        {
566
739
          dbus_connection_send (bus, reply, NULL);
567
739
          dbus_message_unref (reply);
568
        }
569
740
      result = DBUS_HANDLER_RESULT_HANDLED;
570
    }
571

            
572
  _DROUTE_DEBUG ("DRoute (handle other) (reply): type %d\n",
573
                 dbus_message_get_type (reply));
574
741
  return result;
575
}
576

            
577
/*---------------------------------------------------------------------------*/
578

            
579
static DBusHandlerResult
580
1118
handle_message (DBusConnection *bus, DBusMessage *message, void *user_data)
581
{
582
1118
  DRoutePath *path = (DRoutePath *) user_data;
583
1118
  const gchar *iface = dbus_message_get_interface (message);
584
1118
  const gchar *member = dbus_message_get_member (message);
585
1118
  const gint type = dbus_message_get_type (message);
586
1118
  const gchar *pathstr = dbus_message_get_path (message);
587

            
588
1118
  DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
589

            
590
  _DROUTE_DEBUG ("DRoute (handle message): %s|%s of type %d on %s\n", member, iface, type, pathstr);
591

            
592
  /* Check for basic reasons not to handle */
593
1118
  if (type != DBUS_MESSAGE_TYPE_METHOD_CALL ||
594
1118
      member == NULL ||
595
      iface == NULL)
596
    return result;
597

            
598
1118
  if (!strcmp (pathstr, DBUS_PATH_DBUS))
599
    result = handle_dbus (bus, message, iface, member, pathstr);
600
1118
  else if (!strcmp (iface, "org.freedesktop.DBus.Properties"))
601
377
    result = handle_properties (bus, message, path, iface, member, pathstr);
602
741
  else if (!strcmp (iface, "org.freedesktop.DBus.Introspectable"))
603
    result = handle_introspection (bus, message, path, iface, member, pathstr);
604
  else
605
741
    result = handle_other (bus, message, path, iface, member, pathstr);
606
#if 0
607
    if (result == DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
608
        g_print ("DRoute | Unhandled message: %s|%s of type %d on %s\n", member, iface, type, pathstr);
609
#endif
610

            
611
1118
  return result;
612
}
613

            
614
/*---------------------------------------------------------------------------*/
615

            
616
static DBusMessage *
617
droute_object_does_not_exist_error (DBusMessage *message)
618
{
619
  DBusMessage *reply;
620
  gchar *errmsg;
621

            
622
  errmsg = g_strdup_printf (
623
      "Method \"%s\" with signature \"%s\" on interface \"%s\" could not be processed as object %s does not exist\n",
624
      dbus_message_get_member (message),
625
      dbus_message_get_signature (message),
626
      dbus_message_get_interface (message),
627
      dbus_message_get_path (message));
628
  reply = dbus_message_new_error (message,
629
                                  DBUS_ERROR_UNKNOWN_OBJECT,
630
                                  errmsg);
631
  g_free (errmsg);
632
  return reply;
633
}
634

            
635
/*---------------------------------------------------------------------------*/
636

            
637
DBusMessage *
638
droute_not_yet_handled_error (DBusMessage *message)
639
{
640
  DBusMessage *reply;
641
  gchar *errmsg;
642

            
643
  errmsg = g_strdup_printf (
644
      "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
645
      dbus_message_get_member (message),
646
      dbus_message_get_signature (message),
647
      dbus_message_get_interface (message));
648
  reply = dbus_message_new_error (message,
649
                                  DBUS_ERROR_UNKNOWN_METHOD,
650
                                  errmsg);
651
  g_free (errmsg);
652
  return reply;
653
}
654

            
655
DBusMessage *
656
droute_out_of_memory_error (DBusMessage *message)
657
{
658
  DBusMessage *reply;
659
  gchar *errmsg;
660

            
661
  errmsg = g_strdup_printf (
662
      "Method \"%s\" with signature \"%s\" on interface \"%s\" could not be processed due to lack of memory\n",
663
      dbus_message_get_member (message),
664
      dbus_message_get_signature (message),
665
      dbus_message_get_interface (message));
666
  reply = dbus_message_new_error (message,
667
                                  DBUS_ERROR_NO_MEMORY,
668
                                  errmsg);
669
  g_free (errmsg);
670
  return reply;
671
}
672

            
673
DBusMessage *
674
droute_invalid_arguments_error (DBusMessage *message)
675
{
676
  DBusMessage *reply;
677
  gchar *errmsg;
678

            
679
  errmsg = g_strdup_printf (
680
      "Method \"%s\" with signature \"%s\" on interface \"%s\" was supplied with invalid arguments\n",
681
      dbus_message_get_member (message),
682
      dbus_message_get_signature (message),
683
      dbus_message_get_interface (message));
684
  reply = dbus_message_new_error (message,
685
                                  DBUS_ERROR_INVALID_ARGS,
686
                                  errmsg);
687
  g_free (errmsg);
688
  return reply;
689
}
690

            
691
void
692
641
droute_path_register (DRoutePath *path, DBusConnection *bus)
693
{
694
641
  if (path->prefix)
695
320
    dbus_connection_register_fallback (bus, path->path, &droute_vtable, path);
696
  else
697
321
    dbus_connection_register_object_path (bus, path->path,
698
                                          &droute_vtable, path);
699
641
}
700

            
701
void
702
640
droute_path_unregister (DRoutePath *path, DBusConnection *bus)
703
{
704
640
  dbus_connection_unregister_object_path (bus, path->path);
705
640
}
706

            
707
void
708
320
droute_context_register (DRouteContext *cnx, DBusConnection *bus)
709
{
710
320
  g_ptr_array_foreach (cnx->registered_paths, (GFunc) droute_path_register,
711
                       bus);
712
320
}
713

            
714
void
715
320
droute_context_unregister (DRouteContext *cnx, DBusConnection *bus)
716
{
717
320
  g_ptr_array_foreach (cnx->registered_paths, (GFunc) droute_path_unregister,
718
                       bus);
719
320
}
720

            
721
void
722
droute_context_deregister (DRouteContext *cnx, DBusConnection *bus)
723
{
724
  g_ptr_array_foreach (cnx->registered_paths, (GFunc) droute_path_unregister,
725
                       bus);
726
}
727

            
728
void
729
159
droute_intercept_dbus (DBusConnection *bus)
730
{
731
159
  dbus_connection_register_object_path (bus, DBUS_PATH_DBUS,
732
                                        &droute_vtable, NULL);
733
159
}
734

            
735
void
736
159
droute_unintercept_dbus (DBusConnection *bus)
737
{
738
159
  dbus_connection_unregister_object_path (bus, DBUS_PATH_DBUS);
739
159
}
740

            
741
/*END------------------------------------------------------------------------*/