summary refs log tree commit diff
path: root/src/settings/nm-settings.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/settings/nm-settings.c')
-rw-r--r--src/settings/nm-settings.c116
1 files changed, 114 insertions, 2 deletions
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
index 1ead4f8b..96564605 100644
--- a/src/settings/nm-settings.c
+++ b/src/settings/nm-settings.c
@@ -49,6 +49,7 @@
 #include <nm-setting-serial.h>
 #include <nm-setting-vpn.h>
 #include <nm-setting-wired.h>
+#include <nm-setting-adsl.h>
 #include <nm-setting-wireless.h>
 #include <nm-setting-wireless-security.h>
 #include <nm-setting-bond.h>
@@ -68,6 +69,7 @@
 #include "plugins/keyfile/plugin.h"
 #include "nm-agent-manager.h"
 #include "nm-settings-utils.h"
+#include "nm-connection-provider.h"
 
 #define CONFIG_KEY_NO_AUTO_DEFAULT "no-auto-default"
 
@@ -110,6 +112,12 @@ static void impl_settings_save_hostname (NMSettings *self,
 
 static void unmanaged_specs_changed (NMSystemConfigInterface *config, gpointer user_data);
 
+static void connection_provider_init (NMConnectionProvider *cp_class);
+
+G_DEFINE_TYPE_EXTENDED (NMSettings, nm_settings, G_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (NM_TYPE_CONNECTION_PROVIDER, connection_provider_init))
+
+
 typedef struct {
 	NMDBusManager *dbus_mgr;
 	DBusGConnection *bus;
@@ -127,8 +135,6 @@ typedef struct {
 	GSList *unmanaged_specs;
 } NMSettingsPrivate;
 
-G_DEFINE_TYPE (NMSettings, nm_settings, G_TYPE_OBJECT)
-
 #define NM_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTINGS, NMSettingsPrivate))
 
 enum {
@@ -186,6 +192,7 @@ load_connections (NMSettings *self)
 	unmanaged_specs_changed (NULL, self);
 
 	g_signal_emit (self, signals[CONNECTIONS_LOADED], 0);
+	g_signal_emit_by_name (self, NM_CP_SIGNAL_CONNECTIONS_LOADED);
 }
 
 void
@@ -674,6 +681,7 @@ connection_removed (NMSettingsConnection *obj, gpointer user_data)
 
 	/* Re-emit for listeners like NMPolicy */
 	g_signal_emit (NM_SETTINGS (user_data), signals[CONNECTION_REMOVED], 0, connection);
+	g_signal_emit_by_name (NM_SETTINGS (user_data), NM_CP_SIGNAL_CONNECTION_REMOVED, connection);
 
 	g_object_unref (connection);
 }
@@ -701,6 +709,7 @@ connection_updated (NMSettingsConnection *connection, gpointer user_data)
 	               signals[CONNECTION_UPDATED],
 	               0,
 	               connection);
+	g_signal_emit_by_name (NM_SETTINGS (user_data), NM_CP_SIGNAL_CONNECTION_UPDATED, connection);
 }
 
 static void
