~ubuntu-branches/debian/sid/upstart/sid

« back to all changes in this revision

Viewing changes to nih-dbus/dbus_proxy.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Biebl
  • Date: 2009-07-23 00:24:02 UTC
  • mfrom: (1.2.2 upstream)
  • mto: This revision was merged to the branch mainline in revision 19.
  • Revision ID: james.westby@ubuntu.com-20090723002402-pm5tq3kkipr18q00
Tags: 0.6.2-1
* New major upstream release. Closes: #530348
* Remove patches that have been merged upstream or are obsolete
  - debian/patches/01-limits.patch
  - debian/patches/02-telinit-u.patch
  - debian/patches/03-static-convenience-libs.patch
* Add Build-Depends on pkg-config (>= 0.22), libdbus-1-dev (>= 1.2.16) and
  libexpat1-dev (>= 2.0.0). D-Bus has replaced the home-grown IPC.
* Bump Standards-Version to 3.8.2. No further changes.
* debian/copyright
  - Update copyright years.
  - Clarify license text, Upstart is GPL-2 only.
  - Refer to the versioned GPL-2 document.
* Drop upstart-logd package. The logd daemon has been buggy for quite a
  while and thus removed completely upstream.
* debian/upstart.postinst
  - Use "telinit u" to tell init to re-exec itself.
* debian/rules
  - Remove obsolete configure flag.
  - Use dh_install instead of copying the job files around manually.
* Merge the upstart-compat-sysv, startup-tasks and system-services package
  into a single upstart package to avoid any unnecessary diversion between
  the Debian and Ubuntu packaging.
* The location of the job files has changed from /etc/event.d to /etc/init,
  in addition a *.conf suffix is now mandatory.
* Install rc.conf, rc-sysinit.conf, rcS.conf and control-alt-delete.conf as
  provided by upstream.
* debian/conf/*.conf
  - Update tty job files for the new job syntax. Add a description and
    author field.
  - Add dbus-reconnect.conf which tells Upstart to reconnect to the D-Bus
    system bus when runlevel 2345 has been reached.
* Update debian/upstart.install to reflect the changes above.
* Drop debian/upstart.dirs, obsolete.
* debian/README.Debian
  - Sync relevant changes from the latest Ubuntu package.
  - Remove outdated information.
* Add initial support for upstart-job.
  upstart-job is both a virtual package and also small helper utility which
  allows to execute native upstart jobs while preserving the legacy sysv
  "/etc/init.d/<service> <action>" interface.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* libnih
 
2
 *
 
3
 * dbus_proxy.c - D-Bus remote object proxy implementation
 
4
 *
 
5
 * Copyright © 2009 Scott James Remnant <scott@netsplit.com>.
 
6
 * Copyright © 2009 Canonical Ltd.
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or modify
 
9
 * it under the terms of the GNU General Public License version 2, as
 
10
 * published by the Free Software Foundation.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License along
 
18
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
19
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
20
 */
 
21
 
 
22
#ifdef HAVE_CONFIG_H
 
23
# include <config.h>
 
24
#endif /* HAVE_CONFIG_H */
 
25
 
 
26
 
 
27
#include <dbus/dbus.h>
 
28
 
 
29
#include <string.h>
 
30
 
 
31
#include <nih/macros.h>
 
32
#include <nih/alloc.h>
 
33
#include <nih/string.h>
 
34
#include <nih/logging.h>
 
35
#include <nih/error.h>
 
36
 
 
37
#include <nih-dbus/dbus_error.h>
 
38
#include <nih-dbus/dbus_object.h>
 
39
 
 
40
#include "dbus_proxy.h"
 
41
 
 
42
 
 
43
/* Prototypes for static functions */
 
44
static int   nih_dbus_proxy_destroy           (NihDBusProxy *proxy);
 
45
static int   nih_dbus_proxy_name_track        (NihDBusProxy *proxy)
 
46
        __attribute__ ((warn_unused_result));
 
47
static char *nih_dbus_proxy_name_rule         (const void *parent,
 
48
                                               NihDBusProxy *proxy)
 
49
        __attribute__ ((warn_unused_result, malloc));
 
50
static int   nih_dbus_proxy_signal_destroy    (NihDBusProxySignal *proxied);
 
51
static char *nih_dbus_proxy_signal_rule       (const void *parent,
 
52
                                               NihDBusProxySignal *proxied)
 
53
        __attribute__ ((warn_unused_result, malloc));
 
54
 
 
55
/* Prototypes for handler functions */
 
56
static DBusHandlerResult nih_dbus_proxy_name_owner_changed (DBusConnection *connection,
 
57
                                                            DBusMessage *message,
 
58
                                                            NihDBusProxy *proxy);
 
59
 
 
60
 
 
61
/**
 
62
 * nih_dbus_proxy_new:
 
63
 * @parent: parent object for new proxy,
 
64
 * @connection: D-Bus connection to associate with,
 
65
 * @name: well-known name of object owner,
 
66
 * @path: path of object,
 
67
 * @lost_handler: optional handler for remote object loss.
 
68
 * @data: data pointer for handlers.
 
69
 *
 
70
 * Creates a new D-Bus proxy for a remote object on @connection with the
 
71
 * well-known or unique bus name @name at @path.  The returned structure
 
72
 * is allocated with nih_alloc() and holds a reference to @connection.
 
73
 *
 
74
 * @name may be NULL for peer-to-peer D-Bus connections.
 
75
 *
 
76
 * Proxies are not generally bound to the life-time of the connection or
 
77
 * the remote object, thus there may be periods when functions will fail
 
78
 * or signal filter functions left dormant due to unavailability of the
 
79
 * remote object or even cease permanently when the bus connection is
 
80
 * disconnected.
 
81
 *
 
82
 * @name will be tracked on the bus, with the current owner's unique name
 
83
 * being available in the returned structure's owner member.  Should the
 
84
 * name be lost from the bus, the optional @lost_handler function will be
 
85
 * called to allow clean-up of the proxy.
 
86
 
 
87
 * If @parent is not NULL, it should be a pointer to another object which
 
88
 * will be used as a parent for the returned proxy.  When all parents
 
89
 * of the returned proxy are freed, the returned proxy will also be
 
90
 * freed.
 
91
 *
 
92
 * Returns: new NihDBusProxy structure on success, or NULL on raised
 
93
 * error.
 
94
 **/
 
95
NihDBusProxy *
 
96
nih_dbus_proxy_new (const void *       parent,
 
97
                    DBusConnection *   connection,
 
98
                    const char *       name,
 
99
                    const char *       path,
 
100
                    NihDBusLostHandler lost_handler,
 
101
                    void *             data)
 
102
{
 
103
        NihDBusProxy *proxy;
 
104
 
 
105
        nih_assert (connection != NULL);
 
106
        nih_assert (path != NULL);
 
107
        nih_assert ((lost_handler == NULL) || (name != NULL));
 
108
 
 
109
        proxy = nih_new (parent, NihDBusProxy);
 
110
        if (! proxy)
 
111
                nih_return_no_memory_error (NULL);
 
112
 
 
113
        proxy->connection = connection;
 
114
 
 
115
        proxy->name = NULL;
 
116
        if (name) {
 
117
                proxy->name = nih_strdup (proxy, name);
 
118
                if (! proxy->name) {
 
119
                        nih_free (proxy);
 
120
                        nih_return_no_memory_error (NULL);
 
121
                }
 
122
        }
 
123
 
 
124
        proxy->owner = NULL;
 
125
 
 
126
        proxy->path = nih_strdup (proxy, path);
 
127
        if (! proxy->path) {
 
128
                nih_free (proxy);
 
129
                nih_return_no_memory_error (NULL);
 
130
        }
 
131
 
 
132
        proxy->auto_start = TRUE;
 
133
 
 
134
        proxy->lost_handler = lost_handler;
 
135
        proxy->data = data;
 
136
 
 
137
        if (proxy->name) {
 
138
                if (nih_dbus_proxy_name_track (proxy) < 0) {
 
139
                        nih_free (proxy);
 
140
                        return NULL;
 
141
                }
 
142
        }
 
143
 
 
144
        dbus_connection_ref (proxy->connection);
 
145
        nih_alloc_set_destructor (proxy, nih_dbus_proxy_destroy);
 
146
 
 
147
        return proxy;
 
148
}
 
