2006-10-13 Dan Williams <dcbw@redhat.com>

* Huge DBus refactor:
		- Create a "DBus Manager" object which manages the connection and
		sends signals on NameOwnerChanged and connection/disconnection events,
		handles reconnection to the bus if NM gets kicked off, and abstracts
		signal handling
		- Remove DBusConnection members from places where they are no
		longer needed due to the refactor, like the dbus-connection
		property of the named manager, and from NMData
		- Reformats a bunch of the code to gnome style
		(8-space tabs, braces on same line as statement, 80-col width).
		Consider it open season to reformat any bits to gnome style.
		style that aren't already.


git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2061 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Dan Williams
2006-10-13 19:41:47 +00:00
parent 129d0ca46d
commit 84678fc9fe
38 changed files with 4569 additions and 2771 deletions

View File

@@ -52,6 +52,10 @@
#include "nm-named-manager.h"
#include "nm-vpn-act-request.h"
#include "nm-dbus-vpn.h"
#include "nm-dbus-nm.h"
#include "nm-dbus-manager.h"
#include "nm-dbus-device.h"
#include "nm-dbus-net.h"
#include "nm-netlink-monitor.h"
#include "nm-dhcp-manager.h"
#include "nm-logging.h"
@@ -60,6 +64,8 @@
#define NM_DEFAULT_PID_FILE LOCALSTATEDIR"/run/NetworkManager.pid"
#define NO_HAL_MSG "Could not initialize connection to the HAL daemon."
/*
* Globals
*/
@@ -67,6 +73,7 @@ static NMData *nm_data = NULL;
static gboolean sigterm_pipe_handler (GIOChannel *src, GIOCondition condition, gpointer data);
static void nm_data_free (NMData *data);
static void nm_hal_deinit (NMData *data);
/*
* nm_get_device_interface_from_hal
@@ -208,21 +215,6 @@ NMDevice *nm_get_active_device (NMData *data)
}
/* Hal doesn't really give us any way to pass a GMainContext to our
* mainloop integration function unfortunately. So we have to use
* a global.
*/
GMainContext *main_context = NULL;
/*
* nm_hal_mainloop_integration
*
*/
static void nm_hal_mainloop_integration (LibHalContext *ctx, DBusConnection * dbus_connection)
{
dbus_connection_setup_with_g_main (dbus_connection, main_context);
}
/*
* nm_hal_device_added
*
@@ -348,10 +340,16 @@ void nm_add_initial_devices (NMData *data)
static gboolean nm_state_change_signal_broadcast (gpointer user_data)
{
NMData *data = (NMData *)user_data;
NMDBusManager *dbus_mgr = NULL;
DBusConnection *dbus_connection = NULL;
g_return_val_if_fail (data != NULL, FALSE);
nm_dbus_signal_state_change (data->dbus_connection, data);
dbus_mgr = nm_dbus_manager_get (NULL);
dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr);
if (dbus_connection)
nm_dbus_signal_state_change (dbus_connection, data);
g_object_unref (dbus_mgr);
return FALSE;
}
@@ -413,6 +411,87 @@ nm_monitor_setup (NMData *data)
return monitor;
}
static gboolean
nm_hal_init (NMData *data,
DBusConnection *connection)
{
gboolean success = FALSE;
DBusError error;
g_return_val_if_fail (data != NULL, FALSE);
g_return_val_if_fail (connection != NULL, FALSE);
/* Clean up an old context */
if (data->hal_ctx) {
nm_warning ("a HAL context already existed. BUG.");
nm_hal_deinit (data);
}
/* Initialize a new libhal context */
if (!(data->hal_ctx = libhal_ctx_new ())) {
nm_warning ("Could not get connection to the HAL service.");
goto out;
}
libhal_ctx_set_dbus_connection (data->hal_ctx, connection);
dbus_error_init (&error);
if (!libhal_ctx_init (data->hal_ctx, &error)) {
nm_error ("libhal_ctx_init() failed: %s\n"
"Make sure the hal daemon is running?",
error.message);
goto out;
}
libhal_ctx_set_user_data (data->hal_ctx, data->main_context);
libhal_ctx_set_device_added (data->hal_ctx, nm_hal_device_added);
libhal_ctx_set_device_removed (data->hal_ctx, nm_hal_device_removed);
libhal_ctx_set_device_new_capability (data->hal_ctx, nm_hal_device_new_capability);
libhal_device_property_watch_all (data->hal_ctx, &error);
if (dbus_error_is_set (&error)) {
nm_error ("libhal_device_property_watch_all(): %s", error.message);
libhal_ctx_shutdown (data->hal_ctx, NULL);
goto out;
}
/* Add any devices we know about */
nm_add_initial_devices (data);
success = TRUE;
out:
if (!success) {
if (dbus_error_is_set (&error))
dbus_error_free (&error);
if (data->hal_ctx) {
libhal_ctx_free (data->hal_ctx);
data->hal_ctx = NULL;
}
}
return success;
}
static void
nm_hal_deinit (NMData *data)
{
DBusError error;
g_return_if_fail (data != NULL);
if (!data->hal_ctx)
return;
dbus_error_init (&error);
libhal_ctx_shutdown (data->hal_ctx, &error);
if (dbus_error_is_set (&error)) {
nm_warning ("libhal shutdown failed - %s", error.message);
dbus_error_free (&error);
}
libhal_ctx_free (data->hal_ctx);
data->hal_ctx = NULL;
}
/*
* nm_data_new
@@ -524,6 +603,9 @@ static void nm_data_free (NMData *data)
nm_ap_list_unref (data->allowed_ap_list);
nm_ap_list_unref (data->invalid_ap_list);
nm_dbus_method_list_unref (data->nm_methods);
nm_dbus_method_list_unref (data->device_methods);
nm_vpn_manager_dispose (data->vpn_manager);
nm_dhcp_manager_dispose (data->dhcp_manager);
g_object_unref (data->named_manager);
@@ -552,81 +634,55 @@ static gboolean sigterm_pipe_handler (GIOChannel *src, GIOCondition condition, g
return FALSE;
}
static LibHalContext *nm_get_hal_ctx (NMData *data)
static void
nm_name_owner_changed_handler (NMDBusManager *mgr,
DBusConnection *connection,
const char *name,
const char *old,
const char *new,
gpointer user_data)
{
LibHalContext * ctx = NULL;
DBusError error;
NMData * data = (NMData *) user_data;
gboolean old_owner_good = (old && (strlen (old) > 0));
gboolean new_owner_good = (new && (strlen (new) > 0));
g_return_val_if_fail (data != NULL, NULL);
/* Only care about signals from HAL */
if (strcmp (name, "org.freedesktop.Hal") != 0)
return;
/* Initialize libhal. We get a connection to the hal daemon here. */
if ((ctx = libhal_ctx_new()) == NULL)
{
nm_error ("libhal_ctx_new() failed, exiting...");
return NULL;
}
nm_hal_mainloop_integration (ctx, data->dbus_connection);
libhal_ctx_set_dbus_connection (ctx, data->dbus_connection);
dbus_error_init (&error);
if(!libhal_ctx_init (ctx, &error))
{
nm_error ("libhal_ctx_init() failed: %s\n"
"Make sure the hal daemon is running?",
error.message);
dbus_error_free (&error);
libhal_ctx_free (ctx);
return NULL;
}
libhal_ctx_set_user_data (ctx, data);
libhal_ctx_set_device_added (ctx, nm_hal_device_added);
libhal_ctx_set_device_removed (ctx, nm_hal_device_removed);
libhal_ctx_set_device_new_capability (ctx, nm_hal_device_new_capability);
dbus_error_init (&error);
libhal_device_property_watch_all (ctx, &error);
if (dbus_error_is_set (&error))
{
nm_error ("libhal_device_property_watch_all(): %s", error.message);
dbus_error_free (&error);
libhal_ctx_free (ctx);
}
return ctx;
}
void nm_hal_init (NMData *data)
{
g_return_if_fail (data != NULL);
if ((data->hal_ctx = nm_get_hal_ctx (data)))
nm_add_initial_devices (data);
}
void nm_hal_deinit (NMData *data)
{
g_return_if_fail (data != NULL);
if (data->hal_ctx)
{
DBusError error;
dbus_error_init (&error);
libhal_ctx_shutdown (data->hal_ctx, &error);
if (dbus_error_is_set (&error))
{
nm_warning ("libhal shutdown failed - %s", error.message);
dbus_error_free (&error);
if (!old_owner_good && new_owner_good) {
/* HAL just appeared */
if (!nm_hal_init (data, connection)) {
nm_error (NO_HAL_MSG);
exit (EXIT_FAILURE);
}
libhal_ctx_free (data->hal_ctx);
data->hal_ctx = NULL;
} else if (old_owner_good && !new_owner_good) {
/* HAL went away. Bad HAL. */
nm_hal_deinit (data);
}
}
static void
nm_dbus_connection_changed_handler (NMDBusManager *mgr,
DBusConnection *connection,
gpointer user_data)
{
NMData *data = (NMData *) user_data;
char * owner;
if (!connection) {
nm_hal_deinit (data);
return;
}
if ((owner = nm_dbus_manager_get_name_owner (mgr, "org.freedesktop.Hal"))) {
if (!nm_hal_init (data, connection)) {
nm_error (NO_HAL_MSG);
exit (EXIT_FAILURE);
}
g_free (owner);
}
}
static void
write_pidfile (const char *pidfile)
@@ -669,19 +725,30 @@ static void nm_print_usage (void)
* main
*
*/
int main( int argc, char *argv[] )
int
main (int argc, char *argv[])
{
GOptionContext *opt_ctx = NULL;
gboolean become_daemon = FALSE;
gboolean enable_test_devices = FALSE;
gboolean show_usage = FALSE;
char * owner;
char * pidfile = NULL;
char * user_pidfile = NULL;
if (getuid () != 0)
{
NMDBusManager * dbus_mgr;
DBusConnection *dbus_connection;
int exit_status = EXIT_FAILURE;
GOptionEntry options[] = {
{"no-daemon", 0, 0, G_OPTION_ARG_NONE, &become_daemon, "Don't become a daemon", NULL},
{"pid-file", 0, 0, G_OPTION_ARG_STRING, &user_pidfile, "Specify the location of a PID file", NULL},
{"enable-test-devices", 0, 0, G_OPTION_ARG_NONE, &enable_test_devices, "Allow dummy devices to be created via DBUS methods [DEBUG]", NULL},
{"info", 0, 0, G_OPTION_ARG_NONE, &show_usage, "Show application information", NULL},
{NULL}
};
if (getuid () != 0) {
g_printerr ("You must be root to run NetworkManager!\n");
return (EXIT_FAILURE);
goto exit;
}
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
@@ -689,43 +756,33 @@ int main( int argc, char *argv[] )
textdomain (GETTEXT_PACKAGE);
/* Parse options */
{
GOptionContext *opt_ctx = NULL;
GOptionEntry options[] = {
{"no-daemon", 0, 0, G_OPTION_ARG_NONE, &become_daemon, "Don't become a daemon", NULL},
{"pid-file", 0, 0, G_OPTION_ARG_STRING, &user_pidfile, "Specify the location of a PID file", NULL},
{"enable-test-devices", 0, 0, G_OPTION_ARG_NONE, &enable_test_devices, "Allow dummy devices to be created via DBUS methods [DEBUG]", NULL},
{"info", 0, 0, G_OPTION_ARG_NONE, &show_usage, "Show application information", NULL},
{NULL}
};
opt_ctx = g_option_context_new("");
g_option_context_add_main_entries(opt_ctx, options, NULL);
g_option_context_parse(opt_ctx, &argc, &argv, NULL);
g_option_context_free(opt_ctx);
}
opt_ctx = g_option_context_new("");
g_option_context_add_main_entries(opt_ctx, options, NULL);
g_option_context_parse(opt_ctx, &argc, &argv, NULL);
g_option_context_free(opt_ctx);
/* Tricky: become_daemon is FALSE by default, so unless it's TRUE because of a CLI
* option, it'll become TRUE after this */
become_daemon = !become_daemon;
if (show_usage == TRUE)
{
if (show_usage == TRUE) {
nm_print_usage();
exit (EXIT_SUCCESS);
exit_status = EXIT_SUCCESS;
goto exit;
}
if (become_daemon)
{
if (daemon (0, 0) < 0)
{
pidfile = g_strdup (user_pidfile ? user_pidfile : NM_DEFAULT_PID_FILE);
/* Tricky: become_daemon is FALSE by default, so unless it's TRUE because
* of a CLI option, it'll become TRUE after this
*/
become_daemon = !become_daemon;
if (become_daemon) {
if (daemon (0, 0) < 0) {
int saved_errno;
saved_errno = errno;
nm_error ("NetworkManager could not daemonize: %s [error %u]",
g_strerror (saved_errno), saved_errno);
exit (EXIT_FAILURE);
nm_error ("Could not daemonize: %s [error %u]",
g_strerror (saved_errno),
saved_errno);
goto exit;
}
pidfile = user_pidfile ? user_pidfile : NM_DEFAULT_PID_FILE;
write_pidfile (pidfile);
}
@@ -748,46 +805,76 @@ int main( int argc, char *argv[] )
/* Initialize our instance data */
nm_data = nm_data_new (enable_test_devices);
if (!nm_data)
{
nm_error ("nm_data_new() failed... Not enough memory?");
exit (EXIT_FAILURE);
if (!nm_data) {
nm_error ("Failed to initialize.");
goto pidfile;
}
/* Create our dbus service */
nm_data->dbus_connection = nm_dbus_init (nm_data);
if (!nm_data->dbus_connection)
{
nm_error ("nm_dbus_init() failed, exiting. "
"Either dbus is not running, or the "
"NetworkManager dbus security policy "
"was not loaded.");
exit (EXIT_FAILURE);
/* Initialize our DBus service & connection */
dbus_mgr = nm_dbus_manager_get (nm_data->main_context);
dbus_connection = nm_dbus_manager_get_dbus_connection (dbus_mgr);
if (!dbus_connection) {
nm_error ("Failed to initialize. "
"Either dbus is not running, or the "
"NetworkManager dbus security policy "
"was not loaded.");
goto done;
}
g_signal_connect (G_OBJECT (dbus_mgr), "name-owner-changed",
G_CALLBACK (nm_name_owner_changed_handler), nm_data);
g_signal_connect (G_OBJECT (dbus_mgr), "dbus-connection-changed",
G_CALLBACK (nm_dbus_connection_changed_handler), nm_data);
nm_dbus_manager_register_signal_handler (dbus_mgr,
NMI_DBUS_INTERFACE,
NULL,
nm_dbus_nmi_signal_handler,
nm_data);
/* Register DBus method handlers for the main NM objects */
nm_data->nm_methods = nm_dbus_nm_methods_setup (nm_data);
nm_dbus_manager_register_method_list (dbus_mgr, nm_data->nm_methods);
nm_data->device_methods = nm_dbus_device_methods_setup (nm_data);
nm_dbus_manager_register_method_list (dbus_mgr, nm_data->device_methods);
nm_data->net_methods = nm_dbus_net_methods_setup (nm_data);
/* Need to happen after DBUS is initialized */
nm_data->vpn_manager = nm_vpn_manager_new (nm_data);
nm_data->dhcp_manager = nm_dhcp_manager_new (nm_data);
nm_data->named_manager = nm_named_manager_new (nm_data->dbus_connection);
if (!nm_data->vpn_manager) {
nm_warning ("Failed to start the VPN manager.");
goto done;
}
nm_data->dhcp_manager = nm_dhcp_manager_new (nm_data, nm_data->main_context);
if (!nm_data->dhcp_manager) {
nm_warning ("Failed to start the DHCP manager.");
goto done;
}
nm_data->named_manager = nm_named_manager_new ();
if (!nm_data->named_manager) {
nm_warning ("Failed to start the named manager.");
goto done;
}
/* Start our DBus service */
if (!nm_dbus_manager_start_service (dbus_mgr)) {
nm_warning ("Failed to start the named manager.");
goto done;
}
/* If Hal is around, grab a device list from it */
if (nm_dbus_manager_name_has_owner (dbus_mgr, "org.freedesktop.Hal")) {
if (!nm_hal_init (nm_data, dbus_connection)) {
nm_error (NO_HAL_MSG);
goto done;
}
}
/* If NMI is running, grab allowed wireless network lists from it ASAP */
if (nm_dbus_is_info_daemon_running (nm_data->dbus_connection))
{
if (nm_dbus_manager_name_has_owner (dbus_mgr, NMI_DBUS_SERVICE)) {
nm_policy_schedule_allowed_ap_list_update (nm_data);
nm_dbus_vpn_schedule_vpn_connections_update (nm_data);
}
/* Right before we init hal, we have to make sure our mainloop
* integration function knows about our GMainContext. HAL doesn't give
* us any way to pass that into its mainloop integration callback, so
* its got to be a global.
*/
main_context = nm_data->main_context;
/* If Hal is around, grab a device list from it */
if ((owner = get_name_owner (nm_data->dbus_connection, "org.freedesktop.Hal")))
nm_hal_init (nm_data);
/* We run dhclient when we need to, and we don't want any stray ones
* lying around upon launch.
*/
@@ -802,16 +889,23 @@ int main( int argc, char *argv[] )
/* Run the main loop */
nm_policy_schedule_device_change_check (nm_data);
nm_schedule_state_change_signal_broadcast (nm_data);
exit_status = EXIT_SUCCESS;
g_main_loop_run (nm_data->main_loop);
done:
nm_print_open_socks ();
nm_data_free (nm_data);
/* nm_data_free needs the dbus connection, so must kill the
* dbus manager after that.
*/
g_object_unref (dbus_mgr);
nm_logging_shutdown ();
/* Clean up pidfile */
pidfile:
if (pidfile)
unlink (pidfile);
g_free (user_pidfile);
g_free (pidfile);
exit (0);
exit:
exit (exit_status);
}