@@ -849,6 +858,7 @@ claim_connection (NMSettings *self,
 	if (priv->connections_loaded) {
 		/* Internal added signal */
 		g_signal_emit (self, signals[CONNECTION_ADDED], 0, connection);
+		g_signal_emit_by_name (self, NM_CP_SIGNAL_CONNECTION_ADDED, connection);
 
 		/* Exported D-Bus signal */
 		g_signal_emit (self, signals[NEW_CONNECTION], 0, connection);
@@ -1621,6 +1631,100 @@ nm_settings_device_removed (NMSettings *self, NMDevice *device)
 
 /***************************************************************/
 
+static gint
+best_connection_sort (gconstpointer a, gconstpointer b, gpointer user_data)
+{
+	NMSettingsConnection *ac = (NMSettingsConnection *) a;
+	NMSettingsConnection *bc = (NMSettingsConnection *) b;
+	guint64 ats, bts;
+
+	if (!ac && bc)
+		return -1;
+	else if (ac && !bc)
+		return 1;
+	else if (!ac && !bc)
+		return 0;
+
+	g_assert (ac && bc);
+
+	/* In the future we may use connection priorities in addition to timestamps */
+	ats = nm_settings_connection_get_timestamp (ac);
+	bts = nm_settings_connection_get_timestamp (bc);
+
+	if (ats < bts)
+		return -1;
+	else if (ats > bts)
+		return 1;
+	return 0;
+}
+
+static GSList *
+get_best_connections (NMConnectionProvider *provider,
+                      guint max_requested,
+                      const char *ctype1,
+                      const char *ctype2,
+                      NMConnectionFilterFunc func,
+                      gpointer func_data)
+{
+	NMSettings *self = NM_SETTINGS (provider);
+	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
+	GSList *sorted = NULL;
+	GHashTableIter iter;
+	NMSettingsConnection *connection;
+	guint added = 0;
+	guint64 oldest = 0;
+
+	g_hash_table_iter_init (&iter, priv->connections);
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &connection)) {
+		if (ctype1 && !nm_connection_is_type (NM_CONNECTION (connection), ctype1))
+			continue;
+		if (ctype2 && !nm_connection_is_type (NM_CONNECTION (connection), ctype2))
+			continue;
+		if (func && !func (provider, NM_CONNECTION (connection), func_data))
+			continue;
+
+		/* Don't bother with a connection that's older than the oldest one in the list */
+		if (   max_requested
+		    && added >= max_requested
+		    && nm_settings_connection_get_timestamp (connection) <= oldest)
+			continue;
+
+		/* List is sorted with oldest first */
+		sorted = g_slist_insert_sorted_with_data (sorted, connection, best_connection_sort, NULL);
+		added++;
+
+		if (max_requested && added > max_requested) {
+			/* Over the limit, remove the oldest one */
+			sorted = g_slist_delete_link (sorted, sorted);
+			added--;
+		}
+
+		oldest = nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (sorted->data));
+	}
+
+	return g_slist_reverse (sorted);
+}
+
+static const GSList *
+get_connections (NMConnectionProvider *provider)
+{
+	static GSList *list = NULL;
+	NMSettings *self = NM_SETTINGS (provider);
+	GHashTableIter iter;
+	NMSettingsConnection *connection;
+
+	/* Lazily free the list with every call so we can keep it 'const' for callers */
+	g_slist_free (list);
+	list = NULL;
+
+	g_hash_table_iter_init (&iter, NM_SETTINGS_GET_PRIVATE (self)->connections);
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &connection))
+		list = g_slist_prepend (list, connection);
+	return g_slist_reverse (list);
+}
+
+/***************************************************************/
+
 NMSettings *
 nm_settings_new (const char *config_file,
                  const char **plugins,
@@ -1660,6 +1764,13 @@ nm_settings_new (const char *config_file,
 }
 
 static void
+connection_provider_init (NMConnectionProvider *cp_class)
+{
+    cp_class->get_best_connections = get_best_connections;
+    cp_class->get_connections = get_connections;
+}
+
+static void
 nm_settings_init (NMSettings *self)
 {
 	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
@@ -1873,6 +1984,7 @@ nm_settings_class_init (NMSettingsClass *class)
 	dbus_g_error_domain_register (NM_SETTING_PPP_ERROR, NULL, NM_TYPE_SETTING_PPP_ERROR);
 	dbus_g_error_domain_register (NM_SETTING_PPPOE_ERROR, NULL, NM_TYPE_SETTING_PPPOE_ERROR);
 	dbus_g_error_domain_register (NM_SETTING_SERIAL_ERROR, NULL, NM_TYPE_SETTING_SERIAL_ERROR);
+	dbus_g_error_domain_register (NM_SETTING_ADSL_ERROR, NULL, NM_TYPE_SETTING_ADSL_ERROR);
 	dbus_g_error_domain_register (NM_SETTING_VPN_ERROR, NULL, NM_TYPE_SETTING_VPN_ERROR);
 	dbus_g_error_domain_register (NM_SETTING_WIRED_ERROR, NULL, NM_TYPE_SETTING_WIRED_ERROR);
 	dbus_g_error_domain_register (NM_SETTING_WIRELESS_SECURITY_ERROR, NULL, NM_TYPE_SETTING_WIRELESS_SECURITY_ERROR);