149
 
 
150
/**
 
151
 * nih_dbus_proxy_destroy:
 
152
 * @proxy: proxy object being destroyed.
 
153
 *
 
154
 * Destructor function for an NihDBusProxy structure; drops the bus rule
 
155
 * matching the NameOwnerChanged signal, the associated filter function,
 
156
 * and the reference to the D-Bus connection it holds.
 
157
 *
 
158
 * Returns: always zero.
 
159
 **/
 
160
static int
 
161
nih_dbus_proxy_destroy (NihDBusProxy *proxy)
 
162
{
 
163
        nih_local char *rule = NULL;
 
164
        DBusError       dbus_error;
 
165
 
 
166
        nih_assert (proxy != NULL);
 
167
 
 
168
        if (proxy->name) {
 
169
                rule = NIH_MUST (nih_dbus_proxy_name_rule (NULL, proxy));
 
170
 
 
171
                dbus_error_init (&dbus_error);
 
172
                dbus_bus_remove_match (proxy->connection, rule, &dbus_error);
 
173
                dbus_error_free (&dbus_error);
 
174
 
 
175
                dbus_connection_remove_filter (proxy->connection,
 
176
                                               (DBusHandleMessageFunction)nih_dbus_proxy_name_owner_changed,
 
177
                                               proxy);
 
178
        }
 
179
 
 
180
        dbus_connection_unref (proxy->connection);
 
181
 
 
182
        return 0;
 
183
}
 
184
 
 
185
 
 
186
/**
 
187
 * nih_dbus_proxy_name_track:
 
188
 * @proxy: proxy object.
 
189
 *
 
190
 * Set up name tracking for the given @proxy object.  We get the current
 
191
 * owner of the name in a synchronous call and set the connection up to
 
192
 * watch for a change in that owner updating the proxy's owner member in
 
193
 * both cases.
 
194
 *
 
195
 * If the proxy has no owner, the connection is instead set up to wait
 
196
 * for it to come onto the bus, and then reset later.
 
197
 *
 
198
 * Returns: 0 on success, negative value on raised error.
 
199
 **/
 
200
static int
 
201
nih_dbus_proxy_name_track (NihDBusProxy *proxy)
 
202
{
 
203
        nih_local char *rule = NULL;
 
204
        DBusError       dbus_error;
 
205
        DBusMessage *   method_call;
 
206
        DBusMessage *   reply;
 
207
        const char *    owner;
 
208
 
 
209
        nih_assert (proxy != NULL);
 
210
        nih_assert (proxy->name != NULL);
 
211
 
 
212
        /* Add the filter function that handles the NameOwnerChanged
 
213
         * signal.  We need to do this first so that we can handle anything
 
214
         * that arrives after we add the signal match.
 
215
         */
 
216
        if (! dbus_connection_add_filter (proxy->connection,
 
217
                                          (DBusHandleMessageFunction)nih_dbus_proxy_name_owner_changed,
 
218
                                          proxy, NULL))
 
219
                nih_return_no_memory_error (-1);
 
220
 
 
221
        /* Ask the bus to send us matching signals.  We've put the filter
 
222
         * function in place so we'll get callbacks straight away; but we
 
223
         * still need to do this before asking for the current name so
 
224
         * we don't miss something.
 
225
         */
 
226
        rule = nih_dbus_proxy_name_rule (NULL, proxy);
 
227
        if (! rule) {
 
228
                nih_error_raise_no_memory ();
 
229
                goto error_after_filter;
 
230
        }
 
231
 
 
232
        dbus_error_init (&dbus_error);
 
233
 
 
234
        dbus_bus_add_match (proxy->connection, rule, &dbus_error);
 
235
        if (dbus_error_is_set (&dbus_error)) {
 
236
                if (dbus_error_has_name (&dbus_error, DBUS_ERROR_NO_MEMORY)) {
 
237
                        nih_error_raise_no_memory ();
 
238
                } else {
 
239
                        nih_dbus_error_raise (dbus_error.name,
 
240
                                              dbus_error.message);
 
241
                }
 
242
 
 
243
                dbus_error_free (&dbus_error);
 
244
                goto error_after_filter;
 
245
        }
 
246
 
 
247
        /* Now that the bus will send us signals about changes in the name's
 
248
         * owner, and we'll handle them, we can get the current owner of the
 
249
         * name.  We may have some signals in the queue that predate this,
 
250
         * but the end result will be the same.
 
251
         */
 
252
        method_call = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
 
253
                                                    DBUS_PATH_DBUS,
 
254
                                                    DBUS_INTERFACE_DBUS,
 
255
                                                    "GetNameOwner");
 
