Files
NetworkManager/gnome/applet/applet-dbus.c
David Zeuthen c357c61e35 2005-06-12 David Zeuthen <davidz@redhat.com>
* gnome/vpn-properties/nm-vpn-ui-interface.h: New file

	* gnome/vpn-properties/nm-vpn-properties.glade: New file

	* gnome/vpn-properties/nm-vpn-properties.c: New file

	* gnome/vpn-properties/Makefile.am: New file

	* src/vpn-manager/nm-vpn-manager.h: Rework prototypes to take an
	array of passwords

	* src/vpn-manager/nm-vpn-manager.c
	(nm_vpn_manager_activate_vpn_connection): Take an array of passwords
	instead of just a single one

	* src/vpn-manager/nm-dbus-vpn.c:
	(nm_dbus_vpn_get_vpn_connection_properties): Also append service_name
	here
	(nm_dbus_vpn_activate_connection): Rework to take an array of passwords

	* gnome/applet/vpn-password-dialog.h (nmwa_vpn_request_password):
	Change the interface here to give a list of passwords. Also, don't
	require username, but do require service

	* gnome/applet/vpn-password-dialog.c: Look up the VPN .name files for
	the binary for the auth-dialog and use that instead of putting up a
	dialog asking for a single password

	* gnome/applet/vpn-connection.[ch]: Don't remember the user_name,
	however do remember the service

	* gnome/applet/main.c (main): Setup i18n

	* gnome/applet/applet.c (nmwa_update_state): Add a line "VPN
	connection to '%s'" to the tooltip if we are connected using VPN
	(nmwa_menu_vpn_item_activate): Check last_attempt_success gconf
	key to determine whether we the auth-dialog needs to
	reprompt. Also cope with the fact that the auth-dialog now returns
	an array of passwords.
	(nmwa_menu_configure_vpn_item_activate): New handler for
	"Configure VPN..." menu item
	(nmwa_menu_add_vpn_menu): Add the "Configure VPN..." menu item
	(is_vpn_available): New function to determine if we got any
	NM-compatible VPN software installed
	(nmwa_menu_add_devices): Use is_vpn_available to add VPN menu
	items only if we have NM-compatible VPN software installed
	(nmwa_gconf_vpn_connections_notify_callback): Slightly rework the
	logic for detecting when VPN connections are removed

	* gnome/applet/applet-dbus.h: Removed the prototypes for
	nmwa_dbus_vpn_activate_connection, nmwa_dbus_vpn_deactivate_connection
	since these are defined elsewhere

	* gnome/applet/applet-dbus.c (set_vpn_last_attempt_status): New
	function used to keep track of whether the last attempt succeded
	(nmwa_dbus_filter): Update last_attempt according to whether the
	VPN connection could be established or not

	* gnome/applet/applet-dbus-vpn.h (nmwa_dbus_vpn_deactivate_connection):
	Change prototype to take an array of passwords, not just a single
	password

	* gnome/applet/applet-dbus-vpn.c (nmwa_dbus_vpn_properties_cb): Only
	update service, not user
	(nmwa_dbus_vpn_remove_one_vpn_connection): Check that applet->
	dbus_active_vpn_name is not NULL before using it
	(nmwa_dbus_vpn_activate_connection): Send the passwords as a
	string array instead of assuming a single password

	* gnome/applet/applet-dbus-info.c:
	(nmi_dbus_get_vpn_connection_properties): Use the logged in user for
	user name; don't read from gconf

	* gnome/applet/Makefile.am: Also export SYSCONFDIR and
	VPN_NAME_FILES_DIR

	* gnome/Makefile.am (SUBDIRS): Add vpn-properties

	* configure.in: Add checks for gmodule-2.0.
	Generate gnome/vpn-properties/Makefile. Don't generate any Makefile's
	in vpn-daemons nor vpn-daemons/vpnc. We have separate autotooled
	projects under vpn-daemons now.	 See vpn-daemons/vpnc/Changelog
	for details

	* vpn-daemons/Makefile.am: Removed

	* vpn-daemons/README: New file to describe extensions points for VPN
	software


