summaryrefslogtreecommitdiffstats
path: root/network
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2007-05-17 17:05:47 +0000
committerLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2007-05-17 17:05:47 +0000
commitdf7260b7a01d10f92849ca9a862a2a2d6ffac865 (patch)
treecf8e317702e4e76c55b40fe1f9ff3b2ce627d617 /network
parent8bd6348b59d94d40ad4e85e3561cbbf2b7a02cdd (diff)
Add LastConnection, DefaultConnection and ChangeDefaultConnection API methods and some minor fixes.
Diffstat (limited to 'network')
-rw-r--r--network/connection.c29
-rw-r--r--network/connection.h4
-rw-r--r--network/manager.c295
-rw-r--r--network/network-api.txt21
4 files changed, 282 insertions, 67 deletions
diff --git a/network/connection.c b/network/connection.c
index 68c53b7b..18bba87c 100644
--- a/network/connection.c
+++ b/network/connection.c
@@ -675,7 +675,8 @@ int connection_register(DBusConnection *conn, const char *path, bdaddr_t *src,
return 0;
}
-int connection_store(DBusConnection *conn, const char *path)
+int connection_store(DBusConnection *conn, const char *path,
+ gboolean default_path)
{
struct network_conn *nc;
const char *role;
@@ -696,17 +697,19 @@ int connection_store(DBusConnection *conn, const char *path)
role = bnep_name(nc->id);
snprintf(key, 32, "%s#%s", dst_addr, role);
- len = strlen(nc->name) + strlen(nc->desc) + 2;
- value = g_malloc0(len);
- snprintf(value, len, "%s:%s", nc->name, nc->desc);
-
ba2str(&nc->src, src_addr);
create_name(filename, PATH_MAX, STORAGEDIR, src_addr, "network");
create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
- err = textfile_put(filename, key, value);
-
- g_free(value);
+ if (default_path)
+ err = textfile_put(filename, "default", key);
+ else {
+ len = strlen(nc->name) + strlen(nc->desc) + 2;
+ value = g_malloc0(len);
+ snprintf(value, len, "%s:%s", nc->name, nc->desc);
+ err = textfile_put(filename, key, value);
+ g_free(value);
+ }
return err;
}
@@ -774,3 +777,13 @@ int connection_remove_stored(DBusConnection *conn, const char *path)
return err;
}
+
+gboolean connection_is_connected(DBusConnection *conn, const char *path)
+{
+ struct network_conn *nc;
+
+ if (!dbus_connection_get_object_user_data(conn, path, (void *) &nc))
+ return FALSE;
+
+ return (nc->state == CONNECTED);
+}
diff --git a/network/connection.h b/network/connection.h
index ff33789f..5561ee32 100644
--- a/network/connection.h
+++ b/network/connection.h
@@ -23,8 +23,10 @@
int connection_register(DBusConnection *conn, const char *path, bdaddr_t *src,
bdaddr_t *dst, uint16_t id, const char *name, const char *desc);
-int connection_store(DBusConnection *conn, const char *path);
+int connection_store(DBusConnection *conn, const char *path,
+ gboolean default_path);
int connection_remove_stored(DBusConnection *conn, const char *path);
int connection_find_data(DBusConnection *conn, const char *path,
const char *pattern);
gboolean connection_has_pending(DBusConnection *conn, const char *path);
+gboolean connection_is_connected(DBusConnection *conn, const char *path);
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 }
};
diff --git a/network/network-api.txt b/network/network-api.txt
index 9bdf5ca8..9a18085e 100644
--- a/network/network-api.txt
+++ b/network/network-api.txt
@@ -64,6 +64,25 @@ Methods string CreateServer(string uuid)
Possible errors:org.bluez.network.Error.DoesNotExist
org.bluez.network.Error.Failed
+ string LastConnection()
+
+ Returns last connected connection path, if none is connected
+ fallback to last created connection.
+
+ Possible errors:org.bluez.network.Error.DoesNotExist
+
+ string DefaultConnection()
+
+ Returns default connection path.
+
+ Possible errors:org.bluez.network.Error.DoesNotExist
+
+ string ChangeDefaultConnection(string pattern)
+
+ Changes default connection path.
+
+ Possible errors:org.bluez.network.Error.DoesNotExist
+
Signals
void ServerCreated(string path)
@@ -74,6 +93,8 @@ Signals
void ConnectionRemoved(string path)
+ void DefaultConnectionChanged(string path)
+
Network Server hierarchy (experimental)
=======================================