256
        if (! method_call) {
 
257
                nih_error_raise_no_memory ();
 
258
 
 
259
                dbus_error_free (&dbus_error);
 
260
                goto error_after_match;
 
261
        }
 
262
 
 
263
        if (! dbus_message_append_args (method_call,
 
264
                                        DBUS_TYPE_STRING, &proxy->name,
 
265
                                        DBUS_TYPE_INVALID)) {
 
266
                nih_error_raise_no_memory ();
 
267
 
 
268
                dbus_message_unref (method_call);
 
269
                dbus_error_free (&dbus_error);
 
270
                goto error_after_match;
 
271
        }
 
272
 
 
273
        /* Parse the reply; an owner is returned, we fill in the owner
 
274
         * member of the proxy - otherwise we set it to NULL.
 
275
         */
 
276
        reply = dbus_connection_send_with_reply_and_block (proxy->connection, method_call,
 
277
                                                           -1, &dbus_error);
 
278
        if (! reply) {
 
279
                if (dbus_error_has_name (&dbus_error,
 
280
                                         DBUS_ERROR_NAME_HAS_NO_OWNER)) {
 
281
                        nih_debug ("%s is not currently owned", proxy->name);
 
282
 
 
283
                        dbus_message_unref (method_call);
 
284
                        dbus_error_free (&dbus_error);
 
285
 
 
286
                        /* Not an error */
 
287
                        return 0;
 
288
 
 
289
                } else if (dbus_error_has_name (&dbus_error,
 
290
                                                DBUS_ERROR_NO_MEMORY)) {
 
291
                        nih_error_raise_no_memory ();
 
292
                } else {
 
293
                        nih_dbus_error_raise (dbus_error.name,
 
294
                                              dbus_error.message);
 
295
                }
 
296
 
 
297
                dbus_message_unref (method_call);
 
298
                dbus_error_free (&dbus_error);
 
299
                goto error_after_match;
 
300
        }
 
301
 
 
302
        dbus_message_unref (method_call);
 
303
 
 
304
        if (! dbus_message_get_args (reply, &dbus_error,
 
305
                                     DBUS_TYPE_STRING, &owner,
 
306
                                     DBUS_TYPE_INVALID)) {
 
307
                if (dbus_error_has_name (&dbus_error, DBUS_ERROR_NO_MEMORY)) {
 
308
                        nih_error_raise_no_memory ();
 
309
                } else {
 
310
                        nih_dbus_error_raise (dbus_error.name,
 
311
                                              dbus_error.message);
 
312
                }
 
313
 
 
314
                dbus_message_unref (reply);
 
315
                dbus_error_free (&dbus_error);
 
316
                goto error_after_match;
 
317
        }
 
318
 
 
319
        dbus_error_free (&dbus_error);
 
320
 
 
321
        proxy->owner = nih_strdup (proxy, owner);
 
322
        if (! proxy->owner) {
 
323
                nih_error_raise_no_memory ();
 
324
 
 
325
                dbus_message_unref (reply);
 
326
                goto error_after_match;
 
327
        }
 
328
 
 
329
        dbus_message_unref (reply);
 
330
 
 
331
        nih_debug ("%s is currently owned by %s", proxy->name, proxy->owner);
 
332
 
 
333
        return 0;
 
334
 
 
335
error_after_match:
 
