diff options
| -rw-r--r-- | network/manager.c | 97 | ||||
| -rw-r--r-- | network/server.c | 80 | ||||
| -rw-r--r-- | network/server.h | 4 | 
3 files changed, 164 insertions, 17 deletions
| diff --git a/network/manager.c b/network/manager.c index 33cbd36f..ace1f602 100644 --- a/network/manager.c +++ b/network/manager.c @@ -77,7 +77,7 @@ static void pending_reply_free(struct pending_reply *pr)  }  static DBusHandlerResult create_path(DBusConnection *conn, -					DBusMessage *msg, char *path, +					DBusMessage *msg, const char *path,  					const char *sname)  {  	DBusMessage *reply, *signal; @@ -101,7 +101,6 @@ static DBusHandlerResult create_path(DBusConnection *conn,  	dbus_message_append_args(reply, DBUS_TYPE_STRING, &path,  					DBUS_TYPE_INVALID); -	g_free(path);  	return send_message_and_unref(conn, reply);  } @@ -221,7 +220,7 @@ static void pan_record_reply(DBusPendingCall *call, void *data)  	pr->mgr->connections = g_slist_append(pr->mgr->connections,  						g_strdup(pr->path)); -	create_path(pr->conn, pr->msg, g_strdup (pr->path), "ConnectionCreated"); +	create_path(pr->conn, pr->msg, pr->path, "ConnectionCreated");  fail:  	sdp_record_free(rec);  	dbus_error_free(&derr); @@ -333,6 +332,64 @@ static int get_handles(struct pending_reply *pr,  	return 0;  } +static void get_address_reply(DBusPendingCall *call, void *data) +{ +	struct pending_reply *pr = data; +	DBusMessage *reply = dbus_pending_call_steal_reply(call); +	DBusError derr; +	const char *address; + +	dbus_error_init(&derr); +	if (dbus_set_error_from_message(&derr, reply)) { +		error("GetAddress: %s(%s)", derr.name, derr.message); +		goto fail; +	} + +	if (!dbus_message_get_args(reply, &derr, +				DBUS_TYPE_STRING, &address, +				DBUS_TYPE_INVALID)) { +		error("%s: %s", derr.name, derr.message); +		goto fail; +	} + +	if (server_register(pr->conn, address, pr->path, pr->id) < 0) { +		err_failed(pr->conn, pr->msg, "D-Bus path registration failed"); +		goto fail; +	} + +	pr->mgr->servers = g_slist_append(pr->mgr->servers, +						g_strdup(pr->path)); + +	create_path(pr->conn, pr->msg, pr->path, "ServerCreated"); +fail: +	dbus_error_free(&derr); +	dbus_message_unref(reply); +	dbus_pending_call_unref(call); +	return; +} + +static int get_address(struct pending_reply *pr, +			DBusPendingCallNotifyFunction cb) +{ +	DBusMessage *msg; +	DBusPendingCall *pending; + +	msg = dbus_message_new_method_call("org.bluez", pr->adapter_path, +			"org.bluez.Adapter", "GetAddress"); +	if (!msg) +		return -1; + +	if (dbus_connection_send_with_reply(pr->conn, msg, &pending, -1) == FALSE) { +		error("Can't send D-Bus message."); +		return -1; +	} + +	dbus_pending_call_set_notify(pending, cb, pr, NULL); +	dbus_message_unref(msg); + +	return 0; +} +  static void default_adapter_reply(DBusPendingCall *call, void *data)  {  	struct pending_reply *pr = data; @@ -357,7 +414,10 @@ static void default_adapter_reply(DBusPendingCall *call, void *data)  	pr->adapter_path = g_strdup(adapter); -	if (get_handles(pr, pan_handle_reply) < 0) { +	if (pr->id == BNEP_SVC_PANU && (get_handles(pr, pan_handle_reply) < 0)) { +		err_failed(pr->conn, pr->msg, "D-Bus path registration failed"); +		goto fail; +	} else if (get_address(pr, get_address_reply) < 0) {  		err_failed(pr->conn, pr->msg, "D-Bus path registration failed");  		goto fail;  	} @@ -404,9 +464,9 @@ static DBusHandlerResult create_server(DBusConnection *conn,  					DBusMessage *msg, void *data)  {  	struct manager *mgr = data; +	struct pending_reply *pr;  	DBusError derr;  	const char *str; -	char *path;  	int id;  	dbus_error_init(&derr); @@ -422,21 +482,28 @@ static DBusHandlerResult create_server(DBusConnection *conn,  	if ((id != BNEP_SVC_GN) && (id != BNEP_SVC_NAP))  		return err_invalid_args(conn, msg, "Not supported"); -	path = g_new0(char, 32); -	snprintf(path, 32, NETWORK_PATH "/server/%X", id); - -	if (g_slist_find_custom(mgr->servers, path, (GCompareFunc) strcmp)) -		return err_already_exists(conn, msg, "Server Already exists"); +	pr = g_new(struct pending_reply, 1); +	pr->conn = conn; +	pr->msg = dbus_message_ref(msg); +	pr->mgr = mgr; +	pr->addr = NULL; +	pr->id = id; +	pr->path = g_new0(char, 32); +	snprintf(pr->path, 32, NETWORK_PATH "/server/%s", bnep_name(id)); -	if (server_register(conn, path, id) == -1) { -		err_failed(conn, msg, "D-Bus path registration failed"); -		g_free(path); +	if (g_slist_find_custom(mgr->servers, pr->path, +				(GCompareFunc) strcmp)) { +		err_already_exists(conn, msg, "Server Already exists"); +		pending_reply_free(pr);  		return DBUS_HANDLER_RESULT_HANDLED;  	} -	mgr->servers = g_slist_append(mgr->servers, g_strdup(path)); +	if (get_default_adapter(pr, default_adapter_reply) < 0) { +		err_failed(conn, msg, "D-Bus path registration failed"); +		pending_reply_free(pr); +	} -	return create_path(conn, msg, path, "ServerCreated"); +	return DBUS_HANDLER_RESULT_HANDLED;  }  static DBusHandlerResult remove_server(DBusConnection *conn, diff --git a/network/server.c b/network/server.c index 67319107..0c0932ae 100644 --- a/network/server.c +++ b/network/server.c @@ -30,6 +30,8 @@  #include <stdlib.h>  #include <errno.h>  #include <sys/socket.h> +#include <sys/file.h> +#include <sys/stat.h>  #include <bluetooth/bluetooth.h>  #include <bluetooth/bnep.h> @@ -50,6 +52,7 @@  #include "bridge.h"  #include "common.h"  #include "server.h" +#include "textfile.h"  /* Pending Authorization */  struct pending_auth { @@ -60,6 +63,7 @@ struct pending_auth {  /* Main server structure */  struct network_server { +	bdaddr_t		src;		/* Bluetooth Local Address */  	char			*iface;		/* Routing interface */  	char			*name;		/* Server service name */  	char			*path; 		/* D-Bus path */ @@ -73,6 +77,48 @@ struct network_server {  static char netdev[16] = "bnep%d"; +static inline int create_filename(char *buf, size_t size, +					bdaddr_t *bdaddr, const char *name) +{ +	char addr[18]; + +	ba2str(bdaddr, addr); + +	return create_name(buf, size, STORAGEDIR, addr, name); +} + +static int del_stored_server_info(bdaddr_t *src, uint16_t uuid) +{ +	char filename[PATH_MAX + 1]; +	const char *str; +	int err; + +	create_filename(filename, PATH_MAX, src, "network"); + +	str = bnep_uuid(uuid); + +	err = textfile_del(filename, str); + +	return err; +} + +static int store_server_info(bdaddr_t *src, uint16_t uuid, gboolean enable) +{ +	char filename[PATH_MAX + 1]; +	const char *str; +	int err; + +	create_filename(filename, PATH_MAX, src, "network"); + +	str = bnep_uuid(uuid); + +	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + +	err = textfile_put(filename, str, enable ? "1" : "0"); + +	return err; +} +  static void pending_auth_free(struct pending_auth *pauth)  {  	if (!pauth) @@ -684,6 +730,9 @@ static DBusHandlerResult enable(DBusConnection *conn,  	DBusMessage *reply;  	int err; +	if (ns->io) +		return err_already_exists(conn, msg, "Server already enabled"); +  	reply = dbus_message_new_method_return(msg);  	if (!reply)  		return DBUS_HANDLER_RESULT_NEED_MEMORY; @@ -699,6 +748,8 @@ static DBusHandlerResult enable(DBusConnection *conn,  	if (err < 0)   		return err_failed(conn, msg, strerror(-err)); +	store_server_info(&ns->src, ns->id, TRUE); +  	return send_message_and_unref(conn, reply);  } @@ -724,6 +775,8 @@ static DBusHandlerResult disable(DBusConnection *conn,  	g_io_channel_unref(ns->io);  	ns->io = NULL; +	store_server_info(&ns->src, ns->id, FALSE); +  	return send_message_and_unref(conn, reply);  } @@ -943,6 +996,8 @@ static void server_free(struct network_server *ns)  		g_io_channel_unref(ns->io);  	} +	del_stored_server_info(&ns->src, ns->id); +  	g_free(ns);  } @@ -961,7 +1016,8 @@ static const DBusObjectPathVTable server_table = {  	.unregister_function = server_unregister,  }; -int server_register(DBusConnection *conn, const char *path, uint16_t id) +int server_register(DBusConnection *conn, const char *addr, const char *path,  +			uint16_t id)  {  	struct network_server *ns; @@ -989,11 +1045,33 @@ int server_register(DBusConnection *conn, const char *path, uint16_t id)  	ns->path = g_strdup(path);  	ns->id = id;  	ns->conn = dbus_connection_ref(conn); +	str2ba(addr, &ns->src);  	info("Registered server path:%s", ns->path); +	store_server_info(&ns->src, ns->id, FALSE); +  	return 0;  fail:  	server_free(ns);  	return -1;  } + +int read_server_uuid(bdaddr_t *src, uint16_t uuid, gboolean *enable) +{ +	char filename[PATH_MAX + 1], *buff; +	const char *str; + +	create_filename(filename, PATH_MAX, src, "network"); + +	str = bnep_uuid(uuid); +	buff = textfile_get(filename, str); +	if (!buff) +		return -ENOENT; + +	*enable = (strtol(buff, NULL, 10)) ? TRUE : FALSE; + +	g_free(buff); + +	return 0; +} diff --git a/network/server.h b/network/server.h index 27b38ba6..7db4ad18 100644 --- a/network/server.h +++ b/network/server.h @@ -21,4 +21,6 @@   *   */ -int server_register(DBusConnection *conn, const char *path, uint16_t id); +int server_register(DBusConnection *conn, const char *addr, const char *path,  +			uint16_t id); +int read_server_uuid(bdaddr_t *src, uint16_t uuid, gboolean *enable); | 
