summaryrefslogtreecommitdiff
path: root/libnm-glib/libnm_glib.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-glib/libnm_glib.c')
-rw-r--r--libnm-glib/libnm_glib.c580
1 files changed, 0 insertions, 580 deletions
diff --git a/libnm-glib/libnm_glib.c b/libnm-glib/libnm_glib.c
deleted file mode 100644
index 1e0725ca1d..0000000000
--- a/libnm-glib/libnm_glib.c
+++ /dev/null
@@ -1,580 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/*
- * libnm_glib -- Access network status & information from glib applications
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * Copyright (C) 2005 - 2008 Red Hat, Inc.
- * Copyright (C) 2005 - 2008 Novell, Inc.
- */
-
-#include "nm-default.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib-lowlevel.h>
-
-#include "NetworkManager.h"
-#include "libnm_glib.h"
-
-#define DBUS_NO_SERVICE_ERROR "org.freedesktop.DBus.Error.ServiceDoesNotExist"
-
-struct libnm_glib_ctx
-{
- unsigned char check;
-
- GMainContext * g_main_ctx;
- GMainLoop * g_main_loop;
- DBusConnection * dbus_con;
- guint dbus_watcher;
- guint dbus_watch_interval;
-
- gboolean thread_done;
- gboolean thread_inited;
- GThread * thread;
-
- GSList * callbacks;
- GMutex * callbacks_lock;
- guint callback_id_last;
-
- libnm_glib_state nm_state;
-};
-
-typedef struct libnm_glib_callback
-{
- guint id;
- GMainContext * gmain_ctx;
- libnm_glib_ctx * libnm_glib_ctx;
- libnm_glib_callback_func func;
- gpointer user_data;
-} libnm_glib_callback;
-
-static void _libnm_glib_schedule_dbus_watcher (libnm_glib_ctx *ctx);
-static DBusConnection * _libnm_glib_dbus_init (gpointer *user_data, GMainContext *context);
-static void _libnm_glib_update_state (libnm_glib_ctx *ctx, NMState state);
-
-static void
-_libnm_glib_nm_state_cb (DBusPendingCall *pcall, void *user_data)
-{
- DBusMessage *reply;
- libnm_glib_ctx *ctx = (libnm_glib_ctx *) user_data;
- NMState nm_state;
-
- g_return_if_fail (pcall != NULL);
- g_return_if_fail (ctx != NULL);
-
- if (!(reply = dbus_pending_call_steal_reply (pcall)))
- goto out;
-
- if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
- {
- DBusError err;
-
- dbus_error_init (&err);
- dbus_set_error_from_message (&err, reply);
- fprintf (stderr, "%s: dbus returned an error.\n (%s) %s\n", __func__, err.name, err.message);
- dbus_error_free (&err);
- dbus_message_unref (reply);
- goto out;
- }
-
- if (dbus_message_get_args (reply, NULL, DBUS_TYPE_UINT32, &nm_state, DBUS_TYPE_INVALID))
- _libnm_glib_update_state (ctx, nm_state);
-
- dbus_message_unref (reply);
-
-out:
- dbus_pending_call_unref (pcall);
-}
-
-static void
-_libnm_glib_get_nm_state (libnm_glib_ctx *ctx)
-{
- DBusMessage *message;
- DBusPendingCall *pcall = NULL;
-
- g_return_if_fail (ctx != NULL);
-
- if ((message = dbus_message_new_method_call (NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, "state")))
- {
- dbus_connection_send_with_reply (ctx->dbus_con, message, &pcall, -1);
- if (pcall)
- dbus_pending_call_set_notify (pcall, _libnm_glib_nm_state_cb, ctx, NULL);
- dbus_message_unref (message);
- }
-}
-
-static gboolean
-_libnm_glib_callback_helper (gpointer user_data)
-{
- libnm_glib_callback *cb_data = (libnm_glib_callback *)user_data;
-
- g_return_val_if_fail (cb_data != NULL, FALSE);
- g_return_val_if_fail (cb_data->func != NULL, FALSE);
- g_return_val_if_fail (cb_data->libnm_glib_ctx != NULL, FALSE);
-
- (*(cb_data->func)) (cb_data->libnm_glib_ctx, cb_data->user_data);
-
- return FALSE;
-}
-
-static void
-_libnm_glib_schedule_single_callback (libnm_glib_ctx *ctx,
- libnm_glib_callback *callback)
-{
- GSource *source;
-
- g_return_if_fail (ctx != NULL);
- g_return_if_fail (callback != NULL);
-
- callback->libnm_glib_ctx = ctx;
-
- source = g_idle_source_new ();
- g_source_set_callback (source, _libnm_glib_callback_helper, callback, NULL);
- g_source_attach (source, callback->gmain_ctx);
- g_source_unref (source);
-}
-
-static void
-_libnm_glib_unschedule_single_callback (libnm_glib_ctx *ctx,
- libnm_glib_callback *callback)
-{
- GSource *source;
-
- g_return_if_fail (ctx != NULL);
- g_return_if_fail (callback != NULL);
-
- source = g_main_context_find_source_by_user_data (callback->gmain_ctx, callback);
- if (source)
- g_source_destroy (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);
- for (elem = ctx->callbacks; elem; elem = g_slist_next (elem))
- {
- libnm_glib_callback *callback = (libnm_glib_callback *)(elem->data);
- if (callback)
- _libnm_glib_schedule_single_callback (ctx, callback);
- }
- g_mutex_unlock (ctx->callbacks_lock);
-}
-
-static void
-_libnm_glib_update_state (libnm_glib_ctx *ctx, NMState state)
-{
- libnm_glib_state old_state;
-
- g_return_if_fail (ctx != NULL);
-
- old_state = ctx->nm_state;
- switch (state) {
- case NM_STATE_CONNECTED_LOCAL:
- case NM_STATE_CONNECTED_SITE:
- case NM_STATE_CONNECTED_GLOBAL:
- ctx->nm_state = LIBNM_ACTIVE_NETWORK_CONNECTION;
- break;
- case NM_STATE_ASLEEP:
- case NM_STATE_CONNECTING:
- case NM_STATE_DISCONNECTED:
- case NM_STATE_DISCONNECTING:
- ctx->nm_state = LIBNM_NO_NETWORK_CONNECTION;
- break;
- case NM_STATE_UNKNOWN:
- default:
- ctx->nm_state = LIBNM_NO_NETWORKMANAGER;
- break;
- }
-
- if (old_state != ctx->nm_state)
- _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_LOCAL, "Disconnected"))
- {
- /* Try to reactivate our connection to dbus on the next pass through the event loop */
- ctx->nm_state = LIBNM_NO_DBUS;
- dbus_connection_close (ctx->dbus_con);
- dbus_connection_unref (ctx->dbus_con);
- ctx->dbus_con = NULL;
- _libnm_glib_schedule_dbus_watcher (ctx);
- }
- else if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged"))
- {
- /* New signal for dbus 0.23... */
- char *service;
- char *old_owner;
- char *new_owner;
-
- if ( dbus_message_get_args (message, &error,
- DBUS_TYPE_STRING, &service,
- DBUS_TYPE_STRING, &old_owner,
- DBUS_TYPE_STRING, &new_owner,
- DBUS_TYPE_INVALID))
- {
- if (strcmp (service, NM_DBUS_SERVICE) == 0)
- {
- gboolean old_owner_good = (old_owner && (strlen (old_owner) > 0));
- gboolean new_owner_good = (new_owner && (strlen (new_owner) > 0));
-
- if (!old_owner_good && new_owner_good) /* Equivalent to old ServiceCreated signal */
- _libnm_glib_get_nm_state (ctx);
- else if (old_owner_good && !new_owner_good) /* Equivalent to old ServiceDeleted signal */
- ctx->nm_state = 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"))
- {
- _libnm_glib_get_nm_state (ctx);
- }
- else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, "StateChanged"))
- {
- NMState state = NM_STATE_UNKNOWN;
-
- dbus_message_get_args (message, &error, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID);
- _libnm_glib_update_state (ctx, state);
- }
- 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_private (DBUS_BUS_SYSTEM, &error);
- if (dbus_error_is_set (&error))
- {
- fprintf (stderr, "%s: error, %s raised:\n %s\n\n", __func__, 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_DBUS "',"
- "sender='" DBUS_SERVICE_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);
-
- ctx->dbus_watcher = 0;
-
- if (!ctx->dbus_con)
- ctx->dbus_con = _libnm_glib_dbus_init ((gpointer)ctx, ctx->g_main_ctx);
-
- if (ctx->dbus_con)
- {
- /* Get NM's state right away after we reconnect */
- _libnm_glib_get_nm_state (ctx);
- ctx->dbus_watch_interval = 1000;
- }
- else
- {
- /* Wait 3 seconds longer each time we fail to reconnect to dbus,
- * with a maximum wait of one minute.
- */
- ctx->dbus_watch_interval = MIN(ctx->dbus_watch_interval + 3000, 60000);
-
- /* Reschule ourselves if we _still_ don't have a connection to dbus */
- _libnm_glib_schedule_dbus_watcher (ctx);
- }
-
- return FALSE;
-}
-
-/*
- * 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_timeout_source_new (ctx->dbus_watch_interval);
- 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_dbus_init ((gpointer) ctx, ctx->g_main_ctx)))
- _libnm_glib_schedule_dbus_watcher (ctx);
- else
- _libnm_glib_get_nm_state (ctx);
-
- 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, "%s: context %p already freed!\n", __func__, 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_close (ctx->dbus_con);
- dbus_connection_unref (ctx->dbus_con);
- ctx->dbus_con = NULL;
- }
-
- if (ctx->callbacks_lock)
- g_mutex_free (ctx->callbacks_lock);
-
- g_slist_free_full (ctx->callbacks, g_free);
-
- if (ctx->thread)
- g_thread_join (ctx->thread);
-
- 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->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;
- ctx->dbus_watch_interval = 1000;
-
- return ctx;
-
-error:
- _libnm_glib_ctx_free (ctx);
- return NULL;
-}
-
-libnm_glib_ctx *
-libnm_glib_init (void)
-{
- libnm_glib_ctx *ctx = NULL;
-
- if (!g_thread_supported ())
- g_thread_init (NULL);
- dbus_g_thread_init ();
-
- if (!(ctx = _libnm_glib_ctx_new ()))
- return NULL;
-
- ctx->thread = g_thread_create (_libnm_glib_dbus_worker, ctx, TRUE, NULL);
- if (!ctx->thread)
- goto error;
-
- /* Wait until initialization of the thread */
- while (!ctx->thread_inited)
- g_usleep (G_USEC_PER_SEC / 20);
-
- 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 / 20);
-
- _libnm_glib_ctx_free (ctx);
-}
-
-libnm_glib_state
-libnm_glib_get_network_state (const libnm_glib_ctx *ctx)
-{
- if (!ctx)
- return LIBNM_INVALID_CONTEXT;
-
- return ctx->nm_state;
-}
-
-guint
-libnm_glib_register_callback (libnm_glib_ctx *ctx,
- libnm_glib_callback_func func,
- gpointer user_data,
- GMainContext *g_main_ctx)
-{
- libnm_glib_callback *callback = NULL;
-
- g_return_val_if_fail (ctx != NULL, 0);
- g_return_val_if_fail (func != NULL, 0);
-
- callback = g_malloc0 (sizeof (libnm_glib_callback));
-
- callback->id = ++ (ctx->callback_id_last);
- callback->func = func;
- callback->gmain_ctx = g_main_ctx;
- callback->libnm_glib_ctx = 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,
- guint 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))
- {
- _libnm_glib_unschedule_single_callback (ctx, callback);
- ctx->callbacks = g_slist_remove_link (ctx->callbacks, elem);
- break;
- }
-
- elem = g_slist_next (elem);
- }
- g_mutex_unlock (ctx->callbacks_lock);
-}