From 99cfa54d0fb675c7d3cb228d3f54d26539073af3 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 12 Jan 2005 18:40:04 +0000 Subject: [PATCH] 2005-01-12 Dan Williams * libnm_glib/ - Client library for applications using glib * configure.in various Makefiles - Split NM_CFLAGS and NM_LIBS into separate variables like DBUS_*, HAL_* and GLIB_* * src/NetworkManager.c src/NetworkManagerMain.h - (nm_schedule_status_signal_broadcast): at the earliest convenience, broadcast a status changed signal over DBUS from the main thread. Still unused anywhere for the moment. Patch from j@bootlab.org * panel_applet/NMWirelessAppletDbus.c src/NetworkManagerDbus.c - Correct INT32->UINT32 mistmatch between NM and the panel applet for the "getMode" method call git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@368 4912f4e0-d625-0410-9fb7-b9a5a253dbdc --- ChangeLog | 22 ++ Makefile.am | 2 +- configure.in | 18 +- dhcpcd/Makefile.am | 7 +- dispatcher-daemon/Makefile.am | 5 +- info-daemon/Makefile.am | 19 +- libnm_glib/Makefile.am | 29 ++ libnm_glib/libnm_glib.c | 545 ++++++++++++++++++++++++++++ libnm_glib/libnm_glib.h | 62 ++++ libnm_glib/libnm_glib.pc.in | 13 + named/Makefile.am | 4 +- panel-applet/Makefile.am | 32 +- panel-applet/NMWirelessAppletDbus.c | 8 +- src/Makefile.am | 35 +- src/NetworkManager.c | 33 ++ src/NetworkManagerAPList.c | 1 - src/NetworkManagerDbus.c | 2 +- src/NetworkManagerMain.h | 10 +- test/Makefile.am | 17 +- test/libnm_glib_test.c | 86 +++++ 20 files changed, 885 insertions(+), 65 deletions(-) create mode 100644 libnm_glib/Makefile.am create mode 100644 libnm_glib/libnm_glib.c create mode 100644 libnm_glib/libnm_glib.h create mode 100644 libnm_glib/libnm_glib.pc.in create mode 100644 test/libnm_glib_test.c diff --git a/ChangeLog b/ChangeLog index 34ab7eb57b..79a1efcc4d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2005-01-12 Dan Williams + + * libnm_glib/ + - Client library for applications using glib + + * configure.in + various Makefiles + - Split NM_CFLAGS and NM_LIBS into separate variables + like DBUS_*, HAL_* and GLIB_* + + * src/NetworkManager.c + src/NetworkManagerMain.h + - (nm_schedule_status_signal_broadcast): at the earliest convenience, + broadcast a status changed signal over DBUS from the main thread. + Still unused anywhere for the moment. + + Patch from j@bootlab.org + * panel_applet/NMWirelessAppletDbus.c + src/NetworkManagerDbus.c + - Correct INT32->UINT32 mistmatch between NM and the panel applet + for the "getMode" method call + 2005-01-10 Dan Williams * src/NetworkManagerDevice.c diff --git a/Makefile.am b/Makefile.am index 9ada7618ed..41e8b8168c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = dhcpcd named src dispatcher-daemon $(notification_icon_dir) info-daemon initscript test po +SUBDIRS = dhcpcd named src libnm_glib dispatcher-daemon $(notification_icon_dir) info-daemon initscript test po EXTRA_DIST = CONTRIBUTING NetworkManager.pc.in NetworkManager.h diff --git a/configure.in b/configure.in index 96cf0c051e..1fb64d16b4 100644 --- a/configure.in +++ b/configure.in @@ -1,6 +1,6 @@ AC_PREREQ(2.52) -AC_INIT(NetworkManager, 0.3.2, dcbw@redhat.com, NetworkManager) +AC_INIT(NetworkManager, 0.3.3, dcbw@redhat.com, NetworkManager) AM_INIT_AUTOMAKE([subdir-objects]) AM_CONFIG_HEADER(config.h) @@ -84,9 +84,17 @@ AC_CHECK_LIB(iw, iw_scan, [ IWLIB=-liw ], [AC_MSG_ERROR(wireless-tools 27.pre23 not installed or not functional)], []) AC_SUBST(IWLIB) -PKG_CHECK_MODULES(NM, dbus-glib-1 >= 0.20 hal >= 0.2.91 gthread-2.0) -AC_SUBST(NM_CFLAGS) -AC_SUBST(NM_LIBS) +PKG_CHECK_MODULES(DBUS, dbus-glib-1 >= 0.20) +AC_SUBST(DBUS_CFLAGS) +AC_SUBST(DBUS_LIBS) + +PKG_CHECK_MODULES(GTHREAD, gthread-2.0) +AC_SUBST(GTHREAD_CFLAGS) +AC_SUBST(GTHREAD_LIBS) + +PKG_CHECK_MODULES(HAL, hal >= 0.2.91) +AC_SUBST(HAL_CFLAGS) +AC_SUBST(HAL_LIBS) PKG_CHECK_MODULES(GTK, gtk+-2.0) AC_SUBST(GTK_CFLAGS) @@ -240,6 +248,7 @@ panel-applet/Makefile panel-applet/icons/Makefile named/Makefile dhcpcd/Makefile +libnm_glib/Makefile test/Makefile initscript/Makefile initscript/RedHat/Makefile @@ -248,6 +257,7 @@ initscript/Debian/Makefile initscript/Slackware/Makefile po/Makefile.in NetworkManager.pc +libnm_glib/libnm_glib.pc ]) echo diff --git a/dhcpcd/Makefile.am b/dhcpcd/Makefile.am index ded3a32428..bf255213d3 100644 --- a/dhcpcd/Makefile.am +++ b/dhcpcd/Makefile.am @@ -1,14 +1,13 @@ INCLUDES = -I${top_srcdir} -I${top_srcdir}/src -AM_CPPFLAGS = \ - $(NM_CFLAGS) \ +noinst_LIBRARIES = libdhcpc.a + +libdhcpc_a_CPPFLAGS = \ -DBINDIR=\"$(bindir)\" \ -DDATADIR=\"$(datadir)\" \ -DARP_DEBUG \ -DDEBUG -noinst_LIBRARIES = libdhcpc.a - libdhcpc_a_SOURCES= \ buildmsg.c \ buildmsg.h \ diff --git a/dispatcher-daemon/Makefile.am b/dispatcher-daemon/Makefile.am index b5be55ba01..6321616add 100644 --- a/dispatcher-daemon/Makefile.am +++ b/dispatcher-daemon/Makefile.am @@ -1,5 +1,6 @@ INCLUDES = \ - $(NM_CFLAGS) \ + $(DBUS_CFLAGS) \ + $(GTHREAD_CFLAGS) \ -Wall \ -DDBUS_API_SUBJECT_TO_CHANGE \ -DBINDIR=\"$(bindir)\" \ @@ -9,5 +10,5 @@ bin_PROGRAMS = NetworkManagerDispatcher NetworkManagerDispatcher_SOURCES = NetworkManagerDispatcher.c -NetworkManagerDispatcher_LDADD = $(NM_LIBS) +NetworkManagerDispatcher_LDADD = $(DBUS_LIBS) $(GTHREAD_LIBS) diff --git a/info-daemon/Makefile.am b/info-daemon/Makefile.am index f905ebc819..17480f1b3b 100644 --- a/info-daemon/Makefile.am +++ b/info-daemon/Makefile.am @@ -2,7 +2,8 @@ INCLUDES = -I${top_srcdir} AM_CPPFLAGS = \ - $(NM_CFLAGS) \ + $(DBUS_CFLAGS) \ + $(GTHREAD_CFLAGS) \ $(GTK_CFLAGS) \ $(GDK_PIXBUF_CFLAGS) \ $(GLADE_CFLAGS) \ @@ -35,13 +36,15 @@ NetworkManagerInfo_SOURCES = NetworkManagerInfo.h \ NetworkManagerInfoNetworksDialog.c \ NetworkManagerInfoNetworksDialog.h -NetworkManagerInfo_LDADD = $(NM_LIBS) \ - $(GLADE_LIBS) \ - $(GCONF_LIBS) \ - $(GTK_LIBS) \ - $(GDK_PIXBUF_LIBS) \ - $(GNOME_KEYRING_LIBS) \ - $(LIBGNOMEUI_LIBS) +NetworkManagerInfo_LDADD = \ + $(DBUS_LIBS) \ + $(GTHREAD_LIBS) \ + $(GLADE_LIBS) \ + $(GCONF_LIBS) \ + $(GTK_LIBS) \ + $(GDK_PIXBUF_LIBS) \ + $(GNOME_KEYRING_LIBS) \ + $(LIBGNOMEUI_LIBS) gladedir = $(datadir)/NetworkManagerInfo/glade glade_DATA = passphrase.glade keyring.png networks.glade diff --git a/libnm_glib/Makefile.am b/libnm_glib/Makefile.am new file mode 100644 index 0000000000..43d0bcf663 --- /dev/null +++ b/libnm_glib/Makefile.am @@ -0,0 +1,29 @@ +INCLUDES = -I${top_srcdir} + +lib_LTLIBRARIES=libnm_glib.la + +libnm_glib_la_CPPFLAGS = \ + $(DBUS_CFLAGS) \ + $(GTHREAD_CFLAGS) \ + -DDBUS_API_SUBJECT_TO_CHANGE + +libnm_glib_la_SOURCES= \ + libnm_glib.c \ + libnm_glib.h + +libnm_glib_la_LDFLAGS= \ + $(DBUS_LIBS) \ + $(GTHREAD_LIBS) + +libnm_glib_includedir=$(includedir)/NetworkManager + +libnm_glib_include_HEADERS = libnm_glib.h + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libnm_glib.pc + +DISTCLEANFILES = \ + libnm_glib.pc + +EXTRA_DIST = \ + libnm_glib.pc.in diff --git a/libnm_glib/libnm_glib.c b/libnm_glib/libnm_glib.c new file mode 100644 index 0000000000..60b27a45d6 --- /dev/null +++ b/libnm_glib/libnm_glib.c @@ -0,0 +1,545 @@ +/* libnm_glib -- Access NetworkManager information from applications + * + * Dan Williams + * + * 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. + * + * (C) Copyright 2005 Red Hat, Inc. + */ + + +#include +#include +#include +#include +#include +#include +#include "NetworkManager.h" +#include "libnm_glib.h" + +#define DBUS_NO_SERVICE_ERROR "org.freedesktop.DBus.Error.ServiceDoesNotExist" + +typedef struct libnm_glib_callback +{ + gint id; + GMainContext *ctx; + GSourceFunc func; + gpointer user_data; +} libnm_glib_callback; + +struct libnm_glib_ctx +{ + unsigned char check; + + GMainContext *g_main_ctx; + GMainLoop *g_main_loop; + DBusConnection *dbus_con; + guint dbus_watcher; + gboolean thread_done; + gboolean thread_inited; + + GSList *callbacks; + GMutex *callbacks_lock; + gint callback_id_last; + + libnm_glib_status nm_status; +}; + + +static void libnm_glib_schedule_dbus_watcher (libnm_glib_ctx *ctx); +static DBusConnection * libnm_glib_dbus_init (gpointer *user_data, GMainContext *context); + + + +static char *libnm_glib_get_nm_status (DBusConnection *con) +{ + DBusMessage *message; + DBusMessage *reply; + DBusError error; + char *status = NULL; + char *ret = NULL; + + g_return_val_if_fail (con != NULL, NULL); + + if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, "status"))) + { + fprintf (stderr, "libnm_glib_get_nm_status(): Couldn't allocate the dbus message\n"); + return NULL; + } + + dbus_error_init (&error); + reply = dbus_connection_send_with_reply_and_block (con, message, -1, &error); + dbus_message_unref (message); + if (dbus_error_is_set (&error)) + { + fprintf (stderr, "libnm_glib_get_nm_status(): %s raised:\n %s\n\n", error.name, error.message); + dbus_error_free (&error); + return NULL; + } + + if (!reply) + { + fprintf (stderr, "libnm_glib_get_nm_status(): dbus reply message was NULL\n" ); + return NULL; + } + + dbus_error_init (&error); + if (!(dbus_message_get_args (reply, &error, DBUS_TYPE_STRING, &status, DBUS_TYPE_INVALID))) + { + fprintf (stderr, "libnm_glib_get_nm_status(): error while getting args: name='%s' message='%s'\n", error.name, error.message); + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + dbus_message_unref (reply); + return g_strdup ("error"); + } + dbus_message_unref (reply); + ret = g_strdup (status); + dbus_free (status); + + return ret; +} + + +static void libnm_glib_schedule_single_callback (libnm_glib_ctx *ctx, libnm_glib_callback *callback) +{ + GSource *source; + libnm_glib_callback_data *data; + + g_return_if_fail (ctx != NULL); + g_return_if_fail (callback != NULL); + + data = g_malloc0 (sizeof (libnm_glib_callback_data)); + data->libnm_ctx = ctx; + data->user_data = callback->user_data; + + source = g_idle_source_new (); + g_source_set_callback (source, callback->func, data, NULL); + g_source_attach (source, callback->ctx); + g_source_unref (source); +} + + +static void libnm_glib_call_callbacks (libnm_glib_ctx *ctx) +{ + GSList *elem; + + g_return_if_fail (ctx != NULL); + + g_mutex_lock (ctx->callbacks_lock); + elem = ctx->callbacks; + while (elem) + { + libnm_glib_callback *callback = (libnm_glib_callback *)(elem->data); + if (callback) + libnm_glib_schedule_single_callback (ctx, callback); + elem = g_slist_next (elem); + } + g_mutex_unlock (ctx->callbacks_lock); +} + + +void libnm_glib_callback_data_free (libnm_glib_callback_data *data) +{ + g_return_if_fail (data != NULL); + + g_free (data); +} + + +static void libnm_glib_update_status (libnm_glib_ctx *ctx, char *status) +{ + libnm_glib_status old_status; + + g_return_if_fail (ctx != NULL); + + old_status = ctx->nm_status; + if (!status) + ctx->nm_status = LIBNM_NO_NETWORKMANAGER; + else if (strcmp (status, "connected") == 0) + ctx->nm_status = LIBNM_ACTIVE_NETWORK_CONNECTION; + else + ctx->nm_status = LIBNM_NO_NETWORK_CONNECTION; + + if (old_status != ctx->nm_status) + libnm_glib_call_callbacks (ctx); +} + + +static DBusHandlerResult libnm_glib_dbus_filter (DBusConnection *connection, DBusMessage *message, void *user_data) +{ + libnm_glib_ctx *ctx = (libnm_glib_ctx *)user_data; + gboolean handled = TRUE; + DBusError error; + + g_return_val_if_fail (ctx != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + g_return_val_if_fail (connection != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + dbus_error_init (&error); + if (dbus_message_is_signal (message, DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, "Disconnected")) + { + /* Try to reactivate our connection to dbus on the next pass through the event loop */ + ctx->nm_status = LIBNM_NO_DBUS; + dbus_connection_disconnect (ctx->dbus_con); + libnm_glib_schedule_dbus_watcher (ctx); + } + if (dbus_message_is_signal (message, DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, "ServiceCreated")) + { + char *service; + + if ( dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &service, DBUS_TYPE_INVALID) + && (strcmp (service, NM_DBUS_SERVICE) == 0)) + { + char *status_string = libnm_glib_get_nm_status (ctx->dbus_con); + libnm_glib_update_status (ctx, status_string); + g_free (status_string); + } + } + else if (dbus_message_is_signal (message, DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, "ServiceDeleted")) + { + char *service; + + if ( dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &service, DBUS_TYPE_INVALID) + && (strcmp (service, NM_DBUS_SERVICE) == 0)) + { + ctx->nm_status = LIBNM_NO_NETWORKMANAGER; + } + } + else if ( dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceNowActive") + || dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceNoLongerActive") + || dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceActivating") + || dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DevicesChanged")) + { + char *status_string = libnm_glib_get_nm_status (ctx->dbus_con); + libnm_glib_update_status (ctx, status_string); + g_free (status_string); + } + else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, "NetworkStatusChange")) + { + char *status_string = NULL; + + if (!(dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &status_string, DBUS_TYPE_INVALID))) + status_string = g_strdup ("error"); + + libnm_glib_update_status (ctx, status_string); + g_free (status_string); + } + else + handled = FALSE; + + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + + return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED); +} + + +/* + * libnm_glib_dbus_init + * + * Initialize a connection to dbus and set up our callbacks. + * + */ +static DBusConnection * libnm_glib_dbus_init (gpointer *user_data, GMainContext *context) +{ + DBusConnection *connection = NULL; + DBusError error; + + dbus_error_init (&error); + connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); + if (dbus_error_is_set (&error)) + { + fprintf (stderr, "libnm: error, %s raised:\n %s\n\n", error.name, error.message); + dbus_error_free (&error); + return (NULL); + } + if (!connection) + return NULL; + + if (!dbus_connection_add_filter (connection, libnm_glib_dbus_filter, user_data, NULL)) + return (NULL); + + dbus_connection_set_exit_on_disconnect (connection, FALSE); + dbus_connection_setup_with_g_main (connection, context); + + dbus_error_init (&error); + dbus_bus_add_match(connection, + "type='signal'," + "interface='" DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS "'," + "sender='" DBUS_SERVICE_ORG_FREEDESKTOP_DBUS "'", + &error); + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + + dbus_error_init (&error); + dbus_bus_add_match(connection, + "type='signal'," + "interface='" NM_DBUS_INTERFACE "'," + "path='" NM_DBUS_PATH "'," + "sender='" NM_DBUS_SERVICE "'", + &error); + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + + return (connection); +} + + +/* + * libnm_glib_dbus_watcher + * + * Repeatedly try to re-activate the connection to dbus. + * + */ +static gboolean libnm_glib_dbus_watcher (gpointer user_data) +{ + libnm_glib_ctx *ctx = (libnm_glib_ctx *)user_data; + + g_return_val_if_fail (ctx != NULL, FALSE); + + if (!ctx->dbus_con) + ctx->dbus_con = libnm_glib_dbus_init ((gpointer)ctx, ctx->g_main_ctx); + + if (ctx->dbus_con) + return (FALSE); /* Don't reschedule ourselves if we have a connection to dbus */ + + /* Reschule ourselves if we _still_ don't have a connection to dbus */ + return (TRUE); +} + + +/* + * libnm_glib_schedule_dbus_watcher + * + * Schedule an idle handler in our main loop to repeatedly + * attempt to re-activate the dbus connection until connected. + * + */ +static void libnm_glib_schedule_dbus_watcher (libnm_glib_ctx *ctx) +{ + g_return_if_fail (ctx != NULL); + + if (ctx->dbus_watcher == 0) + { + GSource *source = g_idle_source_new (); + g_source_set_callback (source, libnm_glib_dbus_watcher, (gpointer)ctx, NULL); + ctx->dbus_watcher = g_source_attach (source, ctx->g_main_ctx); + g_source_unref (source); + } +} + + +/* + * libnm_glib_dbus_worker + * + * Main thread for libnm + * + */ +static gpointer libnm_glib_dbus_worker (gpointer user_data) +{ + libnm_glib_ctx *ctx = (libnm_glib_ctx *)user_data; + + g_return_val_if_fail (ctx != NULL, NULL); + + /* If dbus isn't up yet, schedule an idle handler to check for dbus. + * We also need a way to reconnect to dbus if the connection ever goes + * down. Should probably be done by a timeout polling dbus_connection_is_connected() + * or by getting connection status out of libdbus or something. + */ + if (!ctx->dbus_con) + libnm_glib_schedule_dbus_watcher (ctx); + { + char *status_string = NULL; + + /* Get initial status */ + status_string = libnm_glib_get_nm_status (ctx->dbus_con); + libnm_glib_update_status (ctx, status_string); + g_free (status_string); + } + + ctx->thread_inited = TRUE; + g_main_loop_run (ctx->g_main_loop); + ctx->thread_done = TRUE; + + return NULL; +} + + +static void libnm_glib_ctx_free (libnm_glib_ctx *ctx) +{ + g_return_if_fail (ctx != NULL); + + if (ctx->check == 0xDD) + { + fprintf (stderr, "libnm_glib_ctx_free(): context %p already freed!\n", ctx); + return; + } + + if (ctx->g_main_ctx) + g_main_context_unref (ctx->g_main_ctx); + if (ctx->g_main_loop) + g_main_loop_unref (ctx->g_main_loop); + + if (ctx->dbus_con) + dbus_connection_disconnect (ctx->dbus_con); + + if (ctx->callbacks_lock) + g_mutex_free (ctx->callbacks_lock); + + g_slist_foreach (ctx->callbacks, (GFunc)g_free, NULL); + g_slist_free (ctx->callbacks); + + memset (ctx, 0, sizeof (libnm_glib_ctx)); + memset (&(ctx->check), 0xDD, sizeof (ctx->check)); + g_free (ctx); +} + + +static libnm_glib_ctx *libnm_glib_ctx_new (void) +{ + libnm_glib_ctx *ctx = g_malloc0 (sizeof (libnm_glib_ctx)); + + if (!ctx) + return NULL; + + if (!(ctx->g_main_ctx = g_main_context_new ())) + goto error; + if (!(ctx->g_main_loop = g_main_loop_new (ctx->g_main_ctx, FALSE))) + goto error; + if (!(ctx->callbacks_lock = g_mutex_new ())) + goto error; + +success: + return ctx; + +error: + libnm_glib_ctx_free (ctx); + return NULL; +} + + +libnm_glib_ctx *libnm_glib_init (void) +{ + GError *error = NULL; + libnm_glib_ctx *ctx = NULL; + + g_type_init (); + if (!g_thread_supported ()) + g_thread_init (NULL); + + ctx = libnm_glib_ctx_new(); + if (!ctx) + return NULL; + + /* We don't care if dbus isn't around yet, we keep checking for it and + * intialize our connection when it comes up. + */ + ctx->dbus_con = libnm_glib_dbus_init ((gpointer)ctx, ctx->g_main_ctx); + if (ctx->dbus_con) + { + char *status_string = libnm_glib_get_nm_status (ctx->dbus_con); + libnm_glib_update_status (ctx, status_string); + dbus_free (status_string); + } + + if (!g_thread_create (libnm_glib_dbus_worker, ctx, FALSE, &error)) + { + if (error) + g_error_free (error); + goto error; + } + + /* Wait until initialization of the thread */ + while (!ctx->thread_inited) + g_usleep (G_USEC_PER_SEC / 2); + +success: + return ctx; + +error: + libnm_glib_ctx_free (ctx); + return NULL; +} + + +void libnm_glib_shutdown (libnm_glib_ctx *ctx) +{ + g_return_if_fail (ctx != NULL); + + g_main_loop_quit (ctx->g_main_loop); + while (!(ctx->thread_done)) + g_usleep (G_USEC_PER_SEC / 2); + + libnm_glib_ctx_free (ctx); +} + + +libnm_glib_status libnm_glib_get_network_status (const libnm_glib_ctx *ctx) +{ + if (!ctx) + return LIBNM_INVALID_CONTEXT; + + return ctx->nm_status; +} + + +gint libnm_glib_register_callback (libnm_glib_ctx *ctx, GSourceFunc func, gpointer user_data, GMainContext *g_main_ctx) +{ + libnm_glib_callback *callback = NULL; + libnm_glib_callback_data *data = NULL; + + g_return_val_if_fail (ctx != NULL, -1); + g_return_val_if_fail (func != NULL, -1); + + callback = g_malloc0 (sizeof (libnm_glib_callback)); + if (!callback) + return -1; + + callback->id = ctx->callback_id_last++; + callback->func = func; + callback->ctx = g_main_ctx; + callback->user_data = user_data; + + g_mutex_lock (ctx->callbacks_lock); + ctx->callbacks = g_slist_append (ctx->callbacks, callback); + libnm_glib_schedule_single_callback (ctx, callback); + g_mutex_unlock (ctx->callbacks_lock); + + return (callback->id); +} + + +void libnm_glib_unregister_callback (libnm_glib_ctx *ctx, gint id) +{ + GSList *elem; + + g_return_if_fail (ctx != NULL); + g_return_if_fail (id < 0); + + g_mutex_lock (ctx->callbacks_lock); + elem = ctx->callbacks; + while (elem) + { + libnm_glib_callback *callback = (libnm_glib_callback *)(elem->data); + if (callback && (callback->id == id)) + { + ctx->callbacks = g_slist_remove_link (ctx->callbacks, elem); + break; + } + + elem = g_slist_next (elem); + } + g_mutex_unlock (ctx->callbacks_lock); +} diff --git a/libnm_glib/libnm_glib.h b/libnm_glib/libnm_glib.h new file mode 100644 index 0000000000..181c65ea6a --- /dev/null +++ b/libnm_glib/libnm_glib.h @@ -0,0 +1,62 @@ +/* libnm_glib -- Access NetworkManager information from applications + * + * Dan Williams + * + * 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. + * + * (C) Copyright 2005 Red Hat, Inc. + */ + +#ifndef _LIB_NM_H_ +#define _LIB_NM_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum libnm_glib_status +{ + LIBNM_NO_DBUS = 0, + LIBNM_NO_NETWORKMANAGER, + LIBNM_NO_NETWORK_CONNECTION, + LIBNM_ACTIVE_NETWORK_CONNECTION, + LIBNM_INVALID_CONTEXT +} libnm_glib_status; + +typedef struct libnm_glib_ctx libnm_glib_ctx; + +typedef struct libnm_glib_callback_data +{ + libnm_glib_ctx *libnm_ctx; + gpointer *user_data; +} libnm_glib_callback_data; + + +libnm_glib_ctx *libnm_glib_init (void); +void libnm_glib_shutdown (libnm_glib_ctx *ctx); + +libnm_glib_status libnm_glib_get_network_status (const libnm_glib_ctx *ctx); + +gint libnm_glib_register_callback (libnm_glib_ctx *ctx, GSourceFunc func, gpointer user_data, GMainContext *g_main_ctx); +void libnm_glib_callback_data_free (libnm_glib_callback_data *data); +void libnm_glib_unregister_callback (libnm_glib_ctx *ctx, gint id); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libnm_glib/libnm_glib.pc.in b/libnm_glib/libnm_glib.pc.in new file mode 100644 index 0000000000..ee37a04a86 --- /dev/null +++ b/libnm_glib/libnm_glib.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libnm_glib +Description: Client library for determining network connection properties from NetworkManager, using glib +Version: @VERSION@ +Requires: dbus-1 glib-2.0 dbus-glib-1 +Cflags: -DDBUS_API_SUBJECT_TO_CHANGE -I${includedir}/NetworkManager +Libs: -L${libdir} -lnm_glib + + diff --git a/named/Makefile.am b/named/Makefile.am index ba05b2728a..5abbb5179c 100644 --- a/named/Makefile.am +++ b/named/Makefile.am @@ -8,6 +8,6 @@ noinst_LTLIBRARIES = libnamed.la libnamed_la_SOURCES = nm-named-manager.h nm-named-manager.c -libnamed_la_CPPFLAGS = $(NM_CFLAGS) -DNM_PKGDATADIR=\"$(pkgdatadir)\" -DNM_LOCALSTATEDIR=\"$(localstatedir)\" +libnamed_la_CPPFLAGS = $(DBUS_CFLAGS) $(GTHREAD_CFLAGS) -DNM_PKGDATADIR=\"$(pkgdatadir)\" -DNM_LOCALSTATEDIR=\"$(localstatedir)\" -libnamed_la_LIBADD = $(NM_LIBS) +libnamed_la_LIBADD = $(DBUS_LIBS) $(GTHREAD_LIBS) diff --git a/panel-applet/Makefile.am b/panel-applet/Makefile.am index 3eb1426d39..46f881bbe7 100644 --- a/panel-applet/Makefile.am +++ b/panel-applet/Makefile.am @@ -5,24 +5,26 @@ NOTIFICATION_ICON_SOURCE=@NOTIFICATION_ICON_SRC@ INCLUDES = -I${top_srcdir} -AM_CPPFLAGS = \ - $(NM_CFLAGS) \ - $(GLADE_CFLAGS) \ +noinst_LTLIBRARIES = libnm_notification_applet.la + +libnm_notification_applet_la_CPPFLAGS = \ $(DBUS_CFLAGS) \ + $(GTHREAD_CFLAGS) \ + $(HAL_CFLAGS) \ $(DBUS_GLIB_CFLAGS) \ + $(GLADE_CFLAGS) \ $(GTK_CFLAGS) \ - $(GCONF_CFLAGS) \ - $(LIBGNOMEUI_CFLAGS) \ - $(PANEL_APPLET_CFLAGS) \ - -DICONDIR=\""$(datadir)/pixmaps"\" \ - -DG_DISABLE_DEPRECATED \ + $(GCONF_CFLAGS) \ + $(LIBGNOMEUI_CFLAGS) \ + $(PANEL_APPLET_CFLAGS) \ + -DICONDIR=\""$(datadir)/pixmaps"\" \ + -DDBUS_API_SUBJECT_TO_CHANGE \ + -DG_DISABLE_DEPRECATED \ -DGDK_DISABLE_DEPRECATED \ - -DGNOME_DISABLE_DEPRECATED \ + -DGNOME_DISABLE_DEPRECATED \ -DGNOMELOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ $(NULL) -noinst_LTLIBRARIES = libnm_notification_applet.la - libnm_notification_applet_la_SOURCES = \ NMWirelessApplet.c \ NMWirelessApplet.h \ @@ -43,11 +45,12 @@ libnm_notification_applet_la_SOURCES += \ eggtrayicon.h libnm_notification_applet_la_LIBADD = \ - $(NM_LIBS) \ - $(GLADE_LIBS) \ $(DBUS_LIBS) \ + $(HAL_LIBS) \ + $(GTHREAD_LIBS) \ + $(GLADE_LIBS) \ $(DBUS_GLIB_LIBS) \ - $(PANEL_APPLET_LIBS) \ + $(PANEL_APPLET_LIBS) \ $(GTK_LIBS) \ $(GCONF_LIBS) \ $(LIBGNOMEUI_LIBS) \ @@ -55,6 +58,7 @@ libnm_notification_applet_la_LIBADD = \ libexec_PROGRAMS = NetworkManagerNotification +NetworkManagerNotification_CFLAGS = $(libnm_notification_applet_la_CPPFLAGS) NetworkManagerNotification_SOURCES = main.c NetworkManagerNotification_LDADD = ./libnm_notification_applet.la diff --git a/panel-applet/NMWirelessAppletDbus.c b/panel-applet/NMWirelessAppletDbus.c index c070d787a2..790c606621 100644 --- a/panel-applet/NMWirelessAppletDbus.c +++ b/panel-applet/NMWirelessAppletDbus.c @@ -58,7 +58,7 @@ static int nmwa_dbus_call_nm_method (DBusConnection *con, const char *path, cons g_return_val_if_fail (con != NULL, RETURN_FAILURE); g_return_val_if_fail (path != NULL, RETURN_FAILURE); g_return_val_if_fail (method != NULL, RETURN_FAILURE); - g_return_val_if_fail (((arg_type == DBUS_TYPE_STRING) || (arg_type == DBUS_TYPE_INT32) || (arg_type == DBUS_TYPE_BOOLEAN) || (arg_type == DBUS_TYPE_STRING_ARRAY)), RETURN_FAILURE); + g_return_val_if_fail (((arg_type == DBUS_TYPE_STRING) || (arg_type == DBUS_TYPE_INT32) || (arg_type == DBUS_TYPE_UINT32) || (arg_type == DBUS_TYPE_BOOLEAN) || (arg_type == DBUS_TYPE_STRING_ARRAY)), RETURN_FAILURE); g_return_val_if_fail (arg != NULL, RETURN_FAILURE); if ((arg_type == DBUS_TYPE_STRING) || (arg_type == DBUS_TYPE_STRING_ARRAY)) @@ -119,6 +119,9 @@ static int nmwa_dbus_call_nm_method (DBusConnection *con, const char *path, cons case DBUS_TYPE_INT32: ret = dbus_message_get_args (reply, &error, DBUS_TYPE_INT32, &dbus_int, DBUS_TYPE_INVALID); break; + case DBUS_TYPE_UINT32: + ret = dbus_message_get_args (reply, &error, DBUS_TYPE_UINT32, &dbus_int, DBUS_TYPE_INVALID); + break; case DBUS_TYPE_BOOLEAN: ret = dbus_message_get_args (reply, &error, DBUS_TYPE_BOOLEAN, &dbus_bool, DBUS_TYPE_INVALID); break; @@ -148,6 +151,7 @@ static int nmwa_dbus_call_nm_method (DBusConnection *con, const char *path, cons *item_count = num_items; break; case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: *((int *)(arg)) = dbus_int; break; case DBUS_TYPE_BOOLEAN: @@ -334,7 +338,7 @@ static NMNetworkMode nmwa_dbus_get_object_mode (NMWirelessApplet *applet, char * { NMNetworkMode mode = NETWORK_MODE_INFRA; - switch (nmwa_dbus_call_nm_method (applet->connection, path, "getMode", DBUS_TYPE_INT32, (void **)(&mode), NULL)) + switch (nmwa_dbus_call_nm_method (applet->connection, path, "getMode", DBUS_TYPE_UINT32, (void **)(&mode), NULL)) { case (RETURN_NO_NM): applet->applet_state = APPLET_STATE_NO_NM; diff --git a/src/Makefile.am b/src/Makefile.am index 88dbd7d580..53e9236b50 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,15 +1,4 @@ -INCLUDES = -I${top_srcdir} -I../named - -AM_CPPFLAGS = \ - $(NM_CFLAGS) \ - $(OPENSSL_CFLAGS) \ - -g \ - -Wall \ - -DDBUS_API_SUBJECT_TO_CHANGE \ - -DG_DISABLE_DEPRECATED \ - -DBINDIR=\"$(bindir)\" \ - -DDATADIR=\"$(datadir)\" \ - -DARP_DEBUG +INCLUDES = -I${top_srcdir} -I${top_srcdir}/named bin_PROGRAMS = NetworkManager @@ -26,7 +15,7 @@ NetworkManager_SOURCES = \ NetworkManagerDHCP.h \ NetworkManagerDevice.c \ NetworkManagerDevice.h \ - NetworkManagerDevicePrivate.h \ + NetworkManagerDevicePrivate.h \ NetworkManager.c \ NetworkManagerMain.h \ NetworkManagerPolicy.c \ @@ -39,11 +28,25 @@ NetworkManager_SOURCES = \ NetworkManagerSystem.h \ autoip.c +NetworkManager_CPPFLAGS = \ + $(DBUS_CFLAGS) \ + $(GTHREAD_CFLAGS) \ + $(HAL_CFLAGS) \ + $(OPENSSL_CFLAGS) \ + -g \ + -Wall \ + -DDBUS_API_SUBJECT_TO_CHANGE \ + -DG_DISABLE_DEPRECATED \ + -DBINDIR=\"$(bindir)\" \ + -DDATADIR=\"$(datadir)\" \ + -DARP_DEBUG + + if !WITH_GCRYPT NetworkManager_SOURCES += gnome-keyring-md5.c gnome-keyring-md5.h endif -NetworkManager_LDADD = $(NM_LIBS) $(IWLIB) libnmbackend.la ../dhcpcd/libdhcpc.a ../named/libnamed.la +NetworkManager_LDADD = $(DBUS_LIBS) $(GTHREAD_LIBS) $(HAL_LIBS) $(IWLIB) libnmbackend.la ../dhcpcd/libdhcpc.a ../named/libnamed.la if WITH_GCRYPT NetworkManager_LDADD += $(LIBGCRYPT_LIBS) endif @@ -67,8 +70,8 @@ if TARGET_SLACKWARE libnmbackend_la_SOURCES += backends/NetworkManagerSlackware.c endif -libnmbackend_la_LIBADD = $(NM_LIBS) -libnmbackend_la_CPPFLAGS = $(NM_CFLAGS) +libnmbackend_la_LIBADD = $(DBUS_LIBS) $(GTHREAD_LIBS) +libnmbackend_la_CFLAGS = $(NetworkManager_CPPFLAGS) dbusservicedir = $(DBUS_SYS_DIR) dbusservice_DATA = NetworkManager.conf diff --git a/src/NetworkManager.c b/src/NetworkManager.c index bc4f0ec184..a123164212 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -394,6 +394,39 @@ static void nm_add_initial_devices (NMData *data) } +/* + * nm_status_signal_broadcast + * + */ +static gboolean nm_status_signal_broadcast (gpointer user_data) +{ + NMData *data = (NMData *)user_data; + + g_return_val_if_fail (data != NULL, FALSE); + + nm_dbus_signal_network_status_change (data->dbus_connection, data); + return FALSE; +} + + +/* + * nm_schedule_status_signal_broadcast + * + */ +void nm_schedule_status_signal_broadcast (NMData *data) +{ + guint id = 0; + GSource *source; + + g_return_if_fail (data != NULL); + + source = g_idle_source_new (); + g_source_set_callback (source, nm_status_signal_broadcast, data, NULL); + id = g_source_attach (source, data->main_context); + g_source_unref (source); +} + + /* * nm_link_state_monitor * diff --git a/src/NetworkManagerAPList.c b/src/NetworkManagerAPList.c index 42cb00fa60..31f2365f7f 100644 --- a/src/NetworkManagerAPList.c +++ b/src/NetworkManagerAPList.c @@ -300,7 +300,6 @@ void nm_ap_list_update_network (NMAccessPointList *list, const char *network, NM { NMAccessPoint *ap = NULL; NMAccessPoint *list_ap = NULL; - char *essid = NULL; g_return_if_fail (list != NULL); g_return_if_fail (network != NULL); diff --git a/src/NetworkManagerDbus.c b/src/NetworkManagerDbus.c index 1781e5f7a6..b8901386af 100644 --- a/src/NetworkManagerDbus.c +++ b/src/NetworkManagerDbus.c @@ -1152,7 +1152,7 @@ static DBusMessage *nm_dbus_devices_handle_networks_request (DBusConnection *con else if (strcmp ("getEncrypted", request) == 0) dbus_message_append_args (reply_message, DBUS_TYPE_BOOLEAN, nm_ap_get_encrypted (ap), DBUS_TYPE_INVALID); else if (strcmp ("getMode", request) == 0) - dbus_message_append_args (reply_message, DBUS_TYPE_INT32, nm_ap_get_mode (ap), DBUS_TYPE_INVALID); + dbus_message_append_args (reply_message, DBUS_TYPE_UINT32, nm_ap_get_mode (ap), DBUS_TYPE_INVALID); else { /* Must destroy the allocated message */ diff --git a/src/NetworkManagerMain.h b/src/NetworkManagerMain.h index 0e5e70a3db..d4ba63a1bf 100644 --- a/src/NetworkManagerMain.h +++ b/src/NetworkManagerMain.h @@ -70,11 +70,13 @@ typedef struct NMData } NMData; -struct NMDevice *nm_create_device_and_add_to_list (NMData *data, const char *udi, const char *iface, - gboolean test_device, NMDeviceType test_device_type); +struct NMDevice *nm_create_device_and_add_to_list (NMData *data, const char *udi, const char *iface, + gboolean test_device, NMDeviceType test_device_type); -void nm_remove_device_from_list (NMData *data, const char *udi); +void nm_remove_device_from_list (NMData *data, const char *udi); -void nm_data_mark_state_changed (NMData *data); +void nm_data_mark_state_changed (NMData *data); + +void nm_schedule_status_signal_broadcast (NMData *data); #endif diff --git a/test/Makefile.am b/test/Makefile.am index be95e8f3b3..bf9342f8c1 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,18 +1,23 @@ -INCLUDES = -I${top_srcdir} +INCLUDES = -I${top_srcdir} -I${top_srcdir}/libnm_glib AM_CPPFLAGS = \ - $(NM_CFLAGS) \ + $(DBUS_CFLAGS) \ + $(GTHREAD_CFLAGS) \ + $(HAL_CFLAGS) \ -DDBUS_API_SUBJECT_TO_CHANGE \ -DBINDIR=\"$(bindir)\" \ -DDATADIR=\"$(datadir)\" -noinst_PROGRAMS = nmtest nminfotest nmtestdevices +noinst_PROGRAMS = nmtest nminfotest nmtestdevices libnm_glib_test nmtest_SOURCES = nmclienttest.c -nmtest_LDADD = $(NM_LIBS) +nmtest_LDADD = $(DBUS_LIBS) $(GTHREAD_LIBS) $(HAL_LIBS) nminfotest_SOURCES = nminfotest.c -nminfotest_LDADD = $(NM_LIBS) +nminfotest_LDADD = $(DBUS_LIBS) $(GTHREAD_LIBS) nmtestdevices_SOURCES = nmtestdevices.c -nmtestdevices_LDADD = $(NM_LIBS) +nmtestdevices_LDADD = $(DBUS_LIBS) $(GTHREAD_LIBS) + +libnm_glib_test_SOURCES = libnm_glib_test.c +libnm_glib_test_LDADD = $(DBUS_LIBS) $(GTHREAD_LIBS) -lnm_glib diff --git a/test/libnm_glib_test.c b/test/libnm_glib_test.c new file mode 100644 index 0000000000..fa3c7eecf6 --- /dev/null +++ b/test/libnm_glib_test.c @@ -0,0 +1,86 @@ +/* libnm_glib_test - test app for libnm_glib + * + * Dan Williams + * + * 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. + * + * (C) Copyright 2005 Red Hat, Inc. + */ + +#include +#include +#include +#include +#include "libnm_glib.h" + + +gboolean status_printer (gpointer user_data) +{ + libnm_glib_callback_data *data = (libnm_glib_callback_data *)user_data; + libnm_glib_status status; + + g_return_val_if_fail (data != NULL, FALSE); + g_return_val_if_fail (data->libnm_ctx != NULL, FALSE); + + status = libnm_glib_get_network_status (data->libnm_ctx); + switch (status) + { + case LIBNM_NO_DBUS: + fprintf (stderr, "Status: No DBUS\n"); + break; + case LIBNM_NO_NETWORKMANAGER: + fprintf (stderr, "Status: No NetworkManager\n"); + break; + case LIBNM_NO_NETWORK_CONNECTION: + fprintf (stderr, "Status: No Connection\n"); + break; + case LIBNM_ACTIVE_NETWORK_CONNECTION: + fprintf (stderr, "Status: Active Connection\n"); + break; + case LIBNM_INVALID_CONTEXT: + fprintf (stderr, "Status: Error\n"); + break; + default: + fprintf (stderr, "Status: unknown\n"); + break; + } + + return FALSE; +} + + +int main( int argc, char *argv[] ) +{ + GMainLoop *loop; + libnm_glib_ctx *ctx; + guint id; + + ctx = libnm_glib_init (); + if (!ctx) + { + fprintf (stderr, "Could not initialize libnm.\n"); + exit (1); + } + libnm_glib_register_callback (ctx, status_printer, ctx, NULL); + + loop = g_main_loop_new (NULL, FALSE); +// id = g_timeout_add (2000, status_printer, (gpointer)ctx); + + g_main_loop_run (loop); + +// g_source_remove (id); + + exit (0); +}