diff options
Diffstat (limited to 'network/manager.c')
| -rw-r--r-- | network/manager.c | 295 | 
1 files changed, 237 insertions, 58 deletions
diff --git a/network/manager.c b/network/manager.c index 8eac0bee..6d7654f9 100644 --- a/network/manager.c +++ b/network/manager.c @@ -70,6 +70,7 @@ struct pending_reply {  static GSList *server_paths	= NULL;	/* Network registered servers paths */  static GSList *connection_paths	= NULL;	/* Network registered connections paths */ +static int default_index = -1;		/* Network default connection path index */  static DBusConnection *connection = NULL; @@ -139,6 +140,27 @@ static DBusHandlerResult list_paths(DBusConnection *conn, DBusMessage *msg,  	return send_message_and_unref(conn, reply);  } +static const char * last_connection_used(DBusConnection *conn) +{ +	const char *path = NULL; +	GSList *l; +	int i; + +	for (i = g_slist_length (connection_paths) -1; i > -1; i--) { +		path = g_slist_nth_data (connection_paths, i); +		if (connection_is_connected (conn, path)) +			break; +	} + +	/* No connection connected fallback to last connection */ +	if (i == -1) { +		l = g_slist_last(connection_paths); +		path = l->data; +	} + +	return path; +} +  static DBusHandlerResult remove_path(DBusConnection *conn,  					DBusMessage *msg, GSList **list,  					const char *sname) @@ -163,10 +185,17 @@ static DBusHandlerResult remove_path(DBusConnection *conn,  	/* Remove references from the storage */  	if (*list == connection_paths) { -		if (connection_has_pending (conn, path)) +		if (connection_has_pending(conn, path))  			return err_failed(conn, msg, "Connection is Busy");  		connection_remove_stored(conn, path); +		/* Reset default connection */ +		if (l == g_slist_nth(*list, default_index)) { +			const char *dpath; + +			dpath = last_connection_used(conn); +			connection_store(conn, dpath, TRUE); +		}  	}  	else  		server_remove_stored(conn, path); @@ -251,7 +280,7 @@ static void pan_record_reply(DBusPendingCall *call, void *data)  		goto fail;  	} -	connection_store(pr->conn, pr->path); +	connection_store(pr->conn, pr->path, FALSE);  	connection_paths = g_slist_append(connection_paths, g_strdup(pr->path));  	create_path(pr->conn, pr->msg, pr->path, "ConnectionCreated"); @@ -401,7 +430,7 @@ static DBusHandlerResult create_server(DBusConnection *conn,  	if ((id != BNEP_SVC_GN) && (id != BNEP_SVC_NAP))  		return err_invalid_args(conn, msg, "Not supported"); -	snprintf(path, MAX_PATH_LENGTH, NETWORK_PATH"/server/%s%d", +	snprintf(path, MAX_PATH_LENGTH, NETWORK_PATH"/%s%d",  							bnep_name(id), net_uid++);  	if (g_slist_find_custom(server_paths, path, @@ -480,6 +509,24 @@ static DBusHandlerResult list_connections(DBusConnection *conn,  	return list_paths(conn, msg, connection_paths);  } +static GSList * find_connection_pattern(DBusConnection *conn, +					const char *pattern) +{ +	const char *path; +	GSList *list; + +	if (pattern == NULL) +		return NULL; + +	for (list = connection_paths; list; list = list->next) { +		path = (const char *) list->data; +		if (connection_find_data(conn, path, pattern) == 0) +			break; +	} + +	return list; +} +  static DBusHandlerResult find_connection(DBusConnection *conn,  						DBusMessage *msg, void *data)  { @@ -498,17 +545,15 @@ static DBusHandlerResult find_connection(DBusConnection *conn,  		return DBUS_HANDLER_RESULT_HANDLED;  	} -	for (list = connection_paths; list; list = list->next) { -		path = (const char *) list->data; -		if (connection_find_data(conn, path, pattern) == 0) -			break; -	} +	list = find_connection_pattern(conn, pattern);  	if (list == NULL) {  		err_failed(conn, msg, "No such connection");  		return DBUS_HANDLER_RESULT_HANDLED;  	} +	path = list->data; +  	reply = dbus_message_new_method_return(msg);  	if (!reply)  		return DBUS_HANDLER_RESULT_NEED_MEMORY; @@ -588,6 +633,118 @@ static DBusHandlerResult remove_connection(DBusConnection *conn,  	return remove_path(conn, msg, &connection_paths, "ConnectionRemoved");  } +static DBusHandlerResult last_connection(DBusConnection *conn, +						DBusMessage *msg, void *data) +{ +	const char *path; +	DBusMessage *reply; + +	if (connection_paths == NULL || +		g_slist_length (connection_paths) == 0) { +		err_does_not_exist(conn, msg, "No such connection"); +		return DBUS_HANDLER_RESULT_HANDLED; +	} + +	path = last_connection_used(conn); + +	reply = dbus_message_new_method_return(msg); +	if (!reply) +		return DBUS_HANDLER_RESULT_NEED_MEMORY; + +	dbus_message_append_args(reply, DBUS_TYPE_STRING, &path, +					DBUS_TYPE_INVALID); + +	return send_message_and_unref(conn, reply); +} + +static DBusHandlerResult default_connection(DBusConnection *conn, +						DBusMessage *msg, void *data) +{ +	const char *path; +	DBusMessage *reply; + +	if (connection_paths == NULL || +		g_slist_length (connection_paths) == 0) { +		err_does_not_exist(conn, msg, "No such connection"); +		return DBUS_HANDLER_RESULT_HANDLED; +	} + +	path = g_slist_nth_data (connection_paths, default_index); + +	if (path == NULL) { +		path = last_connection_used(conn); +		connection_store(conn, path, TRUE); +	} + +	reply = dbus_message_new_method_return(msg); +	if (!reply) +		return DBUS_HANDLER_RESULT_NEED_MEMORY; + +	dbus_message_append_args(reply, DBUS_TYPE_STRING, &path, +					DBUS_TYPE_INVALID); + +	return send_message_and_unref(conn, reply); +} + +static DBusHandlerResult change_default_connection(DBusConnection *conn, +						DBusMessage *msg, void *data) +{ +	const char *path; +	const char *pattern; +	DBusMessage *reply; +	DBusError derr; +	GSList *list; + +	dbus_error_init(&derr); +	if (!dbus_message_get_args(msg, &derr, +				DBUS_TYPE_STRING, &pattern, +				DBUS_TYPE_INVALID)) { +		err_invalid_args(conn, msg, derr.message); +		dbus_error_free(&derr); +		return DBUS_HANDLER_RESULT_HANDLED; +	} + +	if (connection_paths == NULL || +		g_slist_length (connection_paths) == 0) { +		err_does_not_exist(conn, msg, "No such connection"); +		return DBUS_HANDLER_RESULT_HANDLED; +	} + +	list = g_slist_find_custom(connection_paths, pattern, (GCompareFunc) strcmp); + +	/* Find object path via pattern */ +	if (list == NULL) { +		list = find_connection_pattern(conn, pattern); + +		if (list == NULL) { +			err_failed(conn, msg, "No such connection"); +			return DBUS_HANDLER_RESULT_HANDLED; +		} +		else +			path = list->data; +	} +	else +		path = list->data; + +	default_index = g_slist_position (connection_paths, list); +	connection_store(connection, path, TRUE); + +	dbus_connection_emit_signal(connection, NETWORK_PATH, +					NETWORK_MANAGER_INTERFACE, +					"DefaultConnectionChanged", +					DBUS_TYPE_STRING, &path, +					DBUS_TYPE_INVALID); + +	reply = dbus_message_new_method_return(msg); +	if (!reply) +		return DBUS_HANDLER_RESULT_NEED_MEMORY; + +	dbus_message_append_args(reply, DBUS_TYPE_STRING, &path, +					DBUS_TYPE_INVALID); + +	return send_message_and_unref(conn, reply); +} +  static void manager_unregister(DBusConnection *conn, void *data)  {  	info("Unregistered manager path"); @@ -674,16 +831,77 @@ static void parse_stored_connection(char *key, char *value, void *data)  	g_free(name);  } -static void register_stored(void) +static void register_connections_stored(const char *adapter) +{ +	char filename[PATH_MAX + 1]; +	char *pattern; +	struct stat s; +	GSList *list; +	bdaddr_t src; +	bdaddr_t default_src; +	int dev_id; + +	create_name(filename, PATH_MAX, STORAGEDIR, adapter, "network"); + +	str2ba(adapter, &src); + +	bacpy(&default_src, BDADDR_ANY); +	dev_id = hci_get_route(NULL); +	if (dev_id < 0) +		hci_devba(dev_id, &default_src); + +	if (stat (filename, &s) == 0 && (s.st_mode & __S_IFREG)) { +		textfile_foreach(filename, parse_stored_connection, &src); +		pattern = textfile_get(filename, "default"); + +		list = find_connection_pattern(connection, pattern); +		if (list != NULL) +			default_index = g_slist_position(connection_paths, list); +		else if (bacmp(&src, &default_src) == 0) { +			list = g_slist_last(connection_paths); +			if (list == NULL) +				return; +			default_index = g_slist_position(connection_paths, list); +			connection_store(connection, list->data, TRUE); +		} +	} +} + +static void register_servers_stored(const char *adapter, const char *profile)  { -	char dirname[PATH_MAX + 1];  	char filename[PATH_MAX + 1];  	char path[MAX_PATH_LENGTH]; -	struct dirent *de; -	DIR *dir; +	const char *ppath = path; +	uint16_t id;  	struct stat s;  	bdaddr_t src; +	if (strcmp(profile, "nap") == 0) +		id = BNEP_SVC_NAP; +	else +		id = BNEP_SVC_GN; + +	create_name(filename, PATH_MAX, STORAGEDIR, adapter, profile); + +	str2ba(adapter, &src); + +	if (stat (filename, &s) == 0 && (s.st_mode & __S_IFREG)) { +		snprintf(path, MAX_PATH_LENGTH, +			NETWORK_PATH"/%s%d", profile, net_uid++); +		if (server_register_from_file(connection, path, +			&src, id, filename) == 0) { +			server_paths = g_slist_append(server_paths, +						g_strdup(path)); +		} +	} +} + +static void register_stored(void) +{ +	char dirname[PATH_MAX + 1]; +	struct dirent *de; +	DIR *dir; +  	snprintf(dirname, PATH_MAX, "%s", STORAGEDIR);  	dir = opendir(dirname); @@ -695,56 +913,13 @@ static void register_stored(void)  			continue;  		/* Connection objects */ -		create_name(filename, PATH_MAX, STORAGEDIR, -						de->d_name, "network"); - -		str2ba(de->d_name, &src); - - -		if (stat (filename, &s) == 0 && (s.st_mode & __S_IFREG)) -			textfile_foreach(filename, parse_stored_connection, &src); +		register_connections_stored(de->d_name);  		/* NAP objects */ -		create_name(filename, PATH_MAX, STORAGEDIR, de->d_name, "nap"); -		if (stat (filename, &s) == 0 && (s.st_mode & __S_IFREG)) { -			snprintf(path, MAX_PATH_LENGTH, -					NETWORK_PATH"/server/nap%d", net_uid++); - -			if (server_register_from_file(connection, path, -					&src, BNEP_SVC_NAP, filename) == 0) { -				server_paths = g_slist_append(server_paths, -								g_strdup(path)); - -				dbus_connection_emit_signal(connection, -							NETWORK_PATH, -							NETWORK_MANAGER_INTERFACE, -							"ServerCreated", -							DBUS_TYPE_STRING, -							&path, -							DBUS_TYPE_INVALID); -			} -		} +		register_servers_stored(de->d_name, "nap");  		/* GN objects */ -		create_name(filename, PATH_MAX, STORAGEDIR, de->d_name, "gn"); -		if (stat (filename, &s) == 0 && (s.st_mode & __S_IFREG)) { -			snprintf(path, MAX_PATH_LENGTH, -					NETWORK_PATH"/server/gn%d", net_uid++); - -			if (server_register_from_file(connection, path, -					&src, BNEP_SVC_GN, filename) == 0) { -				server_paths = g_slist_append(server_paths, -								g_strdup(path)); - -				dbus_connection_emit_signal(connection, -							NETWORK_PATH, -							NETWORK_MANAGER_INTERFACE, -							"ServerCreated", -							DBUS_TYPE_STRING, -							&path, -							DBUS_TYPE_INVALID); -			} -		} +		register_servers_stored(de->d_name, "gn");  	}  	closedir(dir); @@ -759,6 +934,9 @@ static DBusMethodVTable manager_methods[] = {  	{ "FindConnection",	find_connection,	"s",	"s"	},  	{ "CreateConnection",	create_connection,	"ss",	"s"	},  	{ "RemoveConnection",	remove_connection,	"s",	""	}, +	{ "LastConnection",	last_connection,	"",	"s"	}, +	{ "DefaultConnection",	default_connection,	"",	"s"	}, +	{ "ChangeDefaultConnection", change_default_connection, "s", "s"},  	{ NULL, NULL, NULL, NULL }  }; @@ -767,6 +945,7 @@ static DBusSignalVTable manager_signals[] = {  	{ "ServerRemoved",	"s"	},  	{ "ConnectionCreated",	"s"	},  	{ "ConnectionRemoved",	"s"	}, +	{ "DefaultConnectionChanged", "s" },  	{ NULL, NULL }  };  | 
