2003-01-14 Anders Carlsson <andersca@codefactory.se>
[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 "loop.h"
25 #include "services.h"
26 #include <dbus/dbus-list.h>
27
28 static int connection_data_slot;
29 static DBusList *connections = NULL;
30
31 typedef struct
32 {
33   DBusList *services_owned;
34
35 } BusConnectionData;
36
37 #define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot))
38
39 static void
40 connection_error_handler (DBusConnection *connection,
41                           DBusResultCode  error_code,
42                           void           *data)
43 {
44   BusConnectionData *d;
45   BusService *service;
46
47   _dbus_warn ("Error on connection: %s\n",
48               dbus_result_to_string (error_code));
49
50   d = BUS_CONNECTION_DATA (connection);
51   _dbus_assert (d != NULL);
52   
53   /* we don't want to be called again since we're dropping the connection */
54   dbus_connection_set_error_function (connection, NULL, NULL, NULL);
55
56   /* Drop any service ownership */
57   while ((service = _dbus_list_get_last (&d->services_owned)))
58     bus_service_remove_owner (service, 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
84 static void
85 add_connection_watch (DBusWatch      *watch,
86                       DBusConnection *connection)
87 {
88   bus_loop_add_watch (watch, connection_watch_callback, connection,
89                       NULL);
90 }
91
92 static void
93 remove_connection_watch (DBusWatch      *watch,
94                          DBusConnection *connection)
95 {
96   bus_loop_remove_watch (watch, connection_watch_callback, connection);
97 }
98
99 static void
100 free_connection_data (void *data)
101 {
102   BusConnectionData *d = data;
103
104   /* services_owned should be NULL since we should be disconnected */
105   _dbus_assert (d->services_owned == NULL);
106   
107   dbus_free (d);
108 }
109
110 dbus_bool_t
111 bus_connection_init (void)
112 {
113   connection_data_slot = dbus_connection_allocate_data_slot ();
114
115   if (connection_data_slot < 0)
116     return FALSE;
117
118   return TRUE;
119 }
120
121 dbus_bool_t
122 bus_connection_setup (DBusConnection *connection)
123 {
124   BusConnectionData *d;
125
126   d = dbus_new0 (BusConnectionData, 1);
127   
128   if (d == NULL)
129     return FALSE;
130   
131   if (!dbus_connection_set_data (connection,
132                                  connection_data_slot,
133                                  d, free_connection_data))
134     {
135       dbus_free (d);
136       return FALSE;
137     }
138   
139   if (!_dbus_list_append (&connections, connection))
140     {
141       /* this will free our data when connection gets finalized */
142       dbus_connection_disconnect (connection);
143       return FALSE;
144     }
145
146   dbus_connection_ref (connection);
147   
148   dbus_connection_set_watch_functions (connection,
149                                        (DBusAddWatchFunction) add_connection_watch,
150                                        (DBusRemoveWatchFunction) remove_connection_watch,
151                                        connection,
152                                        NULL);
153   
154   dbus_connection_set_error_function (connection,
155                                       connection_error_handler,
156                                       NULL, NULL);
157
158   return TRUE;
159 }
160
161 dbus_bool_t
162 bus_connection_add_owned_service (DBusConnection *connection,
163                                   BusService     *service)
164 {
165   BusConnectionData *d;
166
167   d = BUS_CONNECTION_DATA (connection);
168   _dbus_assert (d != NULL);
169
170   if (!_dbus_list_append (&d->services_owned,
171                           service))
172     return FALSE;
173
174   return TRUE;
175 }
176
177 void
178 bus_connection_remove_owned_service (DBusConnection *connection,
179                                      BusService     *service)
180 {
181   BusConnectionData *d;
182
183   d = BUS_CONNECTION_DATA (connection);
184   _dbus_assert (d != NULL);
185
186   _dbus_list_remove_last (&d->services_owned, service);
187 }