~awe/phablet-extras/ofono-lp1204683

« back to all changes in this revision

Viewing changes to gdbus/mainloop.c

  • Committer: Bazaar Package Importer
  • Author(s): Andres Salomon
  • Date: 2009-08-15 15:55:11 UTC
  • Revision ID: james.westby@ubuntu.com-20090815155511-frst06dijguhyfi4
Tags: upstream-0.3
ImportĀ upstreamĀ versionĀ 0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 *  D-Bus helper library
 
4
 *
 
5
 *  Copyright (C) 2004-2009  Marcel Holtmann <marcel@holtmann.org>
 
6
 *
 
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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
21
 *
 
22
 */
 
23
 
 
24
#ifdef HAVE_CONFIG_H
 
25
#include <config.h>
 
26
#endif
 
27
 
 
28
#include <stdint.h>
 
29
 
 
30
#include <glib.h>
 
31
#include <dbus/dbus.h>
 
32
 
 
33
#ifdef NEED_DBUS_WATCH_GET_UNIX_FD
 
34
#define dbus_watch_get_unix_fd dbus_watch_get_fd
 
35
#endif
 
36
 
 
37
#include "gdbus.h"
 
38
 
 
39
#define DISPATCH_TIMEOUT  0
 
40
 
 
41
#define info(fmt...)
 
42
#define error(fmt...)
 
43
#define debug(fmt...)
 
44
 
 
45
typedef struct {
 
46
        uint32_t id;
 
47
        DBusTimeout *timeout;
 
48
} timeout_handler_t;
 
49
 
 
50
struct watch_info {
 
51
        guint watch_id;
 
52
        GIOChannel *io;
 
53
        DBusConnection *conn;
 
54
};
 
55
 
 
56
struct server_info {
 
57
        guint watch_id;
 
58
        GIOChannel *io;
 
59
        DBusServer *server;
 
60
};
 
61
 
 
62
struct disconnect_data {
 
63
        GDBusWatchFunction disconnect_cb;
 
64
        void *user_data;
 
65
};
 
66
 
 
67
static DBusHandlerResult disconnect_filter(DBusConnection *conn,
 
68
                                                DBusMessage *msg, void *data)
 
69
{
 
70
        struct disconnect_data *dc_data = data;
 
71
 
 
72
        if (dbus_message_is_signal(msg,
 
73
                        DBUS_INTERFACE_LOCAL, "Disconnected") == TRUE) {
 
74
                error("Got disconnected from the system message bus");
 
75
                dc_data->disconnect_cb(conn, dc_data->user_data);
 
76
                dbus_connection_unref(conn);
 
77
        }
 
78
 
 
79
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
80
}
 
81
 
 
82
static gboolean message_dispatch_cb(void *data)
 
83
{
 
84
        DBusConnection *connection = data;
 
85
 
 
86
        dbus_connection_ref(connection);
 
87
 
 
88
        /* Dispatch messages */
 
89
        while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS);
 
90
 
 
91
        dbus_connection_unref(connection);
 
92
 
 
93
        return FALSE;
 
94
}
 
95
 
 
96
static gboolean watch_func(GIOChannel *chan, GIOCondition cond, gpointer data)
 
97
{
 
98
        DBusWatch *watch = data;
 
99
        struct watch_info *info = dbus_watch_get_data(watch);
 
100
        int flags = 0;
 
101
 
 
102
        if (cond & G_IO_IN)  flags |= DBUS_WATCH_READABLE;
 
103
        if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE;
 
104
        if (cond & G_IO_HUP) flags |= DBUS_WATCH_HANGUP;
 
105
        if (cond & G_IO_ERR) flags |= DBUS_WATCH_ERROR;
 
106
 
 
107
        dbus_watch_handle(watch, flags);
 
108
 
 
109
        if (dbus_connection_get_dispatch_status(info->conn) == DBUS_DISPATCH_DATA_REMAINS)
 
110
                g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, info->conn);
 
111
 
 
112
        return TRUE;
 
113
}
 
114
 
 
115
static dbus_bool_t add_watch(DBusWatch *watch, void *data)
 
116
{
 
117
        GIOCondition cond = G_IO_HUP | G_IO_ERR;
 
118
        DBusConnection *conn = data;
 
119
        struct watch_info *info;
 
120
        int fd, flags;
 
121
 
 
122
        if (!dbus_watch_get_enabled(watch))
 
123
                return TRUE;
 
124
 
 
125
        info = g_new(struct watch_info, 1);
 
126
 
 
127
        fd = dbus_watch_get_unix_fd(watch);
 
128
        info->io = g_io_channel_unix_new(fd);
 
129
        info->conn = dbus_connection_ref(conn);
 
130
 
 
131
        dbus_watch_set_data(watch, info, NULL);
 
132
 
 
133
        flags = dbus_watch_get_flags(watch);
 
134
 
 
135
        if (flags & DBUS_WATCH_READABLE) cond |= G_IO_IN;
 
136
        if (flags & DBUS_WATCH_WRITABLE) cond |= G_IO_OUT;
 
137
 
 
138
        info->watch_id = g_io_add_watch(info->io, cond, watch_func, watch);
 
139
 
 
140
        return TRUE;
 
141
}
 
142
 
 
143
static void remove_watch(DBusWatch *watch, void *data)
 
144
{
 
145
        struct watch_info *info = dbus_watch_get_data(watch);
 
146
 
 
147
        dbus_watch_set_data(watch, NULL, NULL);
 
148
 
 
149
        if (info) {
 
150
                g_source_remove(info->watch_id);
 
151
                g_io_channel_unref(info->io);
 
152
                dbus_connection_unref(info->conn);
 
153
                g_free(info);
 
154
        }
 
155
}
 
