diff options
| author | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2009-02-20 15:37:09 -0300 | 
|---|---|---|
| committer | Johan Hedberg <johan.hedberg@nokia.com> | 2009-02-23 11:23:15 +0200 | 
| commit | 231ba99b01b93f7c68a3b37cbaf61d0d75c5ecc8 (patch) | |
| tree | 6cdc25bd597f6d5eb6b43af728e9afcc279d8ff2 | |
| parent | cd9a7649dc02512a6feea9c34a422b5f3e3e57b6 (diff) | |
Convert Network plugin to use confirm callback.
| -rw-r--r-- | network/common.h | 1 | ||||
| -rw-r--r-- | network/server.c | 271 | 
2 files changed, 112 insertions, 160 deletions
| diff --git a/network/common.h b/network/common.h index 67ef3247..424d6183 100644 --- a/network/common.h +++ b/network/common.h @@ -24,6 +24,7 @@  #define PANU_UUID	"00001115-0000-1000-8000-00805f9b34fb"  #define NAP_UUID	"00001116-0000-1000-8000-00805f9b34fb"  #define GN_UUID		"00001117-0000-1000-8000-00805f9b34fb" +#define BNEP_SVC_UUID	"0000000f-0000-1000-8000-00805f9b34fb"  int bnep_init(const char *panu_script, const char *gn_script,  		const char *nap_script); diff --git a/network/server.c b/network/server.c index 01ab5ed7..b155b9a2 100644 --- a/network/server.c +++ b/network/server.c @@ -60,24 +60,17 @@  #define SETUP_TIMEOUT		1  /* Pending Authorization */ -struct setup_session { -	char		*address;	/* Remote Bluetooth Address */ -	uint16_t	dst_role;	/* Destination role */ -	uint16_t	src_role;	/* Source role */ -	int		nsk;		/* L2CAP socket */ +struct network_session { +	bdaddr_t	dst;		/* Remote Bluetooth Address */ +	GIOChannel	*io;		/* Pending connect channel */  	guint		watch;		/* BNEP socket watch */  }; -struct timeout { -	guint	id;		/* Timeout id */ -	guint	watch;		/* BNEP socket watch */ -}; -  struct network_adapter {  	bdaddr_t	src;		/* Bluetooth Local Address */  	char		*path;		/* D-Bus path */  	GIOChannel	*io;		/* Bnep socket */ -	struct timeout	*to;		/* Socket timeout */ +	struct network_session *setup;	/* Setup in progress */  	GSList		*servers;	/* Server register to adapter */  }; @@ -89,12 +82,11 @@ struct network_server {  	gboolean	enable;		/* Enable flag */  	uint32_t	record_id;	/* Service record id */  	uint16_t	id;		/* Service class identifier */ -	GSList		*clients;	/* Active connections */ +	GSList		*sessions;	/* Active connections */  	struct network_adapter *na;	/* Adapter reference */  };  static DBusConnection *connection = NULL; -static struct setup_session *setup = NULL;  static GSList *adapters = NULL;  static const char *prefix = NULL;  static gboolean security = TRUE; @@ -127,28 +119,6 @@ static struct network_server *find_server(GSList *list, uint16_t id)  	return NULL;  } -static struct setup_session *setup_session_new(gchar *address, -		uint16_t dst_role, uint16_t src_role, int nsk, guint watch) -{ -	struct setup_session *setup; - -	setup = g_new0(struct setup_session, 1); -	setup->address = g_strdup(address); -	setup->dst_role = dst_role; -	setup->src_role = src_role; -	setup->nsk = nsk; -	setup->watch = watch; - -	return setup; -} - -static void setup_session_free(struct setup_session *setup) -{ -	g_source_remove(setup->watch); -	g_free(setup->address); -	g_free(setup); -} -  static void add_lang_attr(sdp_record_t *r)  {  	sdp_lang_attr_t base_lang; @@ -299,12 +269,13 @@ static ssize_t send_bnep_ctrl_rsp(int sk, uint16_t val)  	return send(sk, &rsp, sizeof(rsp), 0);  } -static int server_connadd(struct network_server *ns, int nsk, -			const gchar *address, uint16_t dst_role) +static int server_connadd(struct network_server *ns, +				struct network_session *session, +				uint16_t dst_role)  {  	char devname[16];  	const char *bridge; -	int err; +	int err, nsk;  	/* Server can be disabled in the meantime */  	if (ns->enable == FALSE) @@ -313,6 +284,7 @@ static int server_connadd(struct network_server *ns, int nsk,  	memset(devname, 0, 16);  	strncpy(devname, prefix, strlen(prefix)); +	nsk = g_io_channel_unix_get_fd(session->io);  	err = bnep_connadd(nsk, dst_role, devname);  	if (err < 0)  		return err; @@ -332,56 +304,11 @@ static int server_connadd(struct network_server *ns, int nsk,  	} else  		bnep_if_up(devname, ns->id); -	ns->clients = g_slist_append(ns->clients, g_strdup(address)); +	ns->sessions = g_slist_append(ns->sessions, session);  	return 0;  } -static void req_auth_cb(DBusError *derr, void *user_data) -{ -	struct network_server *ns = user_data; -	uint16_t val; - -	if (!setup) { -		info("Authorization cancelled: Client exited"); -		return; -	} - -	if (derr) { -		error("Access denied: %s", derr->message); - -		val = BNEP_CONN_NOT_ALLOWED; -		goto done; -	} - -	if (server_connadd(ns, setup->nsk, -			setup->address, setup->dst_role) < 0) -		val = BNEP_CONN_NOT_ALLOWED; -	else -		val = BNEP_SUCCESS; - -done: -	send_bnep_ctrl_rsp(setup->nsk, val); -	setup_session_free(setup); -	setup = NULL; -} - -static int authorize_connection(struct network_server *ns, const char *address) -{ -	struct network_adapter *na = ns->na; -	const char *uuid; -	bdaddr_t dst; -	int ret_val; - -	uuid = bnep_uuid(ns->id); -	str2ba(address, &dst); - -	ret_val = btd_request_authorization(&na->src, &dst, uuid, -				req_auth_cb, ns); - -	return ret_val; -} -  static uint16_t bnep_setup_chk(uint16_t dst_role, uint16_t src_role)  {  	/* Allowed PAN Profile scenarios */ @@ -428,18 +355,40 @@ static uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req,  	return 0;  } +static void session_free(void *data) +{ +	struct network_session *session = data; + +	if (session->watch) +		g_source_remove(session->watch); + +	if (session->io) +		g_io_channel_unref(session->io); + +	g_free(session); +} + +static void setup_destroy(void *user_data) +{ +	struct network_adapter *na = user_data; +	struct network_session *setup = na->setup; + +	if (!setup) +		return; + +	na->setup = NULL; + +	session_free(setup); +} +  static gboolean bnep_setup(GIOChannel *chan,  			GIOCondition cond, gpointer user_data)  {  	struct network_adapter *na = user_data; -	struct timeout *to = na->to;  	struct network_server *ns;  	uint8_t packet[BNEP_MTU];  	struct bnep_setup_conn_req *req = (void *) packet; -	struct sockaddr_l2 sa; -	socklen_t size; -	char address[18]; -	uint16_t rsp, src_role, dst_role; +	uint16_t src_role, dst_role, rsp = BNEP_CONN_NOT_ALLOWED;  	int n, sk;  	if (cond & G_IO_NVAL) @@ -470,47 +419,18 @@ static gboolean bnep_setup(GIOChannel *chan,  	if (rsp)  		goto reply; -	size = sizeof(sa); -	if (getsockname(sk, (struct sockaddr *) &sa, &size) < 0) { -		rsp = BNEP_CONN_NOT_ALLOWED; -		goto reply; -	} - -	ba2str(&sa.l2_bdaddr, address);  	ns = find_server(na->servers, dst_role);  	if (!ns || ns->enable == FALSE) { -		error("Server unavailable: %s (0x%x)", address, dst_role); -		rsp = BNEP_CONN_NOT_ALLOWED; -		goto reply; -	} - -	if (getpeername(sk, (struct sockaddr *) &sa, &size) < 0) { -		rsp = BNEP_CONN_NOT_ALLOWED; +		error("Server unavailable: (0x%x)", dst_role);  		goto reply;  	} -	ba2str(&sa.l2_bdaddr, address); - -	if (setup) { -		error("Connection rejected: Pending authorization"); -		rsp = BNEP_CONN_NOT_ALLOWED; -		goto reply; -	} - -	setup = setup_session_new(address, dst_role, src_role, sk, to->watch); - -	/* Wait authorization before reply success */ -	if (authorize_connection(ns, address) < 0) { -		setup_session_free(setup); -		setup = NULL; -		rsp = BNEP_CONN_NOT_ALLOWED; +	if (server_connadd(ns, na->setup, dst_role) < 0)  		goto reply; -	} -	g_source_remove(to->id); -	to->id = 0; +	na->setup = NULL; -	return TRUE; +	rsp = BNEP_SUCCESS;  reply:  	send_bnep_ctrl_rsp(sk, rsp); @@ -518,52 +438,90 @@ reply:  	return FALSE;  } -static void setup_destroy(void *user_data) +static void connect_event(GIOChannel *chan, GError *err, gpointer user_data)  {  	struct network_adapter *na = user_data; -	struct timeout *to = na->to; -	na->to = NULL; +	if (err) { +		error("%s", err->message); +		setup_destroy(na); +		return; +	} -	if (to->id) -		g_source_remove(to->id); +	g_io_channel_set_close_on_unref(chan, TRUE); -	g_free(to); +	na->setup->watch = g_io_add_watch_full(chan, G_PRIORITY_DEFAULT, +				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, +				bnep_setup, na, setup_destroy);  } -static gboolean timeout_cb(void *user_data) +static void auth_cb(DBusError *derr, void *user_data)  { -	struct timeout *to = user_data; +	struct network_adapter *na = user_data; +	GError *err = NULL; -	to->id = 0; -	g_source_remove(to->watch); +	if (derr) { +		error("Access denied: %s", derr->message); +		goto reject; +	} -	return FALSE; +	if (!bt_io_accept(na->setup->io, connect_event, na, NULL, +							&err)) { +		error("bt_io_accept: %s", err->message); +		g_error_free(err); +		goto reject; +	} + +	return; + +reject: +	g_io_channel_shutdown(na->setup->io, TRUE, NULL); +	setup_destroy(na);  } -static void connect_event(GIOChannel *chan, GError *err, gpointer user_data) +static void confirm_event(GIOChannel *chan, gpointer user_data)  {  	struct network_adapter *na = user_data; +	int perr; +	bdaddr_t src, dst; +	char *address[18]; +	GError *err = NULL; +	bt_io_get(chan, BT_IO_L2CAP, &err, +			BT_IO_OPT_SOURCE_BDADDR, &src, +			BT_IO_OPT_DEST_BDADDR, &dst, +			BT_IO_OPT_DEST, address, +			BT_IO_OPT_INVALID);  	if (err) {  		error("%s", err->message); -		return; +		g_error_free(err); +		goto drop;  	} -	g_io_channel_set_close_on_unref(chan, TRUE); +	debug("BNEP: incoming connect from %s", address); -	/* -	 * BNEP_SETUP_CONNECTION_REQUEST_MSG shall be received and -	 * user shall authorize the incomming connection before -	 * the time expires. -	 */ -	na->to = g_malloc0(sizeof(struct timeout)); -	na->to->id = g_timeout_add_seconds(SETUP_TIMEOUT, timeout_cb, na->to); -	na->to->watch = g_io_add_watch_full(chan, G_PRIORITY_DEFAULT, -				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, -				bnep_setup, na, setup_destroy); +	if (na->setup) { +		error("Refusing connect from %s: setup in progress", address); +		goto drop; +	} + +	na->setup = g_new0(struct network_session, 1); +	bacpy(&na->setup->dst, &dst); +	na->setup->io = g_io_channel_ref(chan); + +	perr = btd_request_authorization(&src, &dst, BNEP_SVC_UUID, +					auth_cb, na); +	if (perr < 0) { +		error("Refusing connect from %s: %s (%d)", address, +				strerror(-perr), -perr); +		setup_destroy(na); +		goto drop; +	}  	return; + +drop: +	g_io_channel_shutdown(chan, TRUE, NULL);  }  int server_init(DBusConnection *conn, const char *iface_prefix, @@ -651,15 +609,6 @@ static DBusMessage *enable(DBusConnection *conn,  	return reply;  } -static void kill_connection(void *data, void *udata) -{ -	const char *address = data; -	bdaddr_t dst; - -	str2ba(address, &dst); -	bnep_kill_connection(&dst); -} -  static DBusMessage *disable(DBusConnection *conn,  				DBusMessage *msg, void *data)  { @@ -681,7 +630,8 @@ static DBusMessage *disable(DBusConnection *conn,  	ns->enable = FALSE; -	g_slist_foreach(ns->clients, (GFunc) kill_connection, NULL); +	g_slist_foreach(ns->sessions, (GFunc) session_free, NULL); +	g_slist_free(ns->sessions);  	return reply;  } @@ -799,6 +749,7 @@ static void adapter_free(struct network_adapter *na)  		g_io_channel_unref(na->io);  	} +	setup_destroy(na);  	g_free(na->path);  	g_free(na);  } @@ -821,9 +772,9 @@ static void server_free(struct network_server *ns)  	if (ns->range)  		g_free(ns->range); -	if (ns->clients) { -		g_slist_foreach(ns->clients, (GFunc) g_free, NULL); -		g_slist_free(ns->clients); +	if (ns->sessions) { +		g_slist_foreach(ns->sessions, (GFunc) session_free, NULL); +		g_slist_free(ns->sessions);  	}  	g_free(ns); @@ -867,7 +818,7 @@ static struct network_adapter *create_adapter(const char *path, bdaddr_t *src)  	na->path = g_strdup(path);  	bacpy(&na->src, src); -	na->io = bt_io_listen(BT_IO_L2CAP, connect_event, NULL, na, +	na->io = bt_io_listen(BT_IO_L2CAP, NULL, confirm_event, na,  				NULL, &err,  				BT_IO_OPT_SOURCE_BDADDR, src,  				BT_IO_OPT_PSM, BNEP_PSM, | 
