2003-10-16 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / dbus / dbus-bus.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-bus.c  Convenience functions for communicating with the bus.
3  *
4  * Copyright (C) 2003  CodeFactory AB
5  * Copyright (C) 2003  Red Hat, Inc.
6  *
7  * Licensed under the Academic Free License version 1.2
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24
25 #include "dbus-bus.h"
26 #include "dbus-protocol.h"
27 #include "dbus-internals.h"
28 #include "dbus-message.h"
29 #include <string.h>
30
31 /**
32  * @defgroup DBusBus Message bus APIs
33  * @ingroup DBus
34  * @brief Functions for communicating with the message bus
35  *
36  * @todo right now the default address of the system bus is hardcoded,
37  * so if you change it in the global config file suddenly you have to
38  * set DBUS_SYSTEM_BUS_ADDRESS env variable.  Might be nice if the
39  * client lib somehow read the config file, or if the bus on startup
40  * somehow wrote out its address to a well-known spot, but might also
41  * not be worth it.
42  */
43
44 /**
45  * @defgroup DBusBusInternals Message bus APIs internals
46  * @ingroup DBusInternals
47  * @brief Internals of functions for communicating with the message bus
48  *
49  * @{
50  */
51
52 /**
53  * Block of message-bus-related data we attach to each
54  * #DBusConnection used with these convenience functions.
55  *
56  *
57  * @todo get rid of most of these; they should be done
58  * with DBusGProxy and the Qt equivalent, i.e. the same
59  * way any other interface would be used.
60  */
61 typedef struct
62 {
63   DBusConnection *connection; /**< Connection we're associated with */
64   char *base_service; /**< Base service name of this connection */
65
66   unsigned int is_well_known : 1; /**< Is one of the well-known connections in our global array */
67 } BusData;
68
69 /** The slot we have reserved to store BusData.
70  */
71 static dbus_int32_t bus_data_slot = -1;
72
73 /** Number of bus types */
74 #define N_BUS_TYPES 3
75
76 static DBusConnection *bus_connections[N_BUS_TYPES];
77 static char *bus_connection_addresses[N_BUS_TYPES] = { NULL, NULL, NULL };
78
79 static DBusBusType activation_bus_type = DBUS_BUS_ACTIVATION;
80
81 static dbus_bool_t initialized = FALSE;
82
83 /**
84  * Lock for globals in this file
85  */
86 _DBUS_DEFINE_GLOBAL_LOCK (bus);
87
88 static void
89 addresses_shutdown_func (void *data)
90 {
91   int i;
92
93   i = 0;
94   while (i < N_BUS_TYPES)
95     {
96       if (bus_connections[i] != NULL)
97         _dbus_warn ("dbus_shutdown() called but connections were still live!");
98       
99       dbus_free (bus_connection_addresses[i]);
100       bus_connection_addresses[i] = NULL;
101       ++i;
102     }
103
104   activation_bus_type = DBUS_BUS_ACTIVATION;
105 }
106
107 static dbus_bool_t
108 get_from_env (char           **connection_p,
109               const char      *env_var)
110 {
111   const char *s;
112   
113   _dbus_assert (*connection_p == NULL);
114   
115   s = _dbus_getenv (env_var);
116   if (s == NULL || *s == '\0')
117     return TRUE; /* successfully didn't use the env var */
118   else
119     {
120       *connection_p = _dbus_strdup (s);
121       return *connection_p != NULL;
122     }
123 }
124
125 static dbus_bool_t
126 init_connections_unlocked (void)
127 {
128   if (!initialized)
129     {
130       const char *s;
131       int i;
132
133       i = 0;
134       while (i < N_BUS_TYPES)
135         {
136           bus_connections[i] = NULL;
137           ++i;
138         }
139
140       /* Don't init these twice, we may run this code twice if
141        * init_connections_unlocked() fails midway through.
142        */
143       
144        if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
145          {
146            _dbus_verbose ("Filling in system bus address...\n");
147            
148            if (!get_from_env (&bus_connection_addresses[DBUS_BUS_SYSTEM],
149                               "DBUS_SYSTEM_BUS_ADDRESS"))
150              return FALSE;
151            
152            if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
153              {
154                /* Use default system bus address if none set in environment */
155                bus_connection_addresses[DBUS_BUS_SYSTEM] =
156                  _dbus_strdup (DBUS_SYSTEM_BUS_DEFAULT_ADDRESS);
157                if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
158                  return FALSE;
159
160                _dbus_verbose ("  used default system bus \"%s\"\n",
161                               bus_connection_addresses[DBUS_BUS_SYSTEM]);
162              }
163            else
164              _dbus_verbose ("  used env var system bus \"%s\"\n",
165                             bus_connection_addresses[DBUS_BUS_SYSTEM]);
166          }
167           
168       if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL)
169         {
170           _dbus_verbose ("Filling in session bus address...\n");
171           
172           if (!get_from_env (&bus_connection_addresses[DBUS_BUS_SESSION],
173                              "DBUS_SESSION_BUS_ADDRESS"))
174             return FALSE;
175           _dbus_verbose ("  \"%s\"\n", bus_connection_addresses[DBUS_BUS_SESSION] ?
176                          bus_connection_addresses[DBUS_BUS_SESSION] : "none set");
177         }
178
179       if (bus_connection_addresses[DBUS_BUS_ACTIVATION] == NULL)
180         {
181           _dbus_verbose ("Filling in activation bus address...\n");
182           
183           if (!get_from_env (&bus_connection_addresses[DBUS_BUS_ACTIVATION],
184                              "DBUS_ACTIVATION_ADDRESS"))
185             return FALSE;
186
187           _dbus_verbose ("  \"%s\"\n", bus_connection_addresses[DBUS_BUS_ACTIVATION] ?
188                          bus_connection_addresses[DBUS_BUS_ACTIVATION] : "none set");
189         }
190
191       s = _dbus_getenv ("DBUS_ACTIVATION_BUS_TYPE");
192
193       if (s != NULL)
194         {
195           _dbus_verbose ("Bus activation type was set to \"%s\"\n", s);
196           
197           if (strcmp (s, "system") == 0)
198             activation_bus_type = DBUS_BUS_SYSTEM;
199           else if (strcmp (s, "session") == 0)
200             activation_bus_type = DBUS_BUS_SESSION;
201         }
202
203       /* If we return FALSE we have to be sure that restarting
204        * the above code will work right
205        */
206       
207       if (!_dbus_setenv ("DBUS_ACTIVATION_ADDRESS", NULL))
208         return FALSE;
209
210       if (!_dbus_setenv ("DBUS_ACTIVATION_BUS_TYPE", NULL))
211         return FALSE;
212       
213       if (!_dbus_register_shutdown_func (addresses_shutdown_func,
214                                          NULL))
215         return FALSE;
216       
217       initialized = TRUE;
218     }
219
220   return initialized;
221 }
222
223 static void
224 bus_data_free (void *data)
225 {
226   BusData *bd = data;
227   
228   if (bd->is_well_known)
229     {
230       int i;
231       _DBUS_LOCK (bus);
232       /* We may be stored in more than one slot */
233       i = 0;
234       while (i < N_BUS_TYPES)
235         {
236           if (bus_connections[i] == bd->connection)
237             bus_connections[i] = NULL;
238           
239           ++i;
240         }
241       _DBUS_UNLOCK (bus);
242     }
243   
244   dbus_free (bd->base_service);
245   dbus_free (bd);
246
247   dbus_connection_free_data_slot (&bus_data_slot);
248 }
249
250 static BusData*
251 ensure_bus_data (DBusConnection *connection)
252 {
253   BusData *bd;
254
255   if (!dbus_connection_allocate_data_slot (&bus_data_slot))
256     return NULL;
257
258   bd = dbus_connection_get_data (connection, bus_data_slot);
259   if (bd == NULL)
260     {      
261       bd = dbus_new0 (BusData, 1);
262       if (bd == NULL)
263         {
264           dbus_connection_free_data_slot (&bus_data_slot);
265           return NULL;
266         }
267
268       bd->connection = connection;
269       
270       if (!dbus_connection_set_data (connection, bus_data_slot, bd,
271                                      bus_data_free))
272         {
273           dbus_free (bd);
274           dbus_connection_free_data_slot (&bus_data_slot);
275           return NULL;
276         }
277
278       /* Data slot refcount now held by the BusData */
279     }
280   else
281     {
282       dbus_connection_free_data_slot (&bus_data_slot);
283     }
284
285   return bd;
286 }
287
288 /** @} */ /* end of implementation details docs */
289
290 /**
291  * @addtogroup DBusBus
292  * @{
293  */
294
295 /**
296  * Connects to a bus daemon and registers the client with it.
297  * If a connection to the bus already exists, then that connection is returned.
298  *
299  * @todo alex thinks we should nullify the connection when we get a disconnect-message.
300  *
301  * @param type bus type
302  * @param error address where an error can be returned.
303  * @returns a DBusConnection
304  */
305 DBusConnection *
306 dbus_bus_get (DBusBusType  type,
307               DBusError   *error)
308 {
309   const char *address;
310   DBusConnection *connection;
311   BusData *bd;
312   DBusBusType address_type;
313
314   _dbus_return_val_if_fail (type >= 0 && type < N_BUS_TYPES, NULL);
315   _dbus_return_val_if_error_is_set (error, NULL);
316
317   _DBUS_LOCK (bus);
318
319   if (!init_connections_unlocked ())
320     {
321       _DBUS_UNLOCK (bus);
322       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
323       return NULL;
324     }
325
326   /* We want to use the activation address even if the
327    * activating bus is the session or system bus,
328    * per the spec.
329    */
330   address_type = type;
331   
332   /* Use the real type of the activation bus for getting its
333    * connection, but only if the real type's address is available. (If
334    * the activating bus isn't a well-known bus then
335    * activation_bus_type == DBUS_BUS_ACTIVATION)
336    */
337   if (type == DBUS_BUS_ACTIVATION &&
338       bus_connection_addresses[activation_bus_type] != NULL)
339     type = activation_bus_type;
340   
341   if (bus_connections[type] != NULL)
342     {
343       connection = bus_connections[type];
344       dbus_connection_ref (connection);
345       
346       _DBUS_UNLOCK (bus);
347       return connection;
348     }
349
350   address = bus_connection_addresses[address_type];
351   if (address == NULL)
352     {
353       dbus_set_error (error, DBUS_ERROR_FAILED,
354                       "Unable to determine the address of the message bus");
355       _DBUS_UNLOCK (bus);
356       return NULL;
357     }
358
359   connection = dbus_connection_open (address, error);
360   
361   if (!connection)
362     {
363       _DBUS_ASSERT_ERROR_IS_SET (error);
364       _DBUS_UNLOCK (bus);
365       return NULL;
366     }
367
368   /* By default we're bound to the lifecycle of
369    * the message bus.
370    */
371   dbus_connection_set_exit_on_disconnect (connection,
372                                           TRUE);
373   
374   if (!dbus_bus_register (connection, error))
375     {
376       _DBUS_ASSERT_ERROR_IS_SET (error);
377       dbus_connection_disconnect (connection);
378       dbus_connection_unref (connection);
379
380       _DBUS_UNLOCK (bus);
381       return NULL;
382     }
383
384   bus_connections[type] = connection;
385   bd = ensure_bus_data (connection);
386   _dbus_assert (bd != NULL);
387
388   bd->is_well_known = TRUE;
389
390   _DBUS_UNLOCK (bus);
391   return connection;
392 }
393
394
395 /**
396  * Registers a connection with the bus. This must be the first
397  * thing an application does when connecting to the message bus.
398  * If registration succeeds, the base service name will be set,
399  * and can be obtained using dbus_bus_get_base_service().
400  *
401  * @todo if we get an error reply, it has to be converted into
402  * DBusError and returned
403  * 
404  * @param connection the connection
405  * @param error place to store errors
406  * @returns #TRUE on success
407  */
408 dbus_bool_t
409 dbus_bus_register (DBusConnection *connection,
410                    DBusError      *error)
411 {
412   DBusMessage *message, *reply;
413   char *name;
414   BusData *bd;
415   dbus_bool_t retval;
416
417   _dbus_return_val_if_fail (connection != NULL, FALSE);
418   _dbus_return_val_if_error_is_set (error, FALSE);
419
420   retval = FALSE;
421   
422   bd = ensure_bus_data (connection);
423   if (bd == NULL)
424     {
425       _DBUS_SET_OOM (error);
426       return FALSE;
427     }
428
429   if (bd->base_service != NULL)
430     {
431       _dbus_warn ("Attempt to register the same DBusConnection with the message bus, but it is already registered\n");
432       /* This isn't an error, it's a programming bug. We'll be nice
433        * and not _dbus_assert_not_reached()
434        */
435       return TRUE;
436     }
437   
438   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
439                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
440                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
441                                           "Hello"); 
442
443   if (!message)
444     {
445       _DBUS_SET_OOM (error);
446       return FALSE;
447     }
448   
449   reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
450
451   dbus_message_unref (message);
452   
453   if (reply == NULL)
454     goto out;
455   else if (dbus_set_error_from_message (error, reply))
456     goto out;
457   else if (!dbus_message_get_args (reply, error,
458                                    DBUS_TYPE_STRING, &name,
459                                    DBUS_TYPE_INVALID))
460     goto out;
461   
462   bd->base_service = name;
463
464   retval = TRUE;
465   
466  out:
467   if (reply)
468     dbus_message_unref (reply);
469
470   if (!retval)
471     _DBUS_ASSERT_ERROR_IS_SET (error);
472   
473   return retval;
474 }
475
476
477 /**
478  * Sets the base service name of the connection.
479  * Can only be used if you registered with the
480  * bus manually (i.e. if you did not call
481  * dbus_bus_register()). Can only be called
482  * once per connection.
483  *
484  * @param connection the connection
485  * @param base_service the base service name
486  * @returns #FALSE if not enough memory
487  */
488 dbus_bool_t
489 dbus_bus_set_base_service (DBusConnection *connection,
490                            const char     *base_service)
491 {
492   BusData *bd;
493
494   _dbus_return_val_if_fail (connection != NULL, FALSE);
495   _dbus_return_val_if_fail (base_service != NULL, FALSE);
496   
497   bd = ensure_bus_data (connection);
498   if (bd == NULL)
499     return FALSE;
500
501   _dbus_assert (bd->base_service == NULL);
502   
503   bd->base_service = _dbus_strdup (base_service);
504   return bd->base_service != NULL;
505 }
506
507 /**
508  * Gets the base service name of the connection.
509  * Only possible after the connection has been registered
510  * with the message bus.
511  *
512  * @param connection the connection
513  * @returns the base service name
514  */
515 const char*
516 dbus_bus_get_base_service (DBusConnection *connection)
517 {
518   BusData *bd;
519
520   _dbus_return_val_if_fail (connection != NULL, NULL);
521   
522   bd = ensure_bus_data (connection);
523   if (bd == NULL)
524     return NULL;
525   
526   return bd->base_service;
527 }
528
529 /**
530  * Asks the bus to try to acquire a certain service.
531  *
532  * @todo these docs are not complete, need to document the
533  * return value and flags
534  * 
535  * @todo if we get an error reply, it has to be converted into
536  * DBusError and returned
537  *
538  * @param connection the connection
539  * @param service_name the service name
540  * @param flags flags
541  * @param error location to store the error
542  * @returns a result code, -1 if error is set
543  */ 
544 int
545 dbus_bus_acquire_service (DBusConnection *connection,
546                           const char     *service_name,
547                           unsigned int    flags,
548                           DBusError      *error)
549 {
550   DBusMessage *message, *reply;
551   dbus_uint32_t service_result;
552
553   _dbus_return_val_if_fail (connection != NULL, 0);
554   _dbus_return_val_if_fail (service_name != NULL, 0);
555   _dbus_return_val_if_error_is_set (error, 0);
556   
557   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
558                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
559                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
560                                           "AcquireService");
561
562   if (message == NULL)
563     {
564       _DBUS_SET_OOM (error);
565       return -1;
566     }
567  
568   if (!dbus_message_append_args (message,
569                                  DBUS_TYPE_STRING, service_name,
570                                  DBUS_TYPE_UINT32, flags,
571                                  DBUS_TYPE_INVALID))
572     {
573       dbus_message_unref (message);
574       _DBUS_SET_OOM (error);
575       return -1;
576     }
577   
578   reply = dbus_connection_send_with_reply_and_block (connection, message, -1,
579                                                      error);
580   
581   dbus_message_unref (message);
582   
583   if (reply == NULL)
584     {
585       _DBUS_ASSERT_ERROR_IS_SET (error);
586       return -1;
587     }  
588
589   if (dbus_set_error_from_message (error, reply))
590     {
591       _DBUS_ASSERT_ERROR_IS_SET (error);
592       dbus_message_unref (reply);
593       return -1;
594     }
595   
596   if (!dbus_message_get_args (reply, error,
597                               DBUS_TYPE_UINT32, &service_result,
598                               DBUS_TYPE_INVALID))
599     {
600       _DBUS_ASSERT_ERROR_IS_SET (error);
601       dbus_message_unref (reply);
602       return -1;
603     }
604
605   dbus_message_unref (reply);
606   
607   return service_result;
608 }
609
610 /**
611  * Checks whether a certain service exists.
612  *
613  * @todo the SERVICE_EXISTS message should use BOOLEAN not UINT32
614  *
615  * @param connection the connection
616  * @param service_name the service name
617  * @param error location to store any errors
618  * @returns #TRUE if the service exists, #FALSE if not or on error
619  */
620 dbus_bool_t
621 dbus_bus_service_exists (DBusConnection *connection,
622                          const char     *service_name,
623                          DBusError      *error)
624 {
625   DBusMessage *message, *reply;
626   unsigned int exists;
627
628   _dbus_return_val_if_fail (connection != NULL, FALSE);
629   _dbus_return_val_if_fail (service_name != NULL, FALSE);
630   _dbus_return_val_if_error_is_set (error, FALSE);
631   
632   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
633                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
634                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
635                                           "ServiceExists");
636   if (message == NULL)
637     {
638       _DBUS_SET_OOM (error);
639       return FALSE;
640     }
641   
642   if (!dbus_message_append_args (message,
643                                  DBUS_TYPE_STRING, service_name,
644                                  DBUS_TYPE_INVALID))
645     {
646       dbus_message_unref (message);
647       _DBUS_SET_OOM (error);
648       return FALSE;
649     }
650   
651   reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
652   dbus_message_unref (message);
653
654   if (reply == NULL)
655     {
656       _DBUS_ASSERT_ERROR_IS_SET (error);
657       return FALSE;
658     }
659
660   if (!dbus_message_get_args (reply, error,
661                               DBUS_TYPE_UINT32, &exists,
662                               DBUS_TYPE_INVALID))
663     {
664       _DBUS_ASSERT_ERROR_IS_SET (error);
665       return FALSE;
666     }
667   
668   return (exists != FALSE);
669 }
670
671 /**
672  * Activates a given service
673  *
674  * @param connection the connection
675  * @param service_name the service name
676  * @param flags the flags
677  * @param result a place to store the result of the activation, which will
678  * be one of DBUS_ACTIVATION_REPLY_ACTIVATED or
679  * DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE if successful.  Pass NULL if you
680  * don't care about the result.
681  * @param error location to store any errors
682  * @returns #TRUE if the activation succeeded, #FALSE if not
683  *
684  * @todo document what the flags do
685  */
686 dbus_bool_t
687 dbus_bus_activate_service (DBusConnection *connection,
688                            const char     *service_name,
689                            dbus_uint32_t   flags,
690                            dbus_uint32_t  *result,
691                            DBusError      *error)
692 {
693   DBusMessage *msg;
694   DBusMessage *reply;
695
696   msg = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
697                                       DBUS_PATH_ORG_FREEDESKTOP_DBUS,
698                                       DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
699                                       "ActivateService");
700
701   if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, service_name,
702                                  DBUS_TYPE_UINT32, flags, DBUS_TYPE_INVALID))
703     {
704       dbus_message_unref (msg);
705       _DBUS_SET_OOM (error);
706       return FALSE;
707     }
708
709   reply = dbus_connection_send_with_reply_and_block (connection, msg,
710                                                      -1, error);
711   dbus_message_unref (msg);
712
713   if (reply == NULL)
714     {
715       _DBUS_ASSERT_ERROR_IS_SET (error);
716       return FALSE;
717     }
718
719   if (dbus_set_error_from_message (error, reply))
720     {
721       _DBUS_ASSERT_ERROR_IS_SET (error);
722       dbus_message_unref (reply);
723       return FALSE;
724     }
725
726   if (result != NULL &&
727       !dbus_message_get_args (reply, error, DBUS_TYPE_UINT32,
728                               result, DBUS_TYPE_INVALID))
729     {
730       _DBUS_ASSERT_ERROR_IS_SET (error);
731       dbus_message_unref (reply);
732       return FALSE;
733     }
734   
735   dbus_message_unref (reply);
736   return TRUE;
737 }
738
739 static void
740 send_no_return_values (DBusConnection *connection,
741                        DBusMessage    *msg,
742                        DBusError      *error)
743 {
744   if (error)
745     {
746       /* Block to check success codepath */
747       DBusMessage *reply;
748       
749       reply = dbus_connection_send_with_reply_and_block (connection, msg,
750                                                          -1, error);
751       
752       if (reply == NULL)
753         {
754           _DBUS_ASSERT_ERROR_IS_SET (error);
755           return;
756         }
757
758       if (dbus_set_error_from_message (error, reply))
759         {
760           _DBUS_ASSERT_ERROR_IS_SET (error);
761           dbus_message_unref (reply);
762           return;
763         }
764
765       dbus_message_unref (reply);
766     }
767   else
768     {
769       /* Silently-fail nonblocking codepath */
770       if (!dbus_connection_send (connection, msg, NULL))
771         return;
772     }
773 }
774
775 /**
776  * Adds a match rule to match messages going through the message bus.
777  * The "rule" argument is the string form of a match rule.
778  *
779  * If you pass #NULL for the error, this function will not
780  * block; the match thus won't be added until you flush the
781  * connection, and if there's an error adding the match
782  * (only possible error is lack of resources in the bus),
783  * you won't find out about it.
784  *
785  * If you pass non-#NULL for the error this function will
786  * block until it gets a reply.
787  *
788  * Normal API conventions would have the function return
789  * a boolean value indicating whether the error was set,
790  * but that would require blocking always to determine
791  * the return value.
792  * 
793  * @param connection connection to the message bus
794  * @param rule textual form of match rule
795  * @param error location to store any errors
796  */
797 void
798 dbus_bus_add_match (DBusConnection *connection,
799                     const char     *rule,
800                     DBusError      *error)
801 {
802   DBusMessage *msg;
803
804   msg = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
805                                       DBUS_PATH_ORG_FREEDESKTOP_DBUS,
806                                       DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
807                                       "AddMatch");
808
809   if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, rule,
810                                  DBUS_TYPE_INVALID))
811     {
812       dbus_message_unref (msg);
813       _DBUS_SET_OOM (error);
814       return;
815     }
816
817   send_no_return_values (connection, msg, error);
818
819   dbus_message_unref (msg);
820 }
821
822 /**
823  * Removes a previously-added match rule "by value" (the most
824  * recently-added identical rule gets removed).  The "rule" argument
825  * is the string form of a match rule.
826  *
827  * If you pass #NULL for the error, this function will not
828  * block; otherwise it will. See detailed explanation in
829  * docs for dbus_bus_add_match().
830  * 
831  * @param connection connection to the message bus
832  * @param rule textual form of match rule
833  * @param error location to store any errors
834  */
835 void
836 dbus_bus_remove_match (DBusConnection *connection,
837                        const char     *rule,
838                        DBusError      *error)
839 {
840   DBusMessage *msg;
841
842   msg = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
843                                       DBUS_PATH_ORG_FREEDESKTOP_DBUS,
844                                       DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
845                                       "RemoveMatch");
846
847   if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, rule,
848                                  DBUS_TYPE_INVALID))
849     {
850       dbus_message_unref (msg);
851       _DBUS_SET_OOM (error);
852       return;
853     }
854
855   send_no_return_values (connection, msg, error);
856
857   dbus_message_unref (msg);
858 }
859
860 /** @} */