156
 
 
157
static void watch_toggled(DBusWatch *watch, void *data)
 
158
{
 
159
        /* Because we just exit on OOM, enable/disable is
 
160
         * no different from add/remove */
 
161
        if (dbus_watch_get_enabled(watch))
 
162
                add_watch(watch, data);
 
163
        else
 
164
                remove_watch(watch, data);
 
165
}
 
166
 
 
167
static gboolean timeout_handler_dispatch(gpointer data)
 
168
{
 
169
        timeout_handler_t *handler = data;
 
170
 
 
171
        /* if not enabled should not be polled by the main loop */
 
172
        if (dbus_timeout_get_enabled(handler->timeout) != TRUE)
 
173
                return FALSE;
 
174
 
 
175
        dbus_timeout_handle(handler->timeout);
 
176
 
 
177
        return FALSE;
 
178
}
 
179
 
 
180
static void timeout_handler_free(void *data)
 
181
{
 
182
        timeout_handler_t *handler = data;
 
183
        if (!handler)
 
184
                return;
 
185
 
 
186
        g_source_remove(handler->id);
 
187
        g_free(handler);
 
188
}
 
189
 
 
190
static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
 
191
{
 
192
        timeout_handler_t *handler;
 
193
 
 
194
        if (!dbus_timeout_get_enabled(timeout))
 
195
                return TRUE;
 
196
 
 
197
        handler = g_new0(timeout_handler_t, 1);
 
198
 
 
199
        handler->timeout = timeout;
 
200
        handler->id = g_timeout_add(dbus_timeout_get_interval(timeout),
 
201
                                        timeout_handler_dispatch, handler);
 
202
 
 
203
        dbus_timeout_set_data(timeout, handler, timeout_handler_free);
 
204
 
 
205
        return TRUE;
 
206
}
 
207
 
 
208
static void remove_timeout(DBusTimeout *timeout, void *data)
 
209
{
 
210
}
 
211
 
 
212
static void timeout_toggled(DBusTimeout *timeout, void *data)
 
213
{
 
214
        if (dbus_timeout_get_enabled(timeout))
 
215
                add_timeout(timeout, data);
 
216
        else
 
217
                remove_timeout(timeout, data);
 
218
}
 
219
 
 
220
static void dispatch_status_cb(DBusConnection *conn,
 
221
                                DBusDispatchStatus new_status, void *data)
 
222
{
 
223
        if (!dbus_connection_get_is_connected(conn))
 
224
                return;
 
225
 
 
226
        if (new_status == DBUS_DISPATCH_DATA_REMAINS)
 
227
                g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, data);
 
228
}
 
229
 
 
230
static void setup_dbus_with_main_loop(DBusConnection *conn)
 
231
{
 
232
        dbus_connection_set_watch_functions(conn, add_watch, remove_watch,
 
233
                                                watch_toggled, conn, NULL);
 
234
 
 
235
        dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout,
 
236
                                                timeout_toggled, conn, NULL);
 
237
 
 
238
        dbus_connection_set_dispatch_status_function(conn, dispatch_status_cb,
 
239
                                                                conn, NULL);
 
240
}
 
241
 
 
242
DBusConnection *g_dbus_setup_bus(DBusBusType type, const char *name,
 
243
                                                        DBusError *error)
 
244
{
 
245
        DBusConnection *conn;
 
246
 
 
247
        conn = dbus_bus_get(type, error);
 
248
 
 
249
        if (error != NULL) {
 
250
                if (dbus_error_is_set(error) == TRUE)
 
251
                        return NULL;
 
252
        }
 
253
 
 
254
        if (conn == NULL)
 
255
                return NULL;
 
256
 
 
257
        if (name != NULL) {
 
258
                if (dbus_bus_request_name(conn, name,
 
259
                                DBUS_NAME_FLAG_DO_NOT_QUEUE, error) !=
 
260
                                DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER ) {
 
261
                        dbus_connection_unref(conn);
 
262
                        return NULL;
 
263
                }
 
264
 
 
265
                if (error != NULL) {
 
266
                        if (dbus_error_is_set(error) == TRUE) {
 
267
                                dbus_connection_unref(conn);
 
268
                                return NULL;
 
269
                        }
 
270
                }
 
271
        }
 
272
 
 
273
        setup_dbus_with_main_loop(conn);
 
274
 
 
275
        return conn;
 
276
}
 
277
 
 
278
gboolean g_dbus_request_name(DBusConnection *connection, const char *name,
 
279
                                                        DBusError *error)
 
280
{
 
281
        return TRUE;
 
282
}
 
283
 
 
284
gboolean g_dbus_set_disconnect_function(DBusConnection *connection,
 
285
                                GDBusWatchFunction function,
 
286
                                void *user_data, DBusFreeFunction destroy)
 
287
{
 
288
        struct disconnect_data *dc_data;
 
289
 
 
290
        dc_data = g_new(struct disconnect_data, 1);
 
291
 
 
292
        dc_data->disconnect_cb = function;
 
293
        dc_data->user_data = user_data;
 
294
 
 
295
        dbus_connection_set_exit_on_disconnect(connection, FALSE);
 
296
 
 
297
        if (dbus_connection_add_filter(connection, disconnect_filter,
 
298
                                                dc_data, g_free) == FALSE) {
 
299
                error("Can't add D-Bus disconnect filter");
 
300
                g_free(dc_data);
 
301
                return FALSE;
 
302
        }
 
303
 
 
304
        return TRUE;
 
305
}