git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@664 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-06-12 14:35:59 +00:00

803 lines
25 KiB
C

/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
*
* Dan Williams <dcbw@redhat.com>
*
* 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 2004 Red Hat, Inc.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib.h>
#include <glib/gi18n.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib-lowlevel.h>
#include "applet.h"
#include "applet-dbus.h"
#include "applet-dbus-devices.h"
#include "applet-dbus-vpn.h"
#include "applet-dbus-info.h"
#include "vpn-connection.h"
#include "passphrase-dialog.h"
#include "nm-utils.h"
#define DBUS_NO_SERVICE_ERROR "org.freedesktop.DBus.Error.ServiceDoesNotExist"
/*
* nmi_dbus_create_error_message
*
* Convenience function to make a DBus error message
*
*/
DBusMessage *nmwa_dbus_create_error_message (DBusMessage *message, const char *exception_namespace, const char *exception, const char *format, ...)
{
char * exception_text;
DBusMessage * reply_message;
va_list args;
char error_text[512];
va_start (args, format);
vsnprintf (error_text, 512, format, args);
va_end (args);
exception_text = g_strdup_printf ("%s.%s", exception_namespace, exception);
reply_message = dbus_message_new_error (message, exception_text, error_text);
g_free (exception_text);
return (reply_message);
}
/*
* deal_with_dbus_error
*
* Ignore some common dbus errors
*
*/
static int deal_with_dbus_error (const char *function, const char *method, DBusError *error)
{
int ret = RETURN_FAILURE;
if (!strcmp (error->name, DBUS_NO_SERVICE_ERROR))
ret = RETURN_NO_NM;
else if (!strcmp (error->name, NM_DBUS_NO_ACTIVE_NET_ERROR))
ret = RETURN_SUCCESS;
else if (!strcmp (error->name, NM_DBUS_NO_ACTIVE_DEVICE_ERROR))
ret = RETURN_SUCCESS;
else if (!strcmp (error->name, NM_DBUS_NO_NETWORKS_ERROR))
ret = RETURN_SUCCESS;
else if (!strcmp (error->name, NM_DBUS_NO_ACTIVE_VPN_CONNECTION))
ret = RETURN_SUCCESS;
else if (!strcmp (error->name, NM_DBUS_NO_VPN_CONNECTIONS))
ret = RETURN_SUCCESS;
if ((ret != RETURN_SUCCESS) && (ret != RETURN_NO_NM))
nm_warning ("%s(): %s raised on method '%s':\n %s\n\n", function, error->name, method, error->message);
return ret;
}
/*
* nmwa_dbus_call_method_string
*
* Do a method call on NetworkManager that returns a string.
*
* Returns: RETURN_SUCCESS on success
* RETURN_FAILURE on failure
* RETURN_NO_NM if NetworkManager service no longer exists
*/
int nmwa_dbus_call_method_string (DBusConnection *con, const char *path, const char *interface, const char *method, gboolean is_obj_path, char **string)
{
DBusMessage * message;
DBusMessage * reply;
DBusError error;
char * dbus_string = NULL;
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 (string != NULL, RETURN_FAILURE);
g_return_val_if_fail (*string == NULL, RETURN_FAILURE);
if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE, path, interface, method)))
{
nm_warning ("nmwa_dbus_call_method_string(): Couldn't allocate the dbus message\n");
return (RETURN_FAILURE);
}
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))
{
int ret = deal_with_dbus_error (__FUNCTION__, method, &error);
dbus_error_free (&error);
return (ret);
}
if (reply == NULL)
{
nm_warning ("nmwa_dbus_call_method_string(): dbus reply message was NULL\n" );
return (RETURN_FAILURE);
}
dbus_error_init (&error);
dbus_message_get_args (reply, &error, is_obj_path ? DBUS_TYPE_OBJECT_PATH : DBUS_TYPE_STRING, &dbus_string, DBUS_TYPE_INVALID);
if (dbus_error_is_set (&error))
{
nm_warning ("nmwa_dbus_call_method_string(): 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 (RETURN_FAILURE);
}
*string = g_strdup (dbus_string);
dbus_message_unref (reply);
return (RETURN_SUCCESS);
}
/*
* nmwa_dbus_call_method_uint32
*
* Do a method call on NetworkManager that returns a DBUS_TYPE_UINT32.
*
* Returns: RETURN_SUCCESS on success
* RETURN_FAILURE on failure
* RETURN_NO_NM if NetworkManager service no longer exists
*/
int nmwa_dbus_call_method_uint32 (DBusConnection *con, const char *path, const char *interface, const char *method, guint32 *num)
{
DBusMessage * message;
DBusMessage * reply;
DBusError error;
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 (num != NULL, RETURN_FAILURE);
if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE, path, interface, method)))
{
nm_warning ("nmwa_dbus_call_method_uint32(): Couldn't allocate the dbus message\n");
return (RETURN_FAILURE);
}
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))
{
int ret = deal_with_dbus_error (__FUNCTION__, method, &error);
dbus_error_free (&error);
return (ret);
}
if (reply == NULL)
{
nm_warning ("nmwa_dbus_call_method_uint32(): dbus reply message was NULL\n" );
return (RETURN_FAILURE);
}
dbus_error_init (&error);
dbus_message_get_args (reply, &error, DBUS_TYPE_UINT32, num, DBUS_TYPE_INVALID);
dbus_message_unref (reply);
if (dbus_error_is_set (&error))
{
nm_warning ("nnmwa_dbus_call_method_uint32(): error while getting args: name='%s' message='%s'\n", error.name, error.message);
if (dbus_error_is_set (&error))
dbus_error_free (&error);
return (RETURN_FAILURE);
}
return (RETURN_SUCCESS);
}
/*
* nmwa_dbus_call_method_int32
*
* Do a method call on NetworkManager that returns a DBUS_TYPE_INT32.
*
* Returns: RETURN_SUCCESS on success
* RETURN_FAILURE on failure
* RETURN_NO_NM if NetworkManager service no longer exists
*/
int nmwa_dbus_call_method_int32 (DBusConnection *con, const char *path, const char *interface, const char *method, gint32 *num)
{
DBusMessage * message;
DBusMessage * reply;
DBusError error;
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 (num != NULL, RETURN_FAILURE);
if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE, path, interface, method)))
{
nm_warning ("nmwa_dbus_call_method_int32(): Couldn't allocate the dbus message\n");
return (RETURN_FAILURE);
}
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))
{
int ret = deal_with_dbus_error (__FUNCTION__, method, &error);
dbus_error_free (&error);
return (ret);
}
if (reply == NULL)
{
nm_warning ("nmwa_dbus_call_method_int32(): dbus reply message was NULL\n" );
return (RETURN_FAILURE);
}
dbus_error_init (&error);
dbus_message_get_args (reply, &error, DBUS_TYPE_INT32, num, DBUS_TYPE_INVALID);
dbus_message_unref (reply);
if (dbus_error_is_set (&error))
{
nm_warning ("nnmwa_dbus_call_method_int32(): error while getting args: name='%s' message='%s'\n", error.name, error.message);
if (dbus_error_is_set (&error))
dbus_error_free (&error);
return (RETURN_FAILURE);
}
return (RETURN_SUCCESS);
}
/*
* nmwa_dbus_call_method_boolean
*
* Do a method call on NetworkManager that returns a DBUS_TYPE_BOOLEAN.
*
* Returns: RETURN_SUCCESS on success
* RETURN_FAILURE on failure
* RETURN_NO_NM if NetworkManager service no longer exists
*/
int nmwa_dbus_call_method_boolean (DBusConnection *con, const char *path, const char *interface, const char *method, gboolean *num)
{
DBusMessage * message;
DBusMessage * reply;
DBusError error;
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 (num != NULL, RETURN_FAILURE);
if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE, path, interface, method)))
{
nm_warning ("nmwa_dbus_call_method_boolean(): Couldn't allocate the dbus message\n");
return (RETURN_FAILURE);
}
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))
{
int ret = deal_with_dbus_error (__FUNCTION__, method, &error);
dbus_error_free (&error);
return (ret);
}
if (reply == NULL)
{
nm_warning ("nmwa_dbus_call_method_boolean(): dbus reply message was NULL\n" );
return (RETURN_FAILURE);
}
dbus_error_init (&error);
dbus_message_get_args (reply, &error, DBUS_TYPE_BOOLEAN, num, DBUS_TYPE_INVALID);
dbus_message_unref (reply);
if (dbus_error_is_set (&error))
{
nm_warning ("nnmwa_dbus_call_method_boolean(): error while getting args: name='%s' message='%s'\n", error.name, error.message);
if (dbus_error_is_set (&error))
dbus_error_free (&error);
return (RETURN_FAILURE);
}
return (RETURN_SUCCESS);
}
/*
* nmwa_dbus_call_method_string_array
*
* Do a method call on NetworkManager that returns a string array.
*
* Returns: RETURN_SUCCESS on success
* RETURN_FAILURE on failure
* RETURN_NO_NM if NetworkManager service no longer exists
*/
int nmwa_dbus_call_method_string_array (DBusConnection *con, const char *path, const char *interface, const char *method,
gboolean is_obj_path, char ***array, guint32 *array_len)
{
DBusMessage * message;
DBusMessage * reply;
DBusError error;
char ** dbus_array;
int dbus_array_len;
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 (array != NULL, RETURN_FAILURE);
g_return_val_if_fail (*array == NULL, RETURN_FAILURE);
g_return_val_if_fail (array_len != NULL, RETURN_FAILURE);
if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE, path, interface, method)))
{
nm_warning ("nmwa_dbus_call_method_string_array(): Couldn't allocate the dbus message\n");
return (RETURN_FAILURE);
}
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))
{
int ret = deal_with_dbus_error (__FUNCTION__, method, &error);
dbus_error_free (&error);
return (ret);
}
if (reply == NULL)
{
nm_warning ("nmwa_dbus_call_method_string_array(): dbus reply message was NULL\n" );
return (RETURN_FAILURE);
}
dbus_error_init (&error);
dbus_message_get_args (reply, &error, DBUS_TYPE_ARRAY, is_obj_path ? DBUS_TYPE_OBJECT_PATH : DBUS_TYPE_STRING, &dbus_array, &dbus_array_len, DBUS_TYPE_INVALID);
if (dbus_error_is_set (&error))
{
nm_warning ("nnmwa_dbus_call_method_string_array(): error while getting args: name='%s' message='%s'\n", error.name, error.message);
dbus_message_unref (reply);
if (dbus_error_is_set (&error))
dbus_error_free (&error);
return (RETURN_FAILURE);
}
*array = g_strdupv (dbus_array);
*array_len = dbus_array_len;
dbus_free_string_array (dbus_array);
dbus_message_unref (reply);
return (RETURN_SUCCESS);
}
static void
set_vpn_last_attempt_status (NMWirelessApplet *applet, const char *vpn_name, gboolean last_attempt_success)
{
char *gconf_key;
char *escaped_name;
escaped_name = gconf_escape_key (vpn_name, strlen (vpn_name));
gconf_key = g_strdup_printf ("%s/%s/last_attempt_success", GCONF_PATH_VPN_CONNECTIONS, escaped_name);
gconf_client_set_bool (applet->gconf_client, gconf_key, last_attempt_success, NULL);
g_free (gconf_key);
g_free (escaped_name);
}
/*
* nmwa_dbus_filter
*
*/
static DBusHandlerResult nmwa_dbus_filter (DBusConnection *connection, DBusMessage *message, void *user_data)
{
NMWirelessApplet *applet = (NMWirelessApplet *)user_data;
gboolean handled = TRUE;
const char * object_path;
const char * member;
const char * interface;
g_return_val_if_fail (applet != 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);
if (!(object_path = dbus_message_get_path (message)))
return FALSE;
if (!(member = dbus_message_get_member (message)))
return FALSE;
if (!(interface = dbus_message_get_interface (message)))
return FALSE;
/* nm_info ("signal(): got signal op='%s' member='%s' interface='%s'", object_path, member, interface); */
if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged"))
{
char *service;
char *old_owner;
char *new_owner;
if (dbus_message_get_args (message, NULL,
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 && !applet->nm_running)
{
/* NetworkManager started up */
applet->nm_running = TRUE;
applet->gui_nm_state = NM_STATE_DISCONNECTED;
applet->dbus_nm_state = NM_STATE_DISCONNECTED;
nmwa_dbus_update_nm_state (applet);
nmwa_dbus_update_devices (applet);
nmwa_dbus_vpn_update_vpn_connections (applet);
}
else if (old_owner_good && !new_owner_good)
{
applet->nm_running = FALSE;
nmi_passphrase_dialog_schedule_cancel (applet);
}
}
}
}
else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, NM_DBUS_SIGNAL_STATE_CHANGE))
{
NMState state = NM_STATE_UNKNOWN;
if (dbus_message_get_args (message, NULL, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID))
{
NetworkDevice *act_dev = nmwa_get_first_active_device (applet->dbus_device_list);
/* If we've switched to connecting, update the active device to ensure that we have
* valid wireless network information for it.
*/
if ( (state == NM_STATE_CONNECTING)
&& act_dev
&& network_device_is_wireless (act_dev))
{
nmwa_dbus_device_update_one_device (applet, network_device_get_nm_path (act_dev));
}
applet->dbus_nm_state = state;
applet->gui_nm_state = state;
}
}
else if ( dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceAdded")
|| 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, "DeviceCarrierOn")
|| dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceCarrierOff"))
{
char *path = NULL;
if (dbus_message_get_args (message, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID))
nmwa_dbus_device_update_one_device (applet, path);
}
else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceRemoved"))
{
char *path = NULL;
if (dbus_message_get_args (message, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID))
nmwa_dbus_device_remove_one_device (applet, path);
}
else if ( dbus_message_is_signal (message, NM_DBUS_INTERFACE_VPN, "VPNConnectionAdded")
|| dbus_message_is_signal (message, NM_DBUS_INTERFACE_VPN, "VPNConnectionUpdate")) /* VPN connection properties changed */
{
char *name = NULL;
if (dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID))
nmwa_dbus_vpn_update_one_vpn_connection (applet, name);
}
else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE_VPN, "VPNConnectionChange")) /* Active VPN connection changed */
{
nmwa_dbus_vpn_get_active_vpn_connection (applet);
}
else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE_VPN, "VPNConnectionRemoved"))
{
char *name = NULL;
if (dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID))
nmwa_dbus_vpn_remove_one_vpn_connection (applet, name);
}
else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, "WirelessNetworkAppeared"))
{
char *dev_path = NULL;
char *net_path = NULL;
if (dbus_message_get_args (message, NULL, DBUS_TYPE_OBJECT_PATH, &dev_path, DBUS_TYPE_OBJECT_PATH, &net_path, DBUS_TYPE_INVALID))
nmwa_dbus_device_update_one_network (applet, dev_path, net_path, NULL);
}
else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, "WirelessNetworkDisappeared"))
{
char *dev_path = NULL;
char *net_path = NULL;
if (dbus_message_get_args (message, NULL, DBUS_TYPE_OBJECT_PATH, &dev_path, DBUS_TYPE_OBJECT_PATH, &net_path, DBUS_TYPE_INVALID))
nmwa_dbus_device_remove_one_network (applet, dev_path, net_path);
}
else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, "WirelessNetworkStrengthChanged"))
{
char * dev_path = NULL;
char * net_path = NULL;
int strength = -1;
if (dbus_message_get_args (message, NULL, DBUS_TYPE_OBJECT_PATH, &dev_path, DBUS_TYPE_OBJECT_PATH, &net_path, DBUS_TYPE_INT32, &strength, DBUS_TYPE_INVALID))
{
/* FIXME actually use strength rather than querying all network properties */
nmwa_dbus_device_update_one_network (applet, dev_path, net_path, NULL);
}
}
else if ( dbus_message_is_signal (message, NM_DBUS_INTERFACE_VPN, NM_DBUS_VPN_SIGNAL_LOGIN_FAILED)
|| dbus_message_is_signal (message, NM_DBUS_INTERFACE_VPN, NM_DBUS_VPN_SIGNAL_LAUNCH_FAILED)
|| dbus_message_is_signal (message, NM_DBUS_INTERFACE_VPN, NM_DBUS_VPN_SIGNAL_CONNECT_FAILED)
|| dbus_message_is_signal (message, NM_DBUS_INTERFACE_VPN, NM_DBUS_VPN_SIGNAL_VPN_CONFIG_BAD)
|| dbus_message_is_signal (message, NM_DBUS_INTERFACE_VPN, NM_DBUS_VPN_SIGNAL_IP_CONFIG_BAD))
{
char *vpn_name;
char *error_msg;
if (dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &vpn_name, DBUS_TYPE_STRING, &error_msg, DBUS_TYPE_INVALID)) {
nmwa_schedule_vpn_failure_dialog (applet, member, vpn_name, error_msg);
/* clear the 'last_attempt_success' key in gconf so we prompt for password next time */
set_vpn_last_attempt_status (applet, vpn_name, FALSE);
}
}
else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE_VPN, NM_DBUS_VPN_SIGNAL_LOGIN_BANNER))
{
char *vpn_name;
char *banner;
if (dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &vpn_name, DBUS_TYPE_STRING, &banner, DBUS_TYPE_INVALID)) {
nmwa_schedule_vpn_login_banner_dialog (applet, vpn_name, banner);
/* set the 'last_attempt_success' key in gconf so we DON'T prompt for password next time */
set_vpn_last_attempt_status (applet, vpn_name, TRUE);
}
}
else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceActivationFailed"))
{
char *dev = NULL;
char *net = NULL;
if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &dev, DBUS_TYPE_STRING, &net, DBUS_TYPE_INVALID))
dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &dev, DBUS_TYPE_INVALID);
if (dev && net)
{
char *string = g_strdup_printf (_("Connection to the wireless network '%s' failed.\n"), net);
nmwa_schedule_warning_dialog (applet, string);
g_free (string);
}
else if (dev)
nmwa_schedule_warning_dialog (applet, _("Connection to the wired network failed.\n"));
}
else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceActivationStage"))
{
char * dev_path = NULL;
NMActStage stage;
if (dbus_message_get_args (message, NULL, DBUS_TYPE_OBJECT_PATH, &dev_path, DBUS_TYPE_UINT32, &stage, DBUS_TYPE_INVALID))
{
NetworkDevice *dev;
if ((dev = nmwa_get_device_for_nm_path (applet->dbus_device_list, dev_path)))
network_device_set_act_stage (dev, stage);
if ((dev = nmwa_get_device_for_nm_path (applet->gui_device_list, dev_path)))
network_device_set_act_stage (dev, stage);
}
}
else
handled = FALSE;
return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
}
/*
* nmwa_dbus_nm_is_running
*
* Ask dbus whether or not NetworkManager is running
*
*/
static gboolean nmwa_dbus_nm_is_running (DBusConnection *connection)
{
DBusError error;
gboolean exists;
g_return_val_if_fail (connection != NULL, FALSE);
dbus_error_init (&error);
exists = dbus_bus_name_has_owner (connection, NM_DBUS_SERVICE, &error);
if (dbus_error_is_set (&error))
dbus_error_free (&error);
return (exists);
}
/*
* nmwa_dbus_init
*
* Initialize a connection to NetworkManager if we can get one
*
*/
static DBusConnection * nmwa_dbus_init (NMWirelessApplet *applet, GMainContext *context)
{
DBusConnection * connection = NULL;
DBusError error;
DBusObjectPathVTable vtable = { NULL, &nmi_dbus_info_message_handler, NULL, NULL, NULL, NULL };
int acquisition;
g_return_val_if_fail (applet != NULL, NULL);
g_return_val_if_fail (context != NULL, NULL);
dbus_error_init (&error);
connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
if (dbus_error_is_set (&error))
{
nm_warning ("%s raised:\n %s\n\n", error.name, error.message);
dbus_error_free (&error);
return NULL;
}
dbus_error_init (&error);
acquisition = dbus_bus_request_name (connection, NMI_DBUS_SERVICE, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error);
if (dbus_error_is_set (&error))
{
nm_warning ("nmwa_dbus_init() could not acquire its service. dbus_bus_acquire_service() says: '%s'", error.message);
dbus_error_free (&error);
return NULL;
}
if (acquisition == DBUS_REQUEST_NAME_REPLY_EXISTS)
return NULL;
if (!dbus_connection_register_object_path (connection, NMI_DBUS_PATH, &vtable, applet))
{
nm_warning ("nmwa_dbus_init() could not register a handler for NetworkManagerInfo. Not enough memory?");
return NULL;
}
if (!dbus_connection_add_filter (connection, nmwa_dbus_filter, applet, NULL))
return NULL;
dbus_connection_set_exit_on_disconnect (connection, FALSE);
dbus_connection_setup_with_g_main (connection, context);
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_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);
dbus_bus_add_match(connection,
"type='signal',"
"interface='" NM_DBUS_INTERFACE_VPN "',"
"path='" NM_DBUS_PATH_VPN "',"
"sender='" NM_DBUS_SERVICE "'",
&error);
if (dbus_error_is_set (&error))
dbus_error_free (&error);
return (connection);
}
/*
* nmwa_dbus_connection_watcher
*
* Try to reconnect if we ever get disconnected from the bus
*
*/
static gboolean nmwa_dbus_connection_watcher (gpointer user_data)
{
NMWirelessApplet *applet = (NMWirelessApplet *)user_data;
g_return_val_if_fail (applet != NULL, TRUE);
if (!applet->connection)
{
if ((applet->connection = nmwa_dbus_init (applet, applet->thread_context)))
{
applet->nm_running = nmwa_dbus_nm_is_running (applet->connection);
applet->dbus_nm_state = NM_STATE_DISCONNECTED;
nmwa_dbus_update_nm_state (applet);
nmwa_dbus_update_devices (applet);
nmwa_dbus_vpn_update_vpn_connections (applet);
}
}
return (TRUE);
}
/*
* nmwa_dbus_worker
*
* Thread worker function that periodically grabs the NetworkManager state
* and updates our local applet state to reflect that.
*
*/
gpointer nmwa_dbus_worker (gpointer user_data)
{
NMWirelessApplet * applet = (NMWirelessApplet *)user_data;
GSource * timeout_source;
GSource * strength_source;
g_return_val_if_fail (applet != NULL, NULL);
dbus_g_thread_init ();
if (!(applet->thread_context = g_main_context_new ()))
return (NULL);
if (!(applet->thread_loop = g_main_loop_new (applet->thread_context, FALSE)))
return (NULL);
applet->connection = nmwa_dbus_init (applet, applet->thread_context);
timeout_source = g_timeout_source_new (2000);
g_source_set_callback (timeout_source, nmwa_dbus_connection_watcher, applet, NULL);
g_source_attach (timeout_source, applet->thread_context);
strength_source = g_timeout_source_new (2000);
g_source_set_callback (strength_source, (GSourceFunc) nmwa_dbus_update_device_strength, applet, NULL);
g_source_attach (strength_source, applet->thread_context);
if (applet->connection && nmwa_dbus_nm_is_running (applet->connection))
{
applet->nm_running = TRUE;
nmwa_dbus_update_nm_state (applet);
nmwa_dbus_update_devices (applet);
nmwa_dbus_vpn_update_vpn_connections (applet);
}
g_main_loop_run (applet->thread_loop);
g_source_destroy (timeout_source);
#if 0
g_source_destroy (strength_source);
#endif
return NULL;
}