3
Simo Sorce <ssorce@redhat.com>
4
Stephen Gallagher <sgallagh@redhat.com>
6
Copyright (C) 2009 Red Hat
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 3 of the License, or
11
(at your option) any later version.
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.
18
You should have received a copy of the GNU General Public License
19
along with this program. If not, see <http://www.gnu.org/licenses/>.
24
#include "dbus/dbus.h"
25
#include "util/util.h"
26
#include "sbus/sssd_dbus.h"
27
#include "sbus/sssd_dbus_private.h"
29
/* =Watches=============================================================== */
31
/* DBUS may ask us to add a watch to a file descriptor that already had a watch
32
* associated. Need to check if that's the case */
33
static struct sbus_watch_ctx *fd_to_watch(struct sbus_watch_ctx *list, int fd)
35
struct sbus_watch_ctx *watch_iter;
38
while (watch_iter != NULL) {
39
if (watch_iter->fd == fd) {
43
watch_iter = watch_iter->next;
49
static int watch_destructor(void *mem)
51
struct sbus_watch_ctx *watch;
53
watch = talloc_get_type(mem, struct sbus_watch_ctx);
54
DLIST_REMOVE(watch->conn->watch_list, watch);
61
* Callback for D-BUS to handle messages on a file-descriptor
63
static void sbus_watch_handler(struct tevent_context *ev,
64
struct tevent_fd *fde,
65
uint16_t flags, void *data)
67
struct sbus_watch_ctx *watch = talloc_get_type(data,
68
struct sbus_watch_ctx);
69
enum dbus_conn_type type;
70
union dbus_conn_pointer dbus_p;
72
/* conn may get freed inside a handle, save the data we need for later */
73
type = watch->conn->type;
74
dbus_p = watch->conn->dbus;
76
/* Take a reference while handling watch */
77
if (type == SBUS_SERVER) {
78
dbus_server_ref(dbus_p.server);
80
dbus_connection_ref(dbus_p.conn);
83
/* Fire if readable */
84
if (flags & TEVENT_FD_READ) {
85
if (watch->dbus_read_watch) {
86
dbus_watch_handle(watch->dbus_read_watch, DBUS_WATCH_READABLE);
90
/* Fire if writeable */
91
if (flags & TEVENT_FD_WRITE) {
92
if (watch->dbus_write_watch) {
93
dbus_watch_handle(watch->dbus_write_watch, DBUS_WATCH_WRITABLE);
97
/* Release reference once done */
98
if (type == SBUS_SERVER) {
99
dbus_server_unref(dbus_p.server);
101
dbus_connection_unref(dbus_p.conn);
107
* Set up hooks into the libevents mainloop for
108
* D-BUS to add file descriptor-based events
110
dbus_bool_t sbus_add_watch(DBusWatch *dbus_watch, void *data)
113
uint16_t event_flags;
114
struct sbus_connection *conn;
115
struct sbus_watch_ctx *watch;
119
conn = talloc_get_type(data, struct sbus_connection);
121
#ifdef HAVE_DBUS_WATCH_GET_UNIX_FD
122
fd = dbus_watch_get_unix_fd(dbus_watch);
124
fd = dbus_watch_get_fd(dbus_watch);
127
watch = fd_to_watch(conn->watch_list, fd);
129
/* does not exist, allocate new one */
130
watch = talloc_zero(conn, struct sbus_watch_ctx);
132
DEBUG(0, ("Out of Memory!\n"));
139
enabled = dbus_watch_get_enabled(dbus_watch);
140
flags = dbus_watch_get_flags(dbus_watch);
142
/* Save the event to the watch object so it can be found later */
143
if (flags & DBUS_WATCH_READABLE) {
144
watch->dbus_read_watch = dbus_watch;
146
if (flags & DBUS_WATCH_WRITABLE) {
147
watch->dbus_write_watch = dbus_watch;
149
dbus_watch_set_data(dbus_watch, watch, NULL);
152
/* pre-existing event, just toggle flags */
153
sbus_toggle_watch(dbus_watch, data);
159
if (flags & DBUS_WATCH_READABLE) {
160
event_flags |= TEVENT_FD_READ;
162
if (flags & DBUS_WATCH_WRITABLE) {
163
event_flags |= TEVENT_FD_WRITE;
167
/* Add the file descriptor to the event loop */
168
watch->fde = tevent_add_fd(conn->ev,
169
watch, fd, event_flags,
170
sbus_watch_handler, watch);
172
DEBUG(0, ("Failed to set up fd event!\n"));
177
DLIST_ADD(conn->watch_list, watch);
178
talloc_set_destructor((TALLOC_CTX *)watch, watch_destructor);
180
DEBUG(8, ("%p/%p (%d), %s/%s (%s)\n",
181
watch, dbus_watch, fd,
182
((flags & DBUS_WATCH_READABLE)?"R":"-"),
183
((flags & DBUS_WATCH_WRITABLE)?"W":"-"),
184
enabled?"enabled":"disabled"));
191
* Hook for D-BUS to toggle the enabled/disabled state of
192
* an event in the mainloop
194
void sbus_toggle_watch(DBusWatch *dbus_watch, void *data)
196
struct sbus_watch_ctx *watch;
202
enabled = dbus_watch_get_enabled(dbus_watch);
203
flags = dbus_watch_get_flags(dbus_watch);
205
watch_data = dbus_watch_get_data(dbus_watch);
206
watch = talloc_get_type(watch_data, struct sbus_watch_ctx);
208
DEBUG(2, ("[%p] does not carry watch context?!\n", dbus_watch));
214
if (flags & DBUS_WATCH_READABLE) {
215
TEVENT_FD_READABLE(watch->fde);
217
if (flags & DBUS_WATCH_WRITABLE) {
218
TEVENT_FD_WRITEABLE(watch->fde);
221
if (flags & DBUS_WATCH_READABLE) {
222
TEVENT_FD_NOT_READABLE(watch->fde);
224
if (flags & DBUS_WATCH_WRITABLE) {
225
TEVENT_FD_NOT_WRITEABLE(watch->fde);
229
if (debug_level >= 8) {
230
#ifdef HAVE_DBUS_WATCH_GET_UNIX_FD
231
fd = dbus_watch_get_unix_fd(dbus_watch);
233
fd = dbus_watch_get_fd(dbus_watch);
236
DEBUG(8, ("%p/%p (%d), %s/%s (%s)\n",
237
watch, dbus_watch, fd,
238
((flags & DBUS_WATCH_READABLE)?"R":"-"),
239
((flags & DBUS_WATCH_WRITABLE)?"W":"-"),
240
enabled?"enabled":"disabled"));
245
* Hook for D-BUS to remove file descriptor-based events
246
* from the libevents mainloop
248
void sbus_remove_watch(DBusWatch *dbus_watch, void *data)
250
struct sbus_watch_ctx *watch;
253
watch_data = dbus_watch_get_data(dbus_watch);
254
watch = talloc_get_type(watch_data, struct sbus_watch_ctx);
256
DEBUG(8, ("%p/%p\n", watch, dbus_watch));
259
DEBUG(2, ("DBUS trying to remove unknown watch!\n"));
263
/* remove dbus watch data */
264
dbus_watch_set_data(dbus_watch, NULL, NULL);
266
/* check which watch to remove, or free if none left */
267
if (watch->dbus_read_watch == dbus_watch) {
268
watch->dbus_read_watch = NULL;
270
if (watch->dbus_write_watch == dbus_watch) {
271
watch->dbus_write_watch = NULL;
273
if (!watch->dbus_read_watch && !watch->dbus_write_watch) {
278
/* =Timeouts============================================================== */
280
static struct timeval _get_interval_tv(int interval) {
282
struct timeval rightnow;
284
gettimeofday(&rightnow,NULL);
286
tv.tv_sec = interval / 1000 + rightnow.tv_sec;
287
tv.tv_usec = (interval % 1000) * 1000 + rightnow.tv_usec;
293
* Callback for D-BUS to handle timed events
295
static void sbus_timeout_handler(struct tevent_context *ev,
296
struct tevent_timer *te,
297
struct timeval t, void *data)
299
struct sbus_timeout_ctx *timeout;
300
timeout = talloc_get_type(data, struct sbus_timeout_ctx);
302
dbus_timeout_handle(timeout->dbus_timeout);
307
* Hook for D-BUS to add time-based events to the mainloop
309
dbus_bool_t sbus_add_timeout(DBusTimeout *dbus_timeout, void *data)
311
struct sbus_connection *conn;
312
struct sbus_timeout_ctx *timeout;
315
DEBUG(8, ("%p\n", dbus_timeout));
317
if (!dbus_timeout_get_enabled(dbus_timeout)) {
321
conn = talloc_get_type(data, struct sbus_connection);
323
timeout = talloc_zero(conn, struct sbus_timeout_ctx);
325
DEBUG(0, ("Out of Memory!\n"));
328
timeout->dbus_timeout = dbus_timeout;
330
tv = _get_interval_tv(dbus_timeout_get_interval(dbus_timeout));
331
timeout->te = tevent_add_timer(conn->ev, timeout, tv,
332
sbus_timeout_handler, timeout);
334
DEBUG(0, ("Failed to set up timeout event!\n"));
338
/* Save the event to the watch object so it can be removed later */
339
dbus_timeout_set_data(timeout->dbus_timeout, timeout, NULL);
345
* sbus_toggle_timeout
346
* Hook for D-BUS to toggle the enabled/disabled state of a mainloop
349
void sbus_toggle_timeout(DBusTimeout *dbus_timeout, void *data)
351
DEBUG(8, ("%p\n", dbus_timeout));
353
if (dbus_timeout_get_enabled(dbus_timeout)) {
354
sbus_add_timeout(dbus_timeout, data);
356
sbus_remove_timeout(dbus_timeout, data);
361
* sbus_remove_timeout
362
* Hook for D-BUS to remove time-based events from the mainloop
364
void sbus_remove_timeout(DBusTimeout *dbus_timeout, void *data)
368
DEBUG(8, ("%p\n", dbus_timeout));
370
timeout = dbus_timeout_get_data(dbus_timeout);
372
/* remove dbus timeout data */
373
dbus_timeout_set_data(dbus_timeout, NULL, NULL);
375
/* Freeing the event object will remove it from the event loop */
376
talloc_free(timeout);
380
/* =Helpers=============================================================== */
382
int sbus_is_dbus_fixed_type(int dbus_type)
386
case DBUS_TYPE_BOOLEAN:
387
case DBUS_TYPE_INT16:
388
case DBUS_TYPE_UINT16:
389
case DBUS_TYPE_INT32:
390
case DBUS_TYPE_UINT32:
391
case DBUS_TYPE_INT64:
392
case DBUS_TYPE_UINT64:
393
case DBUS_TYPE_DOUBLE:
399
int sbus_is_dbus_string_type(int dbus_type)
402
case DBUS_TYPE_STRING:
403
case DBUS_TYPE_OBJECT_PATH:
404
case DBUS_TYPE_SIGNATURE:
410
size_t sbus_get_dbus_type_size(int dbus_type)
421
case DBUS_TYPE_INT16:
422
case DBUS_TYPE_UINT16:
427
case DBUS_TYPE_BOOLEAN:
428
case DBUS_TYPE_INT32:
429
case DBUS_TYPE_UINT32:
434
case DBUS_TYPE_INT64:
435
case DBUS_TYPE_UINT64:
436
case DBUS_TYPE_DOUBLE: