bus: Assign a serial number for messages from the driver
[platform/upstream/dbus.git] / bus / services.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* services.c  Service management
3  *
4  * Copyright (C) 2003  Red Hat, Inc.
5  * Copyright (C) 2003  CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 2.1
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24
25 #include <config.h>
26 #include <dbus/dbus-hash.h>
27 #include <dbus/dbus-list.h>
28 #include <dbus/dbus-mempool.h>
29 #include <dbus/dbus-marshal-validate.h>
30
31 #include "driver.h"
32 #include "services.h"
33 #include "connection.h"
34 #include "utils.h"
35 #include "activation.h"
36 #include "policy.h"
37 #include "bus.h"
38 #include "selinux.h"
39 #include "apparmor.h"
40
41 struct BusService
42 {
43   int refcount;
44
45   BusRegistry *registry;
46   char *name;
47   DBusList *owners;
48 };
49
50 struct BusOwner
51 {
52   int refcount;
53
54   BusService *service;
55   DBusConnection *conn;
56
57   unsigned int allow_replacement : 1;
58   unsigned int do_not_queue : 1;
59 };
60
61 struct BusRegistry
62 {
63   int refcount;
64
65   BusContext *context;
66   
67   DBusHashTable *service_hash;
68   DBusMemPool   *service_pool;
69   DBusMemPool   *owner_pool;
70
71   DBusHashTable *service_sid_table;
72 };
73
74 BusRegistry*
75 bus_registry_new (BusContext *context)
76 {
77   BusRegistry *registry;
78
79   _dbus_assert (context);
80   registry = dbus_new0 (BusRegistry, 1);
81   if (registry == NULL)
82     return NULL;
83
84   registry->refcount = 1;
85   registry->context = context;
86   
87   registry->service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
88                                                  NULL, NULL);
89   if (registry->service_hash == NULL)
90     goto failed;
91   
92   registry->service_pool = _dbus_mem_pool_new (sizeof (BusService),
93                                                TRUE);
94
95   if (registry->service_pool == NULL)
96     goto failed;
97
98   registry->owner_pool = _dbus_mem_pool_new (sizeof (BusOwner),
99                                              TRUE);
100
101   if (registry->owner_pool == NULL)
102     goto failed;
103
104   registry->service_sid_table = NULL;
105   
106   return registry;
107
108  failed:
109   bus_registry_unref (registry);
110   return NULL;
111 }
112
113 BusRegistry *
114 bus_registry_ref (BusRegistry *registry)
115 {
116   _dbus_assert (registry->refcount > 0);
117   registry->refcount += 1;
118
119   return registry;
120 }
121
122 void
123 bus_registry_unref  (BusRegistry *registry)
124 {
125   _dbus_assert (registry->refcount > 0);
126   registry->refcount -= 1;
127
128   if (registry->refcount == 0)
129     {
130       if (registry->service_hash)
131         _dbus_hash_table_unref (registry->service_hash);
132       if (registry->service_pool)
133         _dbus_mem_pool_free (registry->service_pool);
134       if (registry->owner_pool)
135         _dbus_mem_pool_free (registry->owner_pool);
136       if (registry->service_sid_table)
137         _dbus_hash_table_unref (registry->service_sid_table);
138       
139       dbus_free (registry);
140     }
141 }
142
143 BusService*
144 bus_registry_lookup (BusRegistry      *registry,
145                      const DBusString *service_name)
146 {
147   BusService *service;
148
149   service = _dbus_hash_table_lookup_string (registry->service_hash,
150                                             _dbus_string_get_const_data (service_name));
151
152   return service;
153 }
154
155 static DBusList *
156 _bus_service_find_owner_link (BusService *service,
157                               DBusConnection *connection)
158 {
159   DBusList *link;
160   
161   link = _dbus_list_get_first_link (&service->owners);
162
163   while (link != NULL)
164     {
165       BusOwner *bus_owner;
166
167       bus_owner = (BusOwner *) link->data;
168       if (bus_owner->conn == connection) 
169         break;
170
171       link = _dbus_list_get_next_link (&service->owners, link);
172     }
173
174   return link;
175 }
176
177 static void
178 bus_owner_set_flags (BusOwner *owner,
179                      dbus_uint32_t flags)
180 {
181    owner->allow_replacement = 
182         (flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT) != FALSE;
183
184    owner->do_not_queue =
185         (flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) != FALSE;
186 }
187
188 static BusOwner *
189 bus_owner_new (BusService *service, 
190                DBusConnection *conn, 
191                dbus_uint32_t flags)
192 {
193   BusOwner *result;
194
195   result = _dbus_mem_pool_alloc (service->registry->owner_pool);
196   if (result != NULL)
197     {
198       result->refcount = 1;
199       /* don't ref the connection because we don't want
200          to block the connection from going away.
201          transactions take care of reffing the connection
202          but we need to use refcounting on the owner
203          so that the owner does not get freed before
204          we can deref the connection in the transaction
205        */
206       result->conn = conn;
207       result->service = service;
208
209       if (!bus_connection_add_owned_service (conn, service))
210         {
211           _dbus_mem_pool_dealloc (service->registry->owner_pool, result);
212           return NULL;
213         }
214         
215       bus_owner_set_flags (result, flags);
216     }
217   return result;
218 }
219
220 static BusOwner *
221 bus_owner_ref (BusOwner *owner)
222 {
223   _dbus_assert (owner->refcount > 0);
224   owner->refcount += 1;
225
226   return owner;
227 }
228
229 static void
230 bus_owner_unref  (BusOwner *owner)
231 {
232   _dbus_assert (owner->refcount > 0);
233   owner->refcount -= 1;
234
235   if (owner->refcount == 0)
236     {
237       bus_connection_remove_owned_service (owner->conn, owner->service);
238       _dbus_mem_pool_dealloc (owner->service->registry->owner_pool, owner);
239     }
240 }
241
242 BusService*
243 bus_registry_ensure (BusRegistry               *registry,
244                      const DBusString          *service_name,
245                      DBusConnection            *owner_connection_if_created,
246                      dbus_uint32_t              flags,
247                      BusTransaction            *transaction,
248                      DBusError                 *error)
249 {
250   BusService *service;
251
252   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
253   
254   _dbus_assert (owner_connection_if_created != NULL);
255   _dbus_assert (transaction != NULL);
256
257   service = _dbus_hash_table_lookup_string (registry->service_hash,
258                                             _dbus_string_get_const_data (service_name));
259   if (service != NULL)
260     return service;
261   
262   service = _dbus_mem_pool_alloc (registry->service_pool);
263   if (service == NULL)
264     {
265       BUS_SET_OOM (error);
266       return NULL;
267     }
268
269   service->registry = registry;  
270   service->refcount = 1;
271
272   _dbus_verbose ("copying string %p '%s' to service->name\n",
273                  service_name, _dbus_string_get_const_data (service_name));
274   if (!_dbus_string_copy_data (service_name, &service->name))
275     {
276       _dbus_mem_pool_dealloc (registry->service_pool, service);
277       BUS_SET_OOM (error);
278       return NULL;
279     }
280   _dbus_verbose ("copied string %p '%s' to '%s'\n",
281                  service_name, _dbus_string_get_const_data (service_name),
282                  service->name);
283
284   if (!bus_driver_send_service_owner_changed (service->name, 
285                                               NULL,
286                                               bus_connection_get_name (owner_connection_if_created),
287                                               transaction, error))
288     {
289       bus_service_unref (service);
290       return NULL;
291     }
292
293   if (!bus_activation_service_created (bus_context_get_activation (registry->context),
294                                        service->name, transaction, error))
295     {
296       bus_service_unref (service);
297       return NULL;
298     }
299   
300   if (!bus_service_add_owner (service, owner_connection_if_created, flags,
301                                               transaction, error))
302     {
303       bus_service_unref (service);
304       return NULL;
305     }
306   
307   if (!_dbus_hash_table_insert_string (registry->service_hash,
308                                        service->name,
309                                        service))
310     {
311       /* The add_owner gets reverted on transaction cancel */
312       BUS_SET_OOM (error);
313       return NULL;
314     }
315   
316   return service;
317 }
318
319 void
320 bus_registry_foreach (BusRegistry               *registry,
321                       BusServiceForeachFunction  function,
322                       void                      *data)
323 {
324   DBusHashIter iter;
325   
326   _dbus_hash_iter_init (registry->service_hash, &iter);
327   while (_dbus_hash_iter_next (&iter))
328     {
329       BusService *service = _dbus_hash_iter_get_value (&iter);
330
331       (* function) (service, data);
332     }
333 }
334
335 dbus_bool_t
336 bus_registry_list_services (BusRegistry *registry,
337                             char      ***listp,
338                             int         *array_len)
339 {
340   int i, j, len;
341   char **retval;
342   DBusHashIter iter;
343    
344   len = _dbus_hash_table_get_n_entries (registry->service_hash);
345   retval = dbus_new (char *, len + 1);
346
347   if (retval == NULL)
348     return FALSE;
349
350   _dbus_hash_iter_init (registry->service_hash, &iter);
351   i = 0;
352   while (_dbus_hash_iter_next (&iter))
353     {
354       BusService *service = _dbus_hash_iter_get_value (&iter);
355
356       retval[i] = _dbus_strdup (service->name);
357       if (retval[i] == NULL)
358         goto error;
359
360       i++;
361     }
362
363   retval[i] = NULL;
364   
365   if (array_len)
366     *array_len = len;
367   
368   *listp = retval;
369   return TRUE;
370   
371  error:
372   for (j = 0; j < i; j++)
373     dbus_free (retval[j]);
374   dbus_free (retval);
375
376   return FALSE;
377 }
378
379 BusResult
380 bus_registry_acquire_service (BusRegistry      *registry,
381                               DBusConnection   *connection,
382                               DBusMessage      *message,
383                               const DBusString *service_name,
384                               dbus_uint32_t     flags,
385                               dbus_uint32_t    *result,
386                               BusTransaction   *transaction,
387                               DBusError        *error)
388 {
389   BusResult retval;
390   DBusConnection *old_owner_conn;
391   BusClientPolicy *policy;
392   BusService *service;
393   BusActivation  *activation;
394   BusSELinuxID *sid;
395   BusOwner *primary_owner;
396   int limit;
397  
398   retval = BUS_RESULT_FALSE;
399
400   if (!_dbus_validate_bus_name (service_name, 0,
401                                 _dbus_string_get_length (service_name)))
402     {
403       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
404                       "Requested bus name \"%s\" is not valid",
405                       _dbus_string_get_const_data (service_name));
406       
407       _dbus_verbose ("Attempt to acquire invalid service name\n");
408       
409       goto out;
410     }
411   
412   if (_dbus_string_get_byte (service_name, 0) == ':')
413     {
414       /* Not allowed; only base services can start with ':' */
415       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
416                       "Cannot acquire a service starting with ':' such as \"%s\"",
417                       _dbus_string_get_const_data (service_name));
418       
419       _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
420                      _dbus_string_get_const_data (service_name));
421       
422       goto out;
423     }
424
425   if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
426     {
427       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
428                       "Connection \"%s\" (%s) is not allowed to own the service \"%s\"because "
429                       "it is reserved for D-Bus' use only",
430                       bus_connection_is_active (connection) ?
431                       bus_connection_get_name (connection) :
432                       "(inactive)",
433                       bus_connection_get_loginfo (connection),
434                       DBUS_SERVICE_DBUS);
435       goto out;
436     }
437
438   policy = bus_connection_get_policy (connection);
439   _dbus_assert (policy != NULL);
440
441   /* Note that if sid is #NULL then the bus's own context gets used
442    * in bus_connection_selinux_allows_acquire_service()
443    */
444   sid = bus_selinux_id_table_lookup (registry->service_sid_table,
445                                      service_name);
446
447   if (!bus_selinux_allows_acquire_service (connection, sid,
448                                            _dbus_string_get_const_data (service_name), error))
449     {
450
451       if (dbus_error_is_set (error) &&
452           dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
453         {
454           goto out;
455         }
456
457       dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
458                       "Connection \"%s\" (%s) is not allowed to own the service \"%s\" due "
459                       "to SELinux policy",
460                       bus_connection_is_active (connection) ?
461                       bus_connection_get_name (connection) :
462                       "(inactive)",
463                       bus_connection_get_loginfo (connection),
464                       _dbus_string_get_const_data (service_name));
465       goto out;
466     }
467
468   if (!bus_apparmor_allows_acquire_service (connection,
469                                             bus_context_get_type (registry->context),
470                                             _dbus_string_get_const_data (service_name), error))
471     goto out;
472   
473   switch (bus_client_policy_check_can_own (policy, service_name, connection, message))
474     {
475       case BUS_RESULT_TRUE:
476         break;
477       case BUS_RESULT_FALSE:
478         dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
479                               "Connection \"%s\" (%s) is not allowed to own the service \"%s\" due "
480                               "to security policies in the configuration file",
481                               bus_connection_is_active (connection) ?
482                               bus_connection_get_name (connection) :
483                               "(inactive)",
484                               bus_connection_get_loginfo (connection),
485                               _dbus_string_get_const_data (service_name));
486
487         /* If we hit OOM while setting the error, this will syslog "out of memory"
488         * which is itself an indication that something is seriously wrong */
489         bus_context_log_literal (registry->context, DBUS_SYSTEM_LOG_SECURITY,
490                                 error->message);
491         goto out;
492       case BUS_RESULT_LATER:
493         retval = BUS_RESULT_LATER;
494         goto out;
495     }
496
497   limit = bus_context_get_max_services_per_connection (registry->context);
498
499   if (bus_connection_get_n_services_owned (connection) >= limit)
500     {
501       DBusError tmp_error;
502
503       dbus_error_init (&tmp_error);
504       dbus_set_error (&tmp_error, DBUS_ERROR_LIMITS_EXCEEDED,
505                       "Connection \"%s\" (%s) is not allowed to own more services "
506                       "(increase limits in configuration file if required)"
507                       "max_names_per_connection=%d)",
508                       bus_connection_is_active (connection) ?
509                       bus_connection_get_name (connection) :
510                       "(inactive)",
511                       bus_connection_get_loginfo (connection),
512                       limit);
513       bus_context_log (registry->context, DBUS_SYSTEM_LOG_WARNING,
514           "%s", tmp_error.message);
515       dbus_move_error (&tmp_error, error);
516       goto out;
517     }
518   
519   service = bus_registry_lookup (registry, service_name);
520
521   if (service != NULL)
522     {
523       primary_owner = bus_service_get_primary_owner (service);
524       if (primary_owner != NULL)
525         old_owner_conn = primary_owner->conn;
526       else
527         old_owner_conn = NULL;
528     }
529   else
530     old_owner_conn = NULL;
531       
532   if (service == NULL)
533     {
534       service = bus_registry_ensure (registry,
535                                      service_name, connection, flags,
536                                      transaction, error);
537       if (service == NULL)
538         goto out;
539     }
540
541   primary_owner = bus_service_get_primary_owner (service);
542   if (primary_owner == NULL)
543     goto out;
544
545   if (old_owner_conn == NULL)
546     {
547       _dbus_assert (primary_owner->conn == connection);
548
549       *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;      
550     }
551   else if (old_owner_conn == connection)
552     {
553       bus_owner_set_flags (primary_owner, flags);
554       *result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
555     }
556   else if (((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
557            !(bus_service_get_allow_replacement (service))) ||
558            ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
559            !(flags & DBUS_NAME_FLAG_REPLACE_EXISTING))) 
560     {
561       DBusList *link;
562       BusOwner *temp_owner;
563     /* Since we can't be queued if we are already in the queue
564        remove us */
565
566       link = _bus_service_find_owner_link (service, connection);
567       if (link != NULL)
568         {
569           _dbus_list_unlink (&service->owners, link);
570           temp_owner = (BusOwner *)link->data;
571           bus_owner_unref (temp_owner); 
572           _dbus_list_free_link (link);
573         }
574       
575       *result = DBUS_REQUEST_NAME_REPLY_EXISTS;
576     }
577   else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
578            (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
579             !(bus_service_get_allow_replacement (service))))
580     {
581       /* Queue the connection */
582       if (!bus_service_add_owner (service, connection, 
583                                   flags,
584                                   transaction, error))
585         goto out;
586       
587       *result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
588     }
589   else
590     {
591       /* Replace the current owner */
592
593       /* We enqueue the new owner and remove the first one because
594        * that will cause NameAcquired and NameLost messages to
595        * be sent.
596        */
597       
598       if (!bus_service_add_owner (service, connection,
599                                   flags,
600                                   transaction, error))
601         goto out;
602
603       if (primary_owner->do_not_queue)
604         {
605           if (!bus_service_remove_owner (service, old_owner_conn,
606                                          transaction, error))
607             goto out;
608         }
609       else
610         {
611           if (!bus_service_swap_owner (service, old_owner_conn,
612                                        transaction, error))
613             goto out;
614         }
615         
616     
617       _dbus_assert (connection == bus_service_get_primary_owner (service)->conn);
618       *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
619     }
620
621   activation = bus_context_get_activation (registry->context);
622   if (bus_activation_send_pending_auto_activation_messages (activation,
623                                                             service,
624                                                             transaction))
625     retval = BUS_RESULT_TRUE;
626   else
627     BUS_SET_OOM (error);
628   
629  out:
630   return retval;
631 }
632
633 dbus_bool_t
634 bus_registry_release_service (BusRegistry      *registry,
635                               DBusConnection   *connection,
636                               const DBusString *service_name,
637                               dbus_uint32_t    *result,
638                               BusTransaction   *transaction,
639                               DBusError        *error)
640 {
641   dbus_bool_t retval;
642   BusService *service;
643
644   retval = FALSE;
645
646   if (!_dbus_validate_bus_name (service_name, 0,
647                                 _dbus_string_get_length (service_name)))
648     {
649       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
650                       "Given bus name \"%s\" is not valid",
651                       _dbus_string_get_const_data (service_name));
652
653       _dbus_verbose ("Attempt to release invalid service name\n");
654
655       goto out;
656     }
657
658   if (_dbus_string_get_byte (service_name, 0) == ':')
659     {
660       /* Not allowed; the base service name cannot be created or released */
661       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
662                       "Cannot release a service starting with ':' such as \"%s\"",
663                       _dbus_string_get_const_data (service_name));
664
665       _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
666                      _dbus_string_get_const_data (service_name));
667
668       goto out;
669     }
670
671    if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
672     {
673       /* Not allowed; the base service name cannot be created or released */
674       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
675                       "Cannot release the %s service because it is owned by the bus",
676                      DBUS_SERVICE_DBUS);
677
678       _dbus_verbose ("Attempt to release service name \"%s\"",
679                      DBUS_SERVICE_DBUS);
680
681       goto out;
682     }
683
684   service = bus_registry_lookup (registry, service_name);
685
686   if (service == NULL)
687     {
688       *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
689     }
690   else if (!bus_service_has_owner (service, connection))
691     {
692       *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
693     }
694   else
695     {
696       if (!bus_service_remove_owner (service, connection,
697                                      transaction, error))
698         goto out;
699
700       _dbus_assert (!bus_service_has_owner (service, connection));
701       *result = DBUS_RELEASE_NAME_REPLY_RELEASED;
702     }
703
704   retval = TRUE;
705
706  out:
707   return retval;
708 }
709
710 dbus_bool_t
711 bus_registry_set_service_context_table (BusRegistry   *registry,
712                                         DBusHashTable *table)
713 {
714   DBusHashTable *new_table;
715   DBusHashIter iter;
716   
717   new_table = bus_selinux_id_table_new ();
718   if (!new_table)
719     return FALSE;
720
721   _dbus_hash_iter_init (table, &iter);
722   while (_dbus_hash_iter_next (&iter))
723     {
724       const char *service = _dbus_hash_iter_get_string_key (&iter);
725       const char *context = _dbus_hash_iter_get_value (&iter);
726
727       if (!bus_selinux_id_table_insert (new_table,
728                                         service,
729                                         context))
730         return FALSE;
731     }
732   
733   if (registry->service_sid_table)
734     _dbus_hash_table_unref (registry->service_sid_table);
735   registry->service_sid_table = new_table;
736   return TRUE;
737 }
738
739 static void
740 bus_service_unlink_owner (BusService      *service,
741                           BusOwner        *owner)
742 {
743   _dbus_list_remove_last (&service->owners, owner);
744   bus_owner_unref (owner);
745 }
746
747 static void
748 bus_service_unlink (BusService *service)
749 {
750   _dbus_assert (service->owners == NULL);
751
752   /* the service may not be in the hash, if
753    * the failure causing transaction cancel
754    * was in the right place, but that's OK
755    */
756   _dbus_hash_table_remove_string (service->registry->service_hash,
757                                   service->name);
758   
759   bus_service_unref (service);
760 }
761
762 static void
763 bus_service_relink (BusService           *service,
764                     DBusPreallocatedHash *preallocated)
765 {
766   _dbus_assert (service->owners == NULL);
767   _dbus_assert (preallocated != NULL);
768
769   _dbus_hash_table_insert_string_preallocated (service->registry->service_hash,
770                                                preallocated,
771                                                service->name,
772                                                service);
773   
774   bus_service_ref (service);
775 }
776
777 /**
778  * Data used to represent an ownership cancellation in
779  * a bus transaction.
780  */
781 typedef struct
782 {
783   BusOwner *owner;            /**< the owner */
784   BusService *service;        /**< service to cancel ownership of */
785 } OwnershipCancelData;
786
787 static void
788 cancel_ownership (void *data)
789 {
790   OwnershipCancelData *d = data;
791
792   /* We don't need to send messages notifying of these
793    * changes, since we're reverting something that was
794    * cancelled (effectively never really happened)
795    */
796   bus_service_unlink_owner (d->service, d->owner);
797   
798   if (d->service->owners == NULL)
799     bus_service_unlink (d->service);
800 }
801
802 static void
803 free_ownership_cancel_data (void *data)
804 {
805   OwnershipCancelData *d = data;
806
807   dbus_connection_unref (d->owner->conn);
808   bus_owner_unref (d->owner);
809   bus_service_unref (d->service);
810   
811   dbus_free (d);
812 }
813
814 static dbus_bool_t
815 add_cancel_ownership_to_transaction (BusTransaction *transaction,
816                                      BusService     *service,
817                                      BusOwner       *owner)
818 {
819   OwnershipCancelData *d;
820
821   d = dbus_new (OwnershipCancelData, 1);
822   if (d == NULL)
823     return FALSE;
824   
825   d->service = service;
826   d->owner = owner;
827
828   if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
829                                         free_ownership_cancel_data))
830     {
831       dbus_free (d);
832       return FALSE;
833     }
834
835   bus_service_ref (d->service);
836   bus_owner_ref (owner);
837   dbus_connection_ref (d->owner->conn);
838  
839   return TRUE;
840 }
841
842 /* this function is self-cancelling if you cancel the transaction */
843 dbus_bool_t
844 bus_service_add_owner (BusService     *service,
845                        DBusConnection *connection,
846                        dbus_uint32_t  flags,
847                        BusTransaction *transaction,
848                        DBusError      *error)
849 {
850   BusOwner *bus_owner;
851   DBusList *bus_owner_link;
852   
853   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
854   
855  /* Send service acquired message first, OOM will result
856   * in cancelling the transaction
857   */
858   if (service->owners == NULL)
859     {
860       if (!bus_driver_send_service_acquired (connection, service->name, transaction, error))
861         return FALSE;
862     }
863   
864   bus_owner_link = _bus_service_find_owner_link (service, connection);
865   
866   if (bus_owner_link == NULL)
867     {
868       bus_owner = bus_owner_new (service, connection, flags);
869       if (bus_owner == NULL)
870         {
871           BUS_SET_OOM (error);
872           return FALSE;
873         }
874
875       bus_owner_set_flags (bus_owner, flags);
876       if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL)
877         {
878           if (!_dbus_list_append (&service->owners,
879                                   bus_owner))
880             {
881               bus_owner_unref (bus_owner);
882               BUS_SET_OOM (error);
883               return FALSE;
884             }
885         }
886       else
887         {
888           if (!_dbus_list_insert_after (&service->owners,
889                                          _dbus_list_get_first_link (&service->owners),
890                                          bus_owner))
891             {
892               bus_owner_unref (bus_owner);
893               BUS_SET_OOM (error);
894               return FALSE;
895             }
896         }      
897     } 
898   else 
899     {
900       /* Update the link since we are already in the queue
901        * No need for operations that can produce OOM
902        */
903
904       bus_owner = (BusOwner *) bus_owner_link->data;
905       if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
906         {
907           DBusList *link;
908           _dbus_list_unlink (&service->owners, bus_owner_link);
909           link = _dbus_list_get_first_link (&service->owners);
910           _dbus_assert (link != NULL);
911           
912           _dbus_list_insert_after_link (&service->owners, link, bus_owner_link);
913         }
914       
915       bus_owner_set_flags (bus_owner, flags);
916       return TRUE;
917     }
918
919   if (!add_cancel_ownership_to_transaction (transaction,
920                                             service,
921                                             bus_owner))
922     {
923       bus_service_unlink_owner (service, bus_owner);
924       BUS_SET_OOM (error);
925       return FALSE;
926     }
927
928   return TRUE;
929 }
930
931 typedef struct
932 {
933   BusOwner       *owner;
934   BusService     *service;
935   BusOwner       *before_owner; /* restore to position before this connection in owners list */
936   DBusList       *owner_link;
937   DBusList       *service_link;
938   DBusPreallocatedHash *hash_entry;
939 } OwnershipRestoreData;
940
941 static void
942 restore_ownership (void *data)
943 {
944   OwnershipRestoreData *d = data;
945   DBusList *link;
946
947   _dbus_assert (d->service_link != NULL);
948   _dbus_assert (d->owner_link != NULL);
949   
950   if (d->service->owners == NULL)
951     {
952       _dbus_assert (d->hash_entry != NULL);
953       bus_service_relink (d->service, d->hash_entry);
954     }
955   else
956     {
957       _dbus_assert (d->hash_entry == NULL);
958     }
959   
960   /* We don't need to send messages notifying of these
961    * changes, since we're reverting something that was
962    * cancelled (effectively never really happened)
963    */
964   link = _dbus_list_get_first_link (&d->service->owners);
965   while (link != NULL)
966     {
967       if (link->data == d->before_owner)
968         break;
969
970       link = _dbus_list_get_next_link (&d->service->owners, link);
971     }
972   
973   _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link);
974
975   /* Note that removing then restoring this changes the order in which
976    * ServiceDeleted messages are sent on destruction of the
977    * connection.  This should be OK as the only guarantee there is
978    * that the base service is destroyed last, and we never even
979    * tentatively remove the base service.
980    */
981   bus_connection_add_owned_service_link (d->owner->conn, d->service_link);
982   
983   d->hash_entry = NULL;
984   d->service_link = NULL;
985   d->owner_link = NULL;
986 }
987
988 static void
989 free_ownership_restore_data (void *data)
990 {
991   OwnershipRestoreData *d = data;
992
993   if (d->service_link)
994     _dbus_list_free_link (d->service_link);
995   if (d->owner_link)
996     _dbus_list_free_link (d->owner_link);
997   if (d->hash_entry)
998     _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
999                                               d->hash_entry);
1000
1001   dbus_connection_unref (d->owner->conn);
1002   bus_owner_unref (d->owner);
1003   bus_service_unref (d->service);
1004   
1005   dbus_free (d);
1006 }
1007
1008 static dbus_bool_t
1009 add_restore_ownership_to_transaction (BusTransaction *transaction,
1010                                       BusService     *service,
1011                                       BusOwner       *owner)
1012 {
1013   OwnershipRestoreData *d;
1014   DBusList *link;
1015
1016   d = dbus_new (OwnershipRestoreData, 1);
1017   if (d == NULL)
1018     return FALSE;
1019   
1020   d->service = service;
1021   d->owner = owner;
1022   d->service_link = _dbus_list_alloc_link (service);
1023   d->owner_link = _dbus_list_alloc_link (owner);
1024   d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
1025   
1026   bus_service_ref (d->service);
1027   bus_owner_ref (d->owner);
1028   dbus_connection_ref (d->owner->conn);
1029
1030   d->before_owner = NULL;
1031   link = _dbus_list_get_first_link (&service->owners);
1032   while (link != NULL)
1033     {
1034       if (link->data == owner)
1035         {
1036           link = _dbus_list_get_next_link (&service->owners, link);
1037
1038           if (link)
1039             d->before_owner = link->data;
1040
1041           break;
1042         }
1043       
1044       link = _dbus_list_get_next_link (&service->owners, link);
1045     }
1046   
1047   if (d->service_link == NULL ||
1048       d->owner_link == NULL ||
1049       d->hash_entry == NULL ||
1050       !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
1051                                         free_ownership_restore_data))
1052     {
1053       free_ownership_restore_data (d);
1054       return FALSE;
1055     }
1056   
1057   return TRUE;
1058 }
1059
1060 dbus_bool_t
1061 bus_service_swap_owner (BusService     *service,
1062                         DBusConnection *connection,
1063                         BusTransaction *transaction,
1064                         DBusError      *error)
1065 {
1066   DBusList *swap_link;
1067   BusOwner *primary_owner;
1068
1069   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1070
1071   /* We send out notifications before we do any work we
1072    * might have to undo if the notification-sending failed
1073    */
1074   
1075   /* Send service lost message */
1076   primary_owner = bus_service_get_primary_owner (service);
1077   if (primary_owner == NULL || primary_owner->conn != connection)
1078     _dbus_assert_not_reached ("Tried to swap a non primary owner");
1079
1080     
1081   if (!bus_driver_send_service_lost (connection, service->name,
1082                                      transaction, error))
1083     return FALSE;
1084
1085   if (service->owners == NULL)
1086     {
1087       _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners");
1088     }
1089   else if (_dbus_list_length_is_one (&service->owners))
1090     {
1091       _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue");
1092     }
1093   else
1094     {
1095       DBusList *link;
1096       BusOwner *new_owner;
1097       DBusConnection *new_owner_conn;
1098       link = _dbus_list_get_first_link (&service->owners);
1099       _dbus_assert (link != NULL);
1100       link = _dbus_list_get_next_link (&service->owners, link);
1101       _dbus_assert (link != NULL);
1102
1103       new_owner = (BusOwner *)link->data;
1104       new_owner_conn = new_owner->conn;
1105
1106       if (!bus_driver_send_service_owner_changed (service->name,
1107                                                   bus_connection_get_name (connection),
1108                                                   bus_connection_get_name (new_owner_conn),
1109                                                   transaction, error))
1110         return FALSE;
1111
1112       /* This will be our new owner */
1113       if (!bus_driver_send_service_acquired (new_owner_conn,
1114                                              service->name,
1115                                              transaction,
1116                                              error))
1117         return FALSE;
1118     }
1119
1120   if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1121     {
1122       BUS_SET_OOM (error);
1123       return FALSE;
1124     }
1125
1126   /* unlink the primary and make it the second link */
1127   swap_link = _dbus_list_get_first_link (&service->owners);
1128   _dbus_list_unlink (&service->owners, swap_link);
1129
1130   _dbus_list_insert_after_link (&service->owners,
1131                                 _dbus_list_get_first_link (&service->owners),
1132                                 swap_link);
1133
1134   return TRUE;
1135 }
1136
1137 /* this function is self-cancelling if you cancel the transaction */
1138 dbus_bool_t
1139 bus_service_remove_owner (BusService     *service,
1140                           DBusConnection *connection,
1141                           BusTransaction *transaction,
1142                           DBusError      *error)
1143 {
1144   BusOwner *primary_owner;
1145   
1146   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1147   
1148   /* We send out notifications before we do any work we
1149    * might have to undo if the notification-sending failed
1150    */
1151   
1152   /* Send service lost message */
1153   primary_owner = bus_service_get_primary_owner (service);
1154   if (primary_owner != NULL && primary_owner->conn == connection)
1155     {
1156       if (!bus_driver_send_service_lost (connection, service->name,
1157                                          transaction, error))
1158         return FALSE;
1159     }
1160   else
1161     {
1162       /* if we are not the primary owner then just remove us from the queue */
1163       DBusList *link;
1164       BusOwner *temp_owner;
1165
1166       link = _bus_service_find_owner_link (service, connection);
1167       _dbus_list_unlink (&service->owners, link);
1168       temp_owner = (BusOwner *)link->data;
1169       bus_owner_unref (temp_owner); 
1170       _dbus_list_free_link (link);
1171
1172       return TRUE; 
1173     }
1174
1175   if (service->owners == NULL)
1176     {
1177       _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
1178     }
1179   else if (_dbus_list_length_is_one (&service->owners))
1180     {
1181       if (!bus_driver_send_service_owner_changed (service->name,
1182                                                   bus_connection_get_name (connection),
1183                                                   NULL,
1184                                                   transaction, error))
1185         return FALSE;
1186     }
1187   else
1188     {
1189       DBusList *link;
1190       BusOwner *new_owner;
1191       DBusConnection *new_owner_conn;
1192       link = _dbus_list_get_first_link (&service->owners);
1193       _dbus_assert (link != NULL);
1194       link = _dbus_list_get_next_link (&service->owners, link);
1195       _dbus_assert (link != NULL);
1196
1197       new_owner = (BusOwner *)link->data;
1198       new_owner_conn = new_owner->conn;
1199
1200       if (!bus_driver_send_service_owner_changed (service->name,
1201                                                   bus_connection_get_name (connection),
1202                                                   bus_connection_get_name (new_owner_conn),
1203                                                   transaction, error))
1204         return FALSE;
1205
1206       /* This will be our new owner */
1207       if (!bus_driver_send_service_acquired (new_owner_conn,
1208                                              service->name,
1209                                              transaction,
1210                                              error))
1211         return FALSE;
1212     }
1213
1214   if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1215     {
1216       BUS_SET_OOM (error);
1217       return FALSE;
1218     }
1219  
1220   bus_service_unlink_owner (service, primary_owner);
1221
1222   if (service->owners == NULL)
1223     bus_service_unlink (service);
1224
1225   return TRUE;
1226 }
1227
1228 BusService *
1229 bus_service_ref (BusService *service)
1230 {
1231   _dbus_assert (service->refcount > 0);
1232   
1233   service->refcount += 1;
1234
1235   return service;
1236 }
1237
1238 void
1239 bus_service_unref (BusService *service)
1240 {
1241   _dbus_assert (service->refcount > 0);
1242   
1243   service->refcount -= 1;
1244
1245   if (service->refcount == 0)
1246     {
1247       _dbus_assert (service->owners == NULL);
1248       
1249       dbus_free (service->name);
1250       _dbus_mem_pool_dealloc (service->registry->service_pool, service);
1251     }
1252 }
1253
1254 DBusConnection *
1255 bus_service_get_primary_owners_connection (BusService *service)
1256 {
1257   BusOwner *owner;
1258
1259   owner = bus_service_get_primary_owner (service);
1260
1261   if (owner != NULL)
1262     return owner->conn;
1263   else
1264     return NULL;
1265 }
1266
1267 BusOwner*
1268 bus_service_get_primary_owner (BusService *service)
1269 {
1270   return _dbus_list_get_first (&service->owners);
1271 }
1272
1273 const char*
1274 bus_service_get_name (BusService *service)
1275 {
1276   return service->name;
1277 }
1278
1279 dbus_bool_t
1280 bus_service_get_allow_replacement (BusService *service)
1281 {
1282   BusOwner *owner;
1283   DBusList *link;
1284  
1285   _dbus_assert (service->owners != NULL);
1286
1287   link = _dbus_list_get_first_link (&service->owners);
1288   owner = (BusOwner *) link->data;
1289
1290   return owner->allow_replacement;
1291 }
1292
1293 dbus_bool_t
1294 bus_service_has_owner (BusService     *service,
1295                        DBusConnection *connection)
1296 {
1297   DBusList *link;
1298
1299   link = _bus_service_find_owner_link (service, connection);
1300  
1301   if (link == NULL)
1302     return FALSE;
1303   else
1304     return TRUE;
1305 }
1306
1307 dbus_bool_t 
1308 bus_service_list_queued_owners (BusService *service,
1309                                 DBusList  **return_list,
1310                                 DBusError  *error)
1311 {
1312   DBusList *link;
1313
1314   _dbus_assert (*return_list == NULL);
1315
1316   link = _dbus_list_get_first_link (&service->owners);
1317   _dbus_assert (link != NULL);
1318   
1319   while (link != NULL)
1320     {
1321       BusOwner *owner;
1322       const char *uname;
1323
1324       owner = (BusOwner *) link->data;
1325       uname = bus_connection_get_name (owner->conn);
1326
1327       if (!_dbus_list_append (return_list, (char *)uname))
1328         goto oom;
1329
1330       link = _dbus_list_get_next_link (&service->owners, link);
1331     }
1332   
1333   return TRUE;
1334   
1335  oom:
1336   _dbus_list_clear (return_list);
1337   BUS_SET_OOM (error);
1338   return FALSE;
1339 }