From c92339de11a2f27198aee3b4242aa6fccc12a004 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sat, 4 Jan 2003 20:29:46 +0000 Subject: 2003-01-04 Havoc Pennington * dbus/dbus-sysdeps.c (_dbus_sleep_milliseconds): new function (_dbus_poll): new function * dbus/dbus-internals.h (_DBUS_STRUCT_OFFSET): new macro copied from GLib * bus/loop.c: initial code for the daemon main loop --- bus/Makefile.am | 7 +- bus/loop.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bus/loop.h | 44 +++++++++++ bus/main.c | 161 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 434 insertions(+), 2 deletions(-) create mode 100644 bus/loop.c create mode 100644 bus/loop.h (limited to 'bus') diff --git a/bus/Makefile.am b/bus/Makefile.am index da115c4d..f51d8950 100644 --- a/bus/Makefile.am +++ b/bus/Makefile.am @@ -1,15 +1,18 @@ INCLUDES=-I$(top_srcdir) $(DBUS_BUS_CFLAGS) \ - -DDAEMON_NAME=\"dbus-daemon-1\" + -DDAEMON_NAME=\"dbus-daemon-1\" -DDBUS_COMPILATION EFENCE= bin_PROGRAMS=dbus-daemon-1 dbus_daemon_1_SOURCES= \ + loop.c \ + loop.h \ main.c dbus_daemon_1_LDADD= \ $(EFENCE) \ $(DBUS_BUS_LIBS) \ - $(top_builddir)/dbus/libdbus-convenience.la + $(top_builddir)/dbus/libdbus-convenience.la \ + $(top_builddir)/dbus/libdbus-1.la diff --git a/bus/loop.c b/bus/loop.c new file mode 100644 index 00000000..633ea42a --- /dev/null +++ b/bus/loop.c @@ -0,0 +1,224 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* loop.c Main loop for daemon + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "loop.h" +#include +#include + +static DBusList *watches = NULL; +static int watch_list_serial = 0; +static dbus_bool_t exited = FALSE; + +typedef struct +{ + DBusWatch *watch; + BusWatchFunction function; + void *data; + DBusFreeFunction free_data_func; +} WatchCallback; + +dbus_bool_t +bus_loop_add_watch (DBusWatch *watch, + BusWatchFunction function, + void *data, + DBusFreeFunction free_data_func) +{ + WatchCallback *cb; + + cb = dbus_new (WatchCallback, 1); + if (cb == NULL) + return FALSE; + + cb->watch = watch; + cb->function = function; + cb->data = data; + cb->free_data_func = free_data_func; + + if (!_dbus_list_append (&watches, cb)) + { + dbus_free (cb); + return FALSE; + } + + watch_list_serial += 1; + + return TRUE; +} + +void +bus_loop_remove_watch (DBusWatch *watch, + BusWatchFunction function, + void *data) +{ + DBusList *link; + + link = _dbus_list_get_first_link (&watches); + while (link != NULL) + { + DBusList *next = _dbus_list_get_next_link (&watches, link); + WatchCallback *cb = link->data; + + if (cb->watch == watch && + cb->function == function && + cb->data == data) + { + _dbus_list_remove_link (&watches, link); + + watch_list_serial += 1; + + if (cb->free_data_func) + (* cb->free_data_func) (cb->data); + dbus_free (cb); + + return; + } + + link = next; + } + + _dbus_warn ("could not find watch %p function %p data %p to remove\n", + watch, function, data); +} + +static void +wait_for_memory (void) +{ + _dbus_sleep_milliseconds (500); +} + +void +bus_loop_run (void) +{ + while (!exited) + { + DBusPollFD *fds; + int n_fds; + WatchCallback **watches_for_fds; + int i; + DBusList *link; + int n_ready; + int initial_serial; + + fds = NULL; + watches_for_fds = NULL; + + n_fds = _dbus_list_get_length (&watches); + + if (n_fds == 0) + { + bus_loop_quit (); + goto next_iteration; + } + + fds = dbus_new0 (DBusPollFD, n_fds); + while (fds == NULL) + { + wait_for_memory (); + fds = dbus_new0 (DBusPollFD, n_fds); + } + + watches_for_fds = dbus_new (WatchCallback*, n_fds); + while (watches_for_fds == NULL) + { + wait_for_memory (); + watches_for_fds = dbus_new (WatchCallback*, n_fds); + } + + i = 0; + link = _dbus_list_get_first_link (&watches); + while (link != NULL) + { + DBusList *next = _dbus_list_get_next_link (&watches, link); + WatchCallback *cb = link->data; + int flags; + + watches_for_fds[i] = cb; + + flags = dbus_watch_get_flags (cb->watch); + + fds[i].fd = dbus_watch_get_fd (cb->watch); + if (flags & DBUS_WATCH_READABLE) + fds[i].events |= _DBUS_POLLIN; + if (flags & DBUS_WATCH_WRITABLE) + fds[i].events |= _DBUS_POLLOUT; + + link = next; + ++i; + } + + n_ready = _dbus_poll (fds, n_fds, -1); + + if (n_ready > 0) + { + initial_serial = watch_list_serial; + i = 0; + while (i < n_fds) + { + if (initial_serial != watch_list_serial) + goto next_iteration; + + if (exited) + goto next_iteration; + + if (fds[i].revents != 0) + { + WatchCallback *cb; + unsigned int condition; + + cb = watches_for_fds[i]; + + condition = 0; + if (fds[i].revents & _DBUS_POLLIN) + condition |= DBUS_WATCH_READABLE; + if (fds[i].revents & _DBUS_POLLOUT) + condition |= DBUS_WATCH_WRITABLE; + if (fds[i].revents & _DBUS_POLLHUP) + condition |= DBUS_WATCH_HANGUP; + if (fds[i].revents & _DBUS_POLLERR) + condition |= DBUS_WATCH_ERROR; + + /* condition may still be 0 if we got some + * weird POLLFOO thing like POLLWRBAND + */ + + if (condition != 0) + (* cb->function) (cb->watch, + condition, + cb->data); + } + + ++i; + } + } + + next_iteration: + dbus_free (fds); + dbus_free (watches_for_fds); + } +} + +void +bus_loop_quit (void) +{ + exited = TRUE; +} diff --git a/bus/loop.h b/bus/loop.h new file mode 100644 index 00000000..e2b5e50a --- /dev/null +++ b/bus/loop.h @@ -0,0 +1,44 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* loop.h Main loop for daemon + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef BUS_LOOP_H +#define BUS_LOOP_H + +#include + +typedef void (* BusWatchFunction) (DBusWatch *watch, + unsigned int condition, + void *data); + +dbus_bool_t bus_loop_add_watch (DBusWatch *watch, + BusWatchFunction function, + void *data, + DBusFreeFunction free_data_func); +void bus_loop_remove_watch (DBusWatch *watch, + BusWatchFunction function, + void *data); +void bus_loop_run (void); +void bus_loop_quit (void); + + +#endif /* BUS_LOOP_H */ diff --git a/bus/main.c b/bus/main.c index 1025a0e7..199a10f0 100644 --- a/bus/main.c +++ b/bus/main.c @@ -1,8 +1,169 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* main.c main() for message bus + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include "loop.h" +#include +#include + +static DBusList *connections = NULL; + +static void +connection_error_handler (DBusConnection *connection, + DBusResultCode error_code, + void *data) +{ + _dbus_warn ("Error on connection: %s\n", + dbus_result_to_string (error_code)); + + /* we don't want to be called again since we're dropping the connection */ + dbus_connection_set_error_function (connection, NULL, NULL, NULL); + + _dbus_list_remove (&connections, connection); + dbus_connection_unref (connection); +} + +static void +connection_watch_callback (DBusWatch *watch, + unsigned int condition, + void *data) +{ + DBusConnection *connection = data; + + dbus_connection_handle_watch (connection, watch, condition); +} + +static void +server_watch_callback (DBusWatch *watch, + unsigned int condition, + void *data) +{ + DBusServer *server = data; + + dbus_server_handle_watch (server, watch, condition); +} + +static void +add_connection_watch (DBusWatch *watch, + DBusConnection *connection) +{ + bus_loop_add_watch (watch, connection_watch_callback, connection, + NULL); +} + +static void +remove_connection_watch (DBusWatch *watch, + DBusConnection *connection) +{ + bus_loop_remove_watch (watch, connection_watch_callback, connection); +} + +static void +add_server_watch (DBusWatch *watch, + DBusServer *server) +{ + bus_loop_add_watch (watch, server_watch_callback, server, + NULL); +} + +static void +remove_server_watch (DBusWatch *watch, + DBusServer *server) +{ + bus_loop_remove_watch (watch, server_watch_callback, server); +} + +static dbus_bool_t +setup_connection (DBusConnection *connection) +{ + if (!_dbus_list_append (&connections, connection)) + { + dbus_connection_disconnect (connection); + return FALSE; + } + + dbus_connection_ref (connection); + + dbus_connection_set_watch_functions (connection, + (DBusAddWatchFunction) add_connection_watch, + (DBusRemoveWatchFunction) remove_connection_watch, + connection, + NULL); + + dbus_connection_set_error_function (connection, + connection_error_handler, + NULL, NULL); + + return TRUE; +} + +static void +setup_server (DBusServer *server) +{ + dbus_server_set_watch_functions (server, + (DBusAddWatchFunction) add_server_watch, + (DBusRemoveWatchFunction) remove_server_watch, + server, + NULL); +} + +static void +new_connection_callback (DBusServer *server, + DBusConnection *new_connection, + void *data) +{ + if (!setup_connection (new_connection)) + ; /* we won't have ref'd the connection so it will die */ +} int main (int argc, char **argv) { + DBusServer *server; + DBusResultCode result; + + if (argc < 2) + { + _dbus_warn ("Give the server address as an argument\n"); + return 1; + } + + server = dbus_server_listen (argv[1], &result); + if (server == NULL) + { + _dbus_warn ("Failed to start server on %s: %s\n", + argv[1], dbus_result_to_string (result)); + return 1; + } + + setup_server (server); + dbus_server_set_new_connection_function (server, + new_connection_callback, + NULL, NULL); + + bus_loop_run (); + + dbus_server_disconnect (server); + dbus_server_unref (server); return 0; } -- cgit