diff options
| author | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2007-03-26 20:08:34 +0000 | 
|---|---|---|
| committer | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2007-03-26 20:08:34 +0000 | 
| commit | 2b349e5e40d1e96a7968104e51fd10d95a6f390b (patch) | |
| tree | 4d567f8e2f09c1e66a1d9dc9f3bcc9a4d765cb12 | |
| parent | edfeafb77880e222832f47f99d668c5a445a24ba (diff) | |
network: added initial code for server L2CAP listening
| -rw-r--r-- | network/server.c | 89 | 
1 files changed, 88 insertions, 1 deletions
| diff --git a/network/server.c b/network/server.c index 427bff8b..1a02bb50 100644 --- a/network/server.c +++ b/network/server.c @@ -25,11 +25,14 @@  #include <config.h>  #endif +#include <unistd.h>  #include <stdlib.h>  #include <errno.h> +#include <sys/socket.h>  #include <bluetooth/bluetooth.h>  #include <bluetooth/bnep.h> +#include <bluetooth/l2cap.h>  #include <bluetooth/sdp.h>  #include <bluetooth/sdp_lib.h> @@ -51,6 +54,7 @@ struct network_server {  	dbus_bool_t	secure;  	uint32_t	record_id;	/* Service record id */  	uint16_t	id;		/* Service class identifier */ +	GIOChannel	*io;		/* GIOChannel when listening */  };  void add_lang_attr(sdp_record_t *r) @@ -183,6 +187,86 @@ static int create_server_record(sdp_buf_t *buf, uint16_t id)  	return ret;  } +static gboolean connect_event(GIOChannel *chan, +				GIOCondition cond, gpointer data) +{ +	info("FIXME: Connect event"); +	return FALSE; +} + +static int l2cap_listen(struct network_server *ns) +{ +	struct l2cap_options l2o; +	struct sockaddr_l2 l2a; +	socklen_t olen; +	int sk, lm, err; + +	/* Create L2CAP socket and bind it to PSM BNEP */ +	sk = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); +	if (sk < 0) { +		err = errno; +		error("Cannot create L2CAP socket. %s(%d)", +					strerror(err), err); +		return -err; +	} + +	memset(&l2a, 0, sizeof(l2a)); +	l2a.l2_family = AF_BLUETOOTH; +	bacpy(&l2a.l2_bdaddr, BDADDR_ANY); +	l2a.l2_psm = htobs(BNEP_PSM); + +	if (bind(sk, (struct sockaddr *) &l2a, sizeof(l2a))) { +		err = errno; +		error("Bind failed. %s(%d)", strerror(err), err); +		goto fail; +	} + +	/* Setup L2CAP options according to BNEP spec */ +	memset(&l2o, 0, sizeof(l2o)); +	olen = sizeof(l2o); +	if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &olen) < 0) { +		err = errno; +		error("Failed to get L2CAP options. %s(%d)", +					strerror(err), err); +		goto fail; +	} + +	l2o.imtu = l2o.omtu = BNEP_MTU; +	if (setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, sizeof(l2o)) < 0) { +		err = errno; +		error("Failed to set L2CAP options. %s(%d)", +					strerror(err), err); +		goto fail; +	} + +	/* Set link mode */ +	lm = (ns->secure ? L2CAP_LM_SECURE : 0); +	if (lm && setsockopt(sk, SOL_L2CAP, L2CAP_LM, &lm, sizeof(lm)) < 0) { +		err = errno; +		error("Failed to set link mode. %s(%d)", +					strerror(err), err); +		goto fail; +	} + +	if (listen(sk, 10) < 0) { +		err = errno; +		error("Listen failed. %s(%d)", strerror(err), err); +		goto fail; +	} + +	ns->io = g_io_channel_unix_new(sk); +	g_io_channel_set_close_on_unref(ns->io, TRUE); + +	g_io_add_watch(ns->io, G_IO_IN, connect_event, NULL); + +	return 0; +fail: + +	close(sk); +	errno = err; +	return -err; +} +  static uint32_t add_server_record(DBusConnection *conn, uint16_t id)  {  	DBusMessage *msg, *reply; @@ -259,6 +343,7 @@ static DBusHandlerResult enable(DBusConnection *conn,  {  	struct network_server *ns = data;  	DBusMessage *reply; +	int err;  	reply = dbus_message_new_method_return(msg);  	if (!reply) @@ -273,7 +358,9 @@ static DBusHandlerResult enable(DBusConnection *conn,  	/* FIXME: Check security */ -	/* FIXME: Start listen */ +	err = l2cap_listen(ns); +	if (err < 0)  +		return err_failed(conn, msg, strerror(-err));  	return send_message_and_unref(conn, reply);  } | 
