[D-BUS] How handle D-BUS messages without GLib main loop?
Claudio Takahasi
cktakahasi at gmail.com
Mon Jun 13 13:24:55 PDT 2005
The function dbus_connection_setup_with_g_main sets the watch
and timeout functions of a DBusConnection to integrate the
connection with the GLib main loop.
However, I need remove glib dependency. I developed
a workaround writing my own main loop and handling
D-Bus messages. The skeleton is below.
Is there another way to implement it?
Comments and suggestions are welcome!
Claudio.
... Start function:
dbus_connection_set_watch_functions(dbus_conn,
add_dbus_watch,
remove_dbus_watch,
watch_dbus_toggled,
NULL,
NULL);
poll_main_loop_run(main_loop);
...
/**
* Add D-Bus watch function
* @param watch D-Bus watch
* @return TRUE
**/
uint32_t add_dbus_watch(DBusWatch *watch, void *data)
{
uint32_t ret_val = 0;
uint32_t cond = POLLHUP | POLLERR;
int32_t *fd, flags;
if (!dbus_watch_get_enabled(watch))
return TRUE;
fd = (int32_t*)malloc(sizeof(int32_t));
if(!fd) {
syslog(LOG_ERR, "Can't allocate memory\n");
return TRUE;
}
(*fd) = dbus_watch_get_fd(watch);
flags = dbus_watch_get_flags(watch);
if (flags & DBUS_WATCH_READABLE)
cond |= POLLIN;
if (flags & DBUS_WATCH_WRITABLE)
cond |= POLLOUT;
fd_poll_add(*fd, cond, dbus_fd_handler , NULL, watch);
dbus_watch_set_data(watch, fd ,(DBusFreeFunction)free);
return ret_val;
}
/**
* D-Bus file descriptor handler
* @param fd D-Bus file descriptor
* @param cond socket condition
* @param udata watch
* @return TRUE
**/
static uint8_t dbus_fd_handler(int32_t fd, uint32_t cond, void *udata)
{
DBusWatch *watch = (DBusWatch *) udata;
uint32_t flags = 0;
if (cond & POLLIN)
flags |= DBUS_WATCH_READABLE;
if (cond & POLLOUT)
flags |= DBUS_WATCH_WRITABLE;
if (cond & POLLHUP)
flags |= DBUS_WATCH_HANGUP;
if (cond & POLLERR)
flags |= DBUS_WATCH_ERROR;
dbus_watch_handle(watch, flags);
dbus_connection_ref(dbus_conn);
/* Dispatch messages */
while (dbus_connection_dispatch(dbus_conn) == DBUS_DISPATCH_DATA_REMAINS);
dbus_connection_unref(dbus_conn);
return TRUE;
}
/**
* Creates a main loop
* @return returns the main loop
**/
static pand_main_loop_t * poll_main_loop_new()
{
pand_main_loop_t * loop = NULL;
loop = (pand_main_loop_t *) malloc(sizeof(pand_main_loop_t));
if(!loop) {
syslog(LOG_ERR, "Can't allocate memory\n");
return NULL;
}
memset(loop, 0, sizeof(pand_main_loop_t));
loop->run = 1;
return loop;
}
/**
* Exit from main loop
* @param loop the main loop
* @return (0) success (-1)fail
**/
static uint8_t poll_main_loop_exit(pand_main_loop_t * loop)
{
uint8_t ret_val = -1;
if (loop) {
loop->run = 0;
ret_val = 0;
}
return ret_val;
}
/**
* Free the main loop data
* @param loop the main loop
**/
static void poll_main_loop_free(pand_main_loop_t * loop)
{
//free all fds
fd_poll_free(loop->fd_poll_head.next);
if (loop) {
free(loop);
loop = NULL;
}
}
/**
* The main loop of the daemon
* @param loop the main loop pointer
**/
static void poll_main_loop_run(pand_main_loop_t * loop)
{
struct pollfd *fds;
struct fd_poll *p, *w;
int nfds, res, i;
uint8_t keep;
fds = malloc(WATCH_MAX * sizeof(struct pollfd));
if (!fds) {
syslog(LOG_ERR, "Can't allocate memory\n");
return;
}
while (loop->run) {
nfds = 0;
for (w = (main_loop->fd_poll_head.next); w != NULL; w = w->next) {
fds[nfds].fd = w->fd;
fds[nfds].events = w->flags;
fds[nfds].revents = 0;
nfds++;
}
res = poll(fds, nfds, -1);
if (res <= 0)
continue;
p = &(main_loop->fd_poll_head);
w = main_loop->fd_poll_head.next;
i = 0;
while (w) {
if (fds[i].revents) {
keep = w->func(w->fd, fds[i].revents, w->udata);
if (!keep) {
p->next = w->next;
memset(w, 0, sizeof(*w));
w = p->next;
i++;
continue;
}
}
p = w;
w = w->next;
i++;
}
}
free(fds);
}
More information about the dbus
mailing list