~ubuntu-branches/ubuntu/trusty/obexd/trusty-proposed

« back to all changes in this revision

Viewing changes to gdbus/mainloop.c

  • Committer: Bazaar Package Importer
  • Author(s): Baptiste Mille-Mathias
  • Date: 2010-03-15 20:43:06 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100315204306-0jq3qj7q1jiybpxr
Tags: 0.22-0ubuntu1
* New upstream release (LP: #539914):
  - Fix file corruption during PUT operation. (LP: #421684]
  - Fix the response of PUT requests for PBAP.
  - Fix blocking while waiting capability script to exit.
  - Fix compilation issues with driver and plugin options.
  - Fix service driver selection when WHO header is informed.
  - Fix issue with PC-Suite WHO header.
  - Fix issue when mime type exists but is unknown.
  - Fix issue when opening file fails during SendFiles.
  - Fix error code response when there is no default vCard.
  - Fix a memory leak when opening a folder for listing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 *
3
3
 *  D-Bus helper library
4
4
 *
5
 
 *  Copyright (C) 2004-2009  Marcel Holtmann <marcel@holtmann.org>
 
5
 *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
6
6
 *
7
7
 *
8
8
 *  This program is free software; you can redistribute it and/or modify
25
25
#include <config.h>
26
26
#endif
27
27
 
28
 
#include <stdint.h>
29
 
 
30
28
#include <glib.h>
31
29
#include <dbus/dbus.h>
32
30
 
42
40
#define error(fmt...)
43
41
#define debug(fmt...)
44
42
 
45
 
typedef struct {
46
 
        uint32_t id;
 
43
struct timeout_handler {
 
44
        guint id;
47
45
        DBusTimeout *timeout;
48
 
} timeout_handler_t;
 
46
};
49
47
 
50
48
struct watch_info {
51
 
        guint watch_id;
52
 
        GIOChannel *io;
 
49
        guint id;
 
50
        DBusWatch *watch;
53
51
        DBusConnection *conn;
54
52
};
55
53
 
56
 
struct server_info {
57
 
        guint watch_id;
58
 
        GIOChannel *io;
59
 
        DBusServer *server;
60
 
};
61
 
 
62
54
struct disconnect_data {
63
 
        GDBusWatchFunction disconnect_cb;
 
55
        GDBusWatchFunction function;
64
56
        void *user_data;
65
57
};
66
58
 
67
 
static DBusHandlerResult disconnect_filter(DBusConnection *conn,
 
59
static gboolean disconnected_signal(DBusConnection *conn,
68
60
                                                DBusMessage *msg, void *data)
69
61
{
70
62
        struct disconnect_data *dc_data = data;
71
63
 
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;
 
64
        error("Got disconnected from the system message bus");
 
65
 
 
66
        dc_data->function(conn, dc_data->user_data);
 
67
 
 
68
        dbus_connection_unref(conn);
 
69
 
 
70
        return TRUE;
80
71
}
81
72
 
82
 
static gboolean message_dispatch_cb(void *data)
 
73
static gboolean message_dispatch(void *data)
83
74
{
84
 
        DBusConnection *connection = data;
 
75
        DBusConnection *conn = data;
85
76
 
86
 
        dbus_connection_ref(connection);
 
77
        dbus_connection_ref(conn);
87
78
 
88
79
        /* Dispatch messages */
89
 
        while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS);
 
80
        while (dbus_connection_dispatch(conn) == DBUS_DISPATCH_DATA_REMAINS);
90
81
 
91
 
        dbus_connection_unref(connection);
 
82
        dbus_connection_unref(conn);
92
83
 
93
84
        return FALSE;
94
85
}
95
86
 
 
87
static inline void queue_dispatch(DBusConnection *conn,
 
88
                                                DBusDispatchStatus status)
 
89
{
 
90
        if (status == DBUS_DISPATCH_DATA_REMAINS)
 
91
                g_timeout_add(DISPATCH_TIMEOUT, message_dispatch, conn);
 
92
}
 
93
 
96
94
static gboolean watch_func(GIOChannel *chan, GIOCondition cond, gpointer data)
97
95
{
98
 
        DBusWatch *watch = data;
99
 
        struct watch_info *info = dbus_watch_get_data(watch);
100
 
        int flags = 0;
 
96
        struct watch_info *info = data;
 
97
        unsigned int flags = 0;
 
98
 
 
99
        dbus_connection_ref(info->conn);
101
100
 
102
101
        if (cond & G_IO_IN)  flags |= DBUS_WATCH_READABLE;
103
102
        if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE;
104
103
        if (cond & G_IO_HUP) flags |= DBUS_WATCH_HANGUP;
105
104
        if (cond & G_IO_ERR) flags |= DBUS_WATCH_ERROR;
106
105
 
107
 
        dbus_watch_handle(watch, flags);
 
106
        dbus_watch_handle(info->watch, flags);
108
107
 
109
 
        if (dbus_connection_get_dispatch_status(info->conn) == DBUS_DISPATCH_DATA_REMAINS)
110
 
                g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, info->conn);
 
108
        dbus_connection_unref(info->conn);
111
109
 
112
110
        return TRUE;
113
111
}
114
112
 
 
113
static void watch_info_free(void *data)
 
114
{
 
115
        struct watch_info *info = data;
 
116
 
 
117
        if (info->id > 0) {
 
118
                g_source_remove(info->id);
 
119
                info->id = 0;
 
120
        }
 
121
 
 
122
        dbus_connection_unref(info->conn);
 
123
 
 
124
        g_free(info);
 
125
}
 
126
 
115
127
static dbus_bool_t add_watch(DBusWatch *watch, void *data)
116
128
{
 
129
        DBusConnection *conn = data;
117
130
        GIOCondition cond = G_IO_HUP | G_IO_ERR;
118
 
        DBusConnection *conn = data;
 
131
        GIOChannel *chan;
119
132
        struct watch_info *info;
120
 
        int fd, flags;
 
133
        unsigned int flags;
 
134
        int fd;
121
135
 
122
136
        if (!dbus_watch_get_enabled(watch))
123
137
                return TRUE;
124
138
 
125
 
        info = g_new(struct watch_info, 1);
 
139
        info = g_new0(struct watch_info, 1);
126
140
 
127
141
        fd = dbus_watch_get_unix_fd(watch);
128
 
        info->io = g_io_channel_unix_new(fd);
 
142
        chan = g_io_channel_unix_new(fd);
 
143
 
 
144
        info->watch = watch;
129
145
        info->conn = dbus_connection_ref(conn);
130
146
 
131
 
        dbus_watch_set_data(watch, info, NULL);
 
147
        dbus_watch_set_data(watch, info, watch_info_free);
132
148
 
133
149
        flags = dbus_watch_get_flags(watch);
134
150
 
135
151
        if (flags & DBUS_WATCH_READABLE) cond |= G_IO_IN;
136
152
        if (flags & DBUS_WATCH_WRITABLE) cond |= G_IO_OUT;
137
153
 
138
 
        info->watch_id = g_io_add_watch(info->io, cond, watch_func, watch);
 
154
        info->id = g_io_add_watch(chan, cond, watch_func, info);
 
155
 
 
156
        g_io_channel_unref(chan);
139
157
 
140
158
        return TRUE;
141
159
}
142
160
 
143
161
static void remove_watch(DBusWatch *watch, void *data)
144
162
{
145
 
        struct watch_info *info = dbus_watch_get_data(watch);
 
163
        if (dbus_watch_get_enabled(watch))
 
164
                return;
146
165
 
 
166
        /* will trigger watch_info_free() */
147
167
        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
168
}
156
169
 
157
170
static void watch_toggled(DBusWatch *watch, void *data)
166
179
 
167
180
static gboolean timeout_handler_dispatch(gpointer data)
168
181
{
169
 
        timeout_handler_t *handler = data;
 
182
        struct timeout_handler *handler = data;
 
183
 
 
184
        handler->id = 0;
170
185
 
171
186
        /* if not enabled should not be polled by the main loop */
172
 
        if (dbus_timeout_get_enabled(handler->timeout) != TRUE)
 
187
        if (!dbus_timeout_get_enabled(handler->timeout))
173
188
                return FALSE;
174
189
 
175
190
        dbus_timeout_handle(handler->timeout);
179
194
 
180
195
static void timeout_handler_free(void *data)
181
196
{
182
 
        timeout_handler_t *handler = data;
183
 
        if (!handler)
184
 
                return;
 
197
        struct timeout_handler *handler = data;
185
198
 
186
199
        if (handler->id > 0) {
187
200
                g_source_remove(handler->id);
193
206
 
194
207
static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
195
208
{
196
 
        timeout_handler_t *handler;
 
209
        int interval = dbus_timeout_get_interval(timeout);
 
210
        struct timeout_handler *handler;
197
211
 
198
212
        if (!dbus_timeout_get_enabled(timeout))
199
213
                return TRUE;
200
214
 
201
 
        handler = g_new0(timeout_handler_t, 1);
 
215
        handler = g_new0(struct timeout_handler, 1);
202
216
 
203
217
        handler->timeout = timeout;
204
 
        handler->id = g_timeout_add(dbus_timeout_get_interval(timeout),
205
 
                                        timeout_handler_dispatch, handler);
206
218
 
207
219
        dbus_timeout_set_data(timeout, handler, timeout_handler_free);
208
220
 
 
221
        handler->id = g_timeout_add(interval, timeout_handler_dispatch,
 
222
                                                                handler);
 
223
 
209
224
        return TRUE;
210
225
}
211
226
 
212
227
static void remove_timeout(DBusTimeout *timeout, void *data)
213
228
{
214
 
        timeout_handler_t *handler;
215
 
 
216
 
        handler = dbus_timeout_get_data(timeout);
217
 
 
218
 
        if (!handler)
219
 
                return;
220
 
 
221
 
        if (handler->id > 0) {
222
 
                g_source_remove(handler->id);
223
 
                handler->id = 0;
224
 
        }
 
229
        if (dbus_timeout_get_enabled(timeout))
 
230
                return;
 
231
 
 
232
        /* will trigger timeout_handler_free() */
 
233
        dbus_timeout_set_data(timeout, NULL, NULL);
225
234
}
226
235
 
227
236
static void timeout_toggled(DBusTimeout *timeout, void *data)
232
241
                remove_timeout(timeout, data);
233
242
}
234
243
 
235
 
static void dispatch_status_cb(DBusConnection *conn,
236
 
                                DBusDispatchStatus new_status, void *data)
 
244
static void dispatch_status(DBusConnection *conn,
 
245
                                        DBusDispatchStatus status, void *data)
237
246
{
238
247
        if (!dbus_connection_get_is_connected(conn))
239
248
                return;
240
249
 
241
 
        if (new_status == DBUS_DISPATCH_DATA_REMAINS)
242
 
                g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, data);
 
250
        queue_dispatch(conn, status);
243
251
}
244
252
 
245
 
static void setup_dbus_with_main_loop(DBusConnection *conn)
 
253
static inline void setup_dbus_with_main_loop(DBusConnection *conn)
246
254
{
247
255
        dbus_connection_set_watch_functions(conn, add_watch, remove_watch,
248
256
                                                watch_toggled, conn, NULL);
249
257
 
250
258
        dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout,
251
 
                                                timeout_toggled, conn, NULL);
 
259
                                                timeout_toggled, NULL, NULL);
252
260
 
253
 
        dbus_connection_set_dispatch_status_function(conn, dispatch_status_cb,
254
 
                                                                conn, NULL);
 
261
        dbus_connection_set_dispatch_status_function(conn, dispatch_status,
 
262
                                                                NULL, NULL);
255
263
}
256
264
 
257
 
DBusConnection *g_dbus_setup_bus(DBusBusType type, const char *name,
258
 
                                                        DBusError *error)
 
265
static gboolean setup_bus(DBusConnection *conn, const char *name,
 
266
                                                DBusError *error)
259
267
{
260
 
        DBusConnection *conn;
261
 
 
262
 
        conn = dbus_bus_get(type, error);
263
 
 
264
 
        if (error != NULL) {
265
 
                if (dbus_error_is_set(error) == TRUE)
266
 
                        return NULL;
267
 
        }
268
 
 
269
 
        if (conn == NULL)
270
 
                return NULL;
 
268
        gboolean result;
 
269
        DBusDispatchStatus status;
271
270
 
272
271
        if (name != NULL) {
273
 
                if (dbus_bus_request_name(conn, name,
274
 
                                DBUS_NAME_FLAG_DO_NOT_QUEUE, error) !=
275
 
                                DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER ) {
276
 
                        dbus_connection_unref(conn);
277
 
                        return NULL;
278
 
                }
 
272
                result = g_dbus_request_name(conn, name, error);
279
273
 
280
274
                if (error != NULL) {
281
 
                        if (dbus_error_is_set(error) == TRUE) {
282
 
                                dbus_connection_unref(conn);
283
 
                                return NULL;
284
 
                        }
 
275
                        if (dbus_error_is_set(error) == TRUE)
 
276
                                return FALSE;
285
277
                }
 
278
 
 
279
                if (result == FALSE)
 
280
                        return FALSE;
286
281
        }
287
282
 
288
283
        setup_dbus_with_main_loop(conn);
289
284
 
290
 
        if (dbus_connection_get_dispatch_status(conn) == DBUS_DISPATCH_DATA_REMAINS)
291
 
                g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, conn);
 
285
        status = dbus_connection_get_dispatch_status(conn);
 
286
        queue_dispatch(conn, status);
 
287
 
 
288
        return TRUE;
 
289
}
 
290
 
 
291
DBusConnection *g_dbus_setup_bus(DBusBusType type, const char *name,
 
292
                                                        DBusError *error)
 
293
{
 
294
        DBusConnection *conn;
 
295
 
 
296
        conn = dbus_bus_get(type, error);
 
297
 
 
298
        if (error != NULL) {
 
299
                if (dbus_error_is_set(error) == TRUE)
 
300
                        return NULL;
 
301
        }
 
302
 
 
303
        if (conn == NULL)
 
304
                return NULL;
 
305
 
 
306
        if (setup_bus(conn, name, error) == FALSE) {
 
307
                dbus_connection_unref(conn);
 
308
                return NULL;
 
309
        }
 
310
 
 
311
        return conn;
 
312
}
 
313
 
 
314
DBusConnection *g_dbus_setup_private(DBusBusType type, const char *name,
 
315
                                                        DBusError *error)
 
316
{
 
317
        DBusConnection *conn;
 
318
 
 
319
        conn = dbus_bus_get_private(type, error);
 
320
 
 
321
        if (error != NULL) {
 
322
                if (dbus_error_is_set(error) == TRUE)
 
323
                        return NULL;
 
324
        }
 
325
 
 
326
        if (conn == NULL)
 
327
                return NULL;
 
328
 
 
329
        if (setup_bus(conn, name, error) == FALSE) {
 
330
                dbus_connection_unref(conn);
 
331
                return NULL;
 
332
        }
292
333
 
293
334
        return conn;
294
335
}
296
337
gboolean g_dbus_request_name(DBusConnection *connection, const char *name,
297
338
                                                        DBusError *error)
298
339
{
 
340
        int result;
 
341
 
 
342
        result = dbus_bus_request_name(connection, name,
 
343
                                        DBUS_NAME_FLAG_DO_NOT_QUEUE, error);
 
344
 
 
345
        if (error != NULL) {
 
346
                if (dbus_error_is_set(error) == TRUE)
 
347
                        return FALSE;
 
348
        }
 
349
 
 
350
        if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
 
351
                if (error != NULL)
 
352
                        dbus_set_error(error, name, "Name already in use");
 
353
 
 
354
                return FALSE;
 
355
        }
 
356
 
299
357
        return TRUE;
300
358
}
301
359
 
305
363
{
306
364
        struct disconnect_data *dc_data;
307
365
 
308
 
        dc_data = g_new(struct disconnect_data, 1);
 
366
        dc_data = g_new0(struct disconnect_data, 1);
309
367
 
310
 
        dc_data->disconnect_cb = function;
 
368
        dc_data->function = function;
311
369
        dc_data->user_data = user_data;
312
370
 
313
371
        dbus_connection_set_exit_on_disconnect(connection, FALSE);
314
372
 
315
 
        if (dbus_connection_add_filter(connection, disconnect_filter,
316
 
                                                dc_data, g_free) == FALSE) {
317
 
                error("Can't add D-Bus disconnect filter");
 
373
        if (g_dbus_add_signal_watch(connection, NULL, NULL,
 
374
                                DBUS_INTERFACE_LOCAL, "Disconnected",
 
375
                                disconnected_signal, dc_data, g_free) == 0) {
 
376
                error("Failed to add watch for D-Bus Disconnected signal");
318
377
                g_free(dc_data);
319
378
                return FALSE;
320
379
        }