336
        dbus_error_init (&dbus_error);
 
337
        dbus_bus_remove_match (proxy->connection, rule, &dbus_error);
 
338
        dbus_error_free (&dbus_error);
 
339
error_after_filter:
 
340
        dbus_connection_remove_filter (proxy->connection,
 
341
                                       (DBusHandleMessageFunction)nih_dbus_proxy_name_owner_changed,
 
342
                                       proxy);
 
343
 
 
344
        return -1;
 
345
}
 
346
 
 
347
/**
 
348
 * nih_dbus_proxy_name_rule:
 
349
 * @parent: parent object for new string,
 
350
 * @proxy: proxy object.
 
351
 *
 
352
 * Generates a D-Bus match rule for the NameOwnerChanged signal for the
 
353
 * given @proxy.
 
354
 *
 
355
 * If @parent is not NULL, it should be a pointer to another object which
 
356
 * will be used as a parent for the returned string.  When all parents
 
357
 * of the returned string are freed, the returned string will also be
 
358
 * freed.
 
359
 *
 
360
 * Returns: newly allocated string or NULL on insufficient memory.
 
361
 **/
 
362
static char *
 
363
nih_dbus_proxy_name_rule (const void *  parent,
 
364
                          NihDBusProxy *proxy)
 
365
{
 
366
        char *rule;
 
367
 
 
368
        nih_assert (proxy != NULL);
 
369
        nih_assert (proxy->name != NULL);
 
370
 
 
371
        rule = nih_sprintf (parent, ("type='%s',sender='%s',path='%s',"
 
372
                                     "interface='%s',member='%s',"
 
373
                                     "arg0='%s'"),
 
374
                            "signal",
 
375
                            DBUS_SERVICE_DBUS,
 
376
                            DBUS_PATH_DBUS,
 
377
                            DBUS_INTERFACE_DBUS,
 
378
                            "NameOwnerChanged",
 
379
                            proxy->name);
 
380
 
 
381
        return rule;
 
382
}
 
383
 
 
384
/**
 
385
 * nih_dbus_proxy_name_owner_changed:
 
386
 * @connection: D-Bus connection signal received on,
 
387
 * @message: signal message,
 
388
 * @proxy: associated proxy object.
 
389
 *
 
390
 * This function is called by D-Bus on receipt of the NameOwnerChanged
 
391
 * signal for the registered name that @proxy represents.  The proxy's
 
392
 * lost_handler function is called to decide what to do about it.
 
393
 *
 
394
 * Returns: usually DBUS_HANDLER_RESULT_NOT_YET_HANDLED so other signal
 
395
 * handlers also get a look-in, DBUS_HANDLED_RESULT_NEED_MEMORY if
 
396
 * insufficient memory.
 
397
 **/
 
398
static DBusHandlerResult
 
399
nih_dbus_proxy_name_owner_changed (DBusConnection *connection,
 
400
                                   DBusMessage *   message,
 
401
                                   NihDBusProxy *  proxy)
 
