4a805731415aecede9a2a2a6a3ef4a6ac5080322
[platform/upstream/dbus.git] / bus / connection.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* connection.c  Client connections
3  *
4  * Copyright (C) 2003  Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 1.2
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 as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23 #include "connection.h"
24 #include "driver.h"
25 #include "loop.h"
26 #include "services.h"
27 #include <dbus/dbus-list.h>
28
29 static int connection_data_slot;
30 static DBusList *connections = NULL;
31
32 typedef struct
33 {
34   DBusList *services_owned;
35
36   char *name;
37 } BusConnectionData;
38
39 #define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot))
40
41 static void
42 connection_disconnect_handler (DBusConnection *connection,
43                                void           *data)
44 {
45   BusConnectionData *d;
46   BusService *service;
47
48   _dbus_warn ("Disconnected\n");
49
50   d = BUS_CONNECTION_DATA (connection);
51   _dbus_assert (d != NULL);  
52
53   /* Drop any service ownership */
54   while ((service = _dbus_list_get_last (&d->services_owned)))
55     bus_service_remove_owner (service, connection);
56
57   /* Tell bus driver that we want to get off */
58   bus_driver_remove_connection (connection);
59   
60   /* no more watching */
61   dbus_connection_set_watch_functions (connection,
62                                        NULL, NULL,
63                                        connection,
64                                        NULL);
65   
66   dbus_connection_set_data (connection,
67                             connection_data_slot,
68                             NULL, NULL);
69   
70   _dbus_list_remove (&connections, connection);    
71   dbus_connection_unref (connection);
72 }
73
74 static void
75 connection_watch_callback (DBusWatch     *watch,
76                            unsigned int   condition,
77                            void          *data)
78 {
79   DBusConnection *connection = data;
80
81   dbus_connection_handle_watch (connection, watch, condition);
82
83   while (dbus_connection_dispatch_message (connection));
84 }
85
86 static void
87 add_connection_watch (DBusWatch      *watch,
88                       DBusConnection *connection)
89 {
90   bus_loop_add_watch (watch, connection_watch_callback, connection,
91                       NULL);
92 }
93
94 static void
95 remove_connection_watch (DBusWatch      *watch,
96                          DBusConnection *connection)
97 {
98   bus_loop_remove_watch (watch, connection_watch_callback, connection);
99 }
100
101 static void
102 free_connection_data (void *data)
103 {
104   BusConnectionData *d = data;
105
106   /* services_owned should be NULL since we should be disconnected */
107   _dbus_assert (d->services_owned == NULL);
108
109   dbus_free (d->name);
110   
111   dbus_free (d);
112 }
113
114 dbus_bool_t
115 bus_connection_init (void)
116 {
117   connection_data_slot = dbus_connection_allocate_data_slot ();
118
119   if (connection_data_slot < 0)
120     return FALSE;
121
122   return TRUE;
123 }
124
125 dbus_bool_t
126 bus_connection_setup (DBusConnection *connection)
127 {
128   BusConnectionData *d;
129
130   d = dbus_new0 (BusConnectionData, 1);
131   
132   if (d == NULL)
133     return FALSE;
134   
135   if (!dbus_connection_set_data (connection,
136                                  connection_data_slot,
137                                  d, free_connection_data))
138     {
139       dbus_free (d);
140       return FALSE;
141     }
142   
143   if (!_dbus_list_append (&connections, connection))
144     {
145       /* this will free our data when connection gets finalized */
146       dbus_connection_disconnect (connection);
147       return FALSE;
148     }
149
150   dbus_connection_ref (connection);
151   
152   dbus_connection_set_watch_functions (connection,
153                                        (DBusAddWatchFunction) add_connection_watch,
154                                        (DBusRemoveWatchFunction) remove_connection_watch,
155                                        connection,
156                                        NULL);
157   
158   dbus_connection_set_disconnect_function (connection,
159                                            connection_disconnect_handler,
160                                            NULL, NULL);
161
162   if (!bus_driver_add_connection (connection))
163     return FALSE;
164   
165   return TRUE;
166 }
167
168 dbus_bool_t
169 bus_connection_add_owned_service (DBusConnection *connection,
170                                   BusService     *service)
171 {
172   BusConnectionData *d;
173
174   d = BUS_CONNECTION_DATA (connection);
175   _dbus_assert (d != NULL);
176
177   if (!_dbus_list_append (&d->services_owned,
178                           service))
179     return FALSE;
180
181   return TRUE;
182 }
183
184 void
185 bus_connection_remove_owned_service (DBusConnection *connection,
186                                      BusService     *service)
187 {
188   BusConnectionData *d;
189
190   d = BUS_CONNECTION_DATA (connection);
191   _dbus_assert (d != NULL);
192
193   _dbus_list_remove_last (&d->services_owned, service);
194 }
195
196 dbus_bool_t
197 bus_connection_set_name (DBusConnection   *connection,
198                          const DBusString *name)
199 {
200   const char *c_name;
201   BusConnectionData *d;
202   
203   d = BUS_CONNECTION_DATA (connection);
204   _dbus_assert (d != NULL);
205   _dbus_assert (d->name == NULL);
206
207   _dbus_string_get_const_data (name, &c_name);
208
209   d->name = _dbus_strdup (c_name);
210
211   if (d->name == NULL)
212     return FALSE;
213
214   return TRUE;
215 }
216
217 const char *
218 bus_connection_get_name (DBusConnection *connection)
219 {
220   BusConnectionData *d;
221   
222   d = BUS_CONNECTION_DATA (connection);
223   _dbus_assert (d != NULL);
224   
225   return d->name;
226 }