402
{
 
403
        DBusError   dbus_error;
 
404
        const char *name;
 
405
        const char *old_owner;
 
406
        const char *new_owner;
 
407
 
 
408
        nih_assert (connection != NULL);
 
409
        nih_assert (message != NULL);
 
410
        nih_assert (proxy->connection == connection);
 
411
        nih_assert (proxy->name != NULL);
 
412
 
 
413
        if (! dbus_message_is_signal (message, DBUS_INTERFACE_DBUS,
 
414
                                      "NameOwnerChanged"))
 
415
                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
416
 
 
417
        if (! dbus_message_has_path (message, DBUS_PATH_DBUS))
 
418
                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
419
 
 
420
        if (! dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
 
421
                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
422
 
 
423
        dbus_error_init (&dbus_error);
 
424
        if (! dbus_message_get_args (message, &dbus_error,
 
425
                                     DBUS_TYPE_STRING, &name,
 
426
                                     DBUS_TYPE_STRING, &old_owner,
 
427
                                     DBUS_TYPE_STRING, &new_owner,
 
428
                                     DBUS_TYPE_INVALID)) {
 
429
                dbus_error_free (&dbus_error);
 
430
                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
431
        }
 
432
 
 
433
        dbus_error_free (&dbus_error);
 
434
 
 
435
        if (strcmp (name, proxy->name))
 
436
                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
437
 
 
438
        /* Ok, it's really the right NameOwnerChanged signal.  If the name
 
439
         * has a new owner, update the owner property (tracking a well known
 
440
         * name between instances) otherwise call the lost handler.
 
441
         */
 
442
        if (strlen (new_owner)) {
 
443
                nih_debug ("%s changed owner from %s to %s",
 
444
                           proxy->name, old_owner, new_owner);
 
445
 
 
446
                if (proxy->owner)
 
447
                        nih_unref (proxy->owner, proxy);
 
448
                proxy->owner = NIH_MUST (nih_strdup (proxy, new_owner));
 
449
        } else {
 
450
                nih_debug ("%s owner left the bus", proxy->name);
 
451
 
 
452
                if (proxy->owner)
 
453
                        nih_unref (proxy->owner, proxy);
 
454
                proxy->owner = NULL;
 
455
 
 
456
                if (proxy->lost_handler) {
 
457
                        nih_error_push_context ();
 
458
                        proxy->lost_handler (proxy->data, proxy);
 
459
                        nih_error_pop_context ();
 
460
                }
 
461
        }
 
462
 
 
463
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
464
}
 
465
 
 
466
 
 
467
/**
 
468
 * nih_dbus_proxy_connect:
 
469
 * @proxy: proxy for remote object,
 
470
 * @interface: signal interface definition,
 
471
 * @name: name of signal,
 
472
 * @handler: signal handler function,
 
473
 * @data: data to pass to @handler.
 
474
 *
 
475
 * Connect the signal @name on @interface to @proxy so that the @handler
 
476
 * function is passed to the filter function defined by @signal when it
 
477
 * is received on the proxied D-Bus connection.
 
478
 *
 
479
 * The signal can be disconnected by freeing the returned structure, the
 
480
 * signal is also bound to the lifetime of @proxy so that the signal is
 
481
 * disconnected when the proxy is freed.
 
482
 *
 
483
 * Returns: newly allocated NihDBusProxySignal structure or NULL on raised
 
484
 * error.
 
485
 **/
 
486
NihDBusProxySignal *
 
487
nih_dbus_proxy_connect (NihDBusProxy *          proxy,
 
488
                        const NihDBusInterface *interface,
 
489
                        const char *            name,
 
490
                        NihDBusSignalHandler    handler,
 
491
                        void *                  data)
 
492
{
 
493
        NihDBusProxySignal *proxied;
 
494
        nih_local char *    rule = NULL;
 
495
        DBusError           dbus_error;
 
496
 
 
497
        nih_assert (proxy != NULL);
 
498
        nih_assert (interface != NULL);
 
499
        nih_assert (name != NULL);
 
500
        nih_assert (handler != NULL);
 
501
 
 
502
        proxied = nih_new (proxy, NihDBusProxySignal);
 
503
        if (! proxied)
 
504
                nih_return_no_memory_error (NULL);
 
505
 
 
506
        proxied->proxy = proxy;
 
507
        proxied->interface = interface;
 
508
        proxied->signal = NULL;
 
509
        proxied->handler = handler;
 
510
        proxied->data = data;
 
511
 
 
512
        for (const NihDBusSignal *signal = interface->signals;
 
513
             signal && signal->name; signal++) {
 
514
                if (! strcmp (signal->name, name)) {
 
515
                        proxied->signal = signal;
 
516
                        break;
 
517
                }
 
518
        }
 
519
        nih_assert (proxied->signal != NULL);
 
520
 
 
521
        if (! dbus_connection_add_filter (proxied->proxy->connection,
 
522
                                          (DBusHandleMessageFunction)proxied->signal->filter,
 
523
                                          proxied, NULL)) {
 
524
                nih_free (proxied);
 
525
                nih_return_no_memory_error (NULL);
 
526
        }
 
527
 
 
528
        if (proxied->proxy->name) {
 
529
                rule = nih_dbus_proxy_signal_rule (NULL, proxied);
 
530
                if (! rule) {
 
531
                        nih_error_raise_no_memory ();
 
532
                        goto error;
 
533
                }
 
534
 
 
535
                dbus_error_init (&dbus_error);
 
536
 
 
537
                dbus_bus_add_match (proxied->proxy->connection, rule, &dbus_error);
 
538
                if (dbus_error_is_set (&dbus_error)) {
 
539
                        if (dbus_error_has_name (&dbus_error, DBUS_ERROR_NO_MEMORY)) {
 
540
                                nih_error_raise_no_memory ();
 
541
                        } else {
 
542
                                nih_dbus_error_raise (dbus_error.name,
 
543
                                                      dbus_error.message);
 
544
                        }
 
545
 
 
546
                        dbus_error_free (&dbus_error);
 
547
                        goto error;
 
548
                }
 
549
        }
 
550
 
 
551
        nih_alloc_set_destructor (proxied, nih_dbus_proxy_signal_destroy);
 
552
 
 
553
        return proxied;
 
554
 
 
555
error:
 
556
        dbus_connection_remove_filter (proxied->proxy->connection,
 
557
                                       (DBusHandleMessageFunction)proxied->signal->filter,
 
558
                                       proxied);
 
559
        nih_free (proxied);
 
560
 
 
561
        return NULL;
 
562
}
 
563
 
 
564
/**
 
565
 * nih_dbus_proxy_signal_destroy:
 
566
 * @proxied: proxied signal being destroyed.
 
567
 *
 
568
 * Destructor function for an NihDBusProxySignal structure; drops the bus
 
569
 * rule matching the signal and the associated filter function.
 
570
 *
 
571
 * Returns: always zero.
 
572
 **/
 
573
static int
 
574
nih_dbus_proxy_signal_destroy (NihDBusProxySignal *proxied)
 
575
{
 
576
        nih_local char *rule = NULL;
 
577
        DBusError       dbus_error;
 
578
 
 
579
        nih_assert (proxied != NULL);
 
580
 
 
581
        if (proxied->proxy->name) {
 
582
                rule = NIH_MUST (nih_dbus_proxy_signal_rule (NULL, proxied));
 
583
 
 
584
                dbus_error_init (&dbus_error);
 
585
                dbus_bus_remove_match (proxied->proxy->connection,
 
586
                                       rule, &dbus_error);
 
587
                dbus_error_free (&dbus_error);
 
588
        }
 
589
 
 
590
        dbus_connection_remove_filter (proxied->proxy->connection,
 
591
                                       (DBusHandleMessageFunction)proxied->signal->filter,
 
592
                                       proxied);
 
593
 
 
594
        return 0;
 
595
}
 
596
 
 
597
/**
 
598
 * nih_dbus_proxy_signal_rule:
 
599
 * @parent: parent object for new string,
 
600
 * @proxied: proxied signal.
 
601
 *
 
602
 * Generates a D-Bus match rule for the @proxied signal.
 
603
 *
 
604
 * If @parent is not NULL, it should be a pointer to another object which
 
605
 * will be used as a parent for the returned string.  When all parents
 
606
 * of the returned string are freed, the returned string will also be
 
607
 * freed.
 
608
 *
 
609
 * Returns: newly allocated string or NULL on insufficient memory.
 
610
 **/
 
611
static char *
 
612
nih_dbus_proxy_signal_rule (const void *        parent,
 
613
                            NihDBusProxySignal *proxied)
 
614
{
 
615
        char *rule;
 
616
 
 
617
        nih_assert (proxied != NULL);
 
618
        nih_assert (proxied->proxy->name != NULL);
 
619
 
 
620
        rule = nih_sprintf (parent, ("type='%s',sender='%s',path='%s',"
 
621
                                     "interface='%s',member='%s'"),
 
622
                            "signal",
 
623
                            proxied->proxy->name,
 
624
                            proxied->proxy->path,
 
625
                            proxied->interface->name,
 
626
                            proxied->signal->name);
 
627
 
 
628
        return rule;
 
629
}