From df2cebf11c6d6be17d5862884aade789dde78555 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 30 Apr 2009 18:06:05 -0300 Subject: [PATCH] obexd: Make use of BtIO on obexd. BtIO can use DEFER_SETUP if the kernel supports it which make possible to really confirm connections. --- obexd/src/bluetooth.c | 132 +++++++++++++++++++----------------------- obexd/src/dbus.h | 3 +- obexd/src/manager.c | 79 +++++++++++++++---------- 3 files changed, 110 insertions(+), 104 deletions(-) diff --git a/obexd/src/bluetooth.c b/obexd/src/bluetooth.c index 37d7b991f..06dc29bb9 100644 --- a/obexd/src/bluetooth.c +++ b/obexd/src/bluetooth.c @@ -46,112 +46,98 @@ #include "bluetooth.h" #include "obex.h" #include "dbus.h" +#include "btio.h" #define BT_RX_MTU 32767 #define BT_TX_MTU 32767 static GSList *servers = NULL; -static gboolean connect_event(GIOChannel *io, GIOCondition cond, gpointer user_data) +static void connect_event(GIOChannel *io, GError *err, gpointer user_data) { - struct sockaddr_rc raddr; - socklen_t alen; struct server *server = user_data; - gchar address[18]; - gint err, sk, nsk; + gint sk; - sk = g_io_channel_unix_get_fd(io); - alen = sizeof(raddr); - nsk = accept(sk, (struct sockaddr *) &raddr, &alen); - if (nsk < 0) - return TRUE; - - alen = sizeof(raddr); - if (getpeername(nsk, (struct sockaddr *) &raddr, &alen) < 0) { - err = errno; - error("getpeername(): %s(%d)", strerror(err), err); - close(nsk); - return TRUE; + if (err) { + error("%s", err->message); + return; } - ba2str(&raddr.rc_bdaddr, address); - info("New connection from: %s, channel %u, fd %d", address, - raddr.rc_channel, nsk); - - if (server->services != OBEX_OPP) { - if (request_service_authorization(server, nsk) < 0) - close(nsk); - - return TRUE; - } + sk = g_io_channel_unix_get_fd(io); - if (obex_session_start(nsk, server) < 0) - close(nsk); + if (obex_session_start(sk, server) == 0) + return; - return TRUE; + g_io_channel_shutdown(io, TRUE, NULL); } -static gint server_start(struct server *server) +static void confirm_event(GIOChannel *io, gpointer user_data) { - struct sockaddr_rc laddr; - int err, sk, arg; - - sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - if (sk < 0) { - err = errno; - error("socket(): %s(%d)", strerror(err), err); - return -err; + struct server *server = user_data; + GError *err = NULL; + char address[18]; + guint8 channel; + + bt_io_get(io, BT_IO_RFCOMM, &err, + BT_IO_OPT_DEST, address, + BT_IO_OPT_CHANNEL, &channel, + BT_IO_OPT_INVALID); + if (err) { + error("%s", err->message); + g_error_free(err); + goto drop; } - arg = fcntl(sk, F_GETFL); - if (arg < 0) { - err = errno; - goto failed; - } + info("New connection from: %s, channel %u", address, channel); + g_io_channel_set_close_on_unref(io, FALSE); - arg |= O_NONBLOCK; - if (fcntl(sk, F_SETFL, arg) < 0) { - err = errno; - goto failed; - } + if (server->services != OBEX_OPP) { + if (request_service_authorization(server, io, address) < 0) + goto drop; - if (server->secure) { - int lm = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT; + return; + } - if (setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0) { - err = errno; - goto failed; - } + if (!bt_io_accept(io, connect_event, server, NULL, &err)) { + error("%s", err->message); + g_error_free(err); + goto drop; } - memset(&laddr, 0, sizeof(laddr)); - laddr.rc_family = AF_BLUETOOTH; - bacpy(&laddr.rc_bdaddr, BDADDR_ANY); - laddr.rc_channel = server->channel; + return; - if (bind(sk, (struct sockaddr *) &laddr, sizeof(laddr)) < 0) { - err = errno; - goto failed; - } +drop: + g_io_channel_shutdown(io, TRUE, NULL); +} - if (listen(sk, 10) < 0) { - err = errno; +static gint server_start(struct server *server) +{ + GError *err = NULL; + + /* Listen */ + if (server->secure) + server->io = bt_io_listen(BT_IO_RFCOMM, NULL, confirm_event, + server, NULL, &err, + BT_IO_OPT_CHANNEL, server->channel, + BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM, + BT_IO_OPT_INVALID); + else + server->io = bt_io_listen(BT_IO_RFCOMM, NULL, confirm_event, + server, NULL, &err, + BT_IO_OPT_CHANNEL, server->channel, + BT_IO_OPT_INVALID); + if (!server->io) goto failed; - } - server->io = g_io_channel_unix_new(sk); g_io_channel_set_close_on_unref(server->io, TRUE); - server->watch = g_io_add_watch(server->io, - G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - connect_event, server); return 0; failed: - error("Bluetooth server register failed: %s(%d)", strerror(err), err); - close(sk); + error("Bluetooth server register failed: ", err->message); + g_error_free(err); - return -err; + return -EINVAL; } static gint server_stop(struct server *server) diff --git a/obexd/src/dbus.h b/obexd/src/dbus.h index cf89972a6..457fe068b 100644 --- a/obexd/src/dbus.h +++ b/obexd/src/dbus.h @@ -41,7 +41,8 @@ void unregister_transfer(guint32 id); void register_record(struct server *server, gpointer user_data); -gint request_service_authorization(struct server *server, gint nsk); +gint request_service_authorization(struct server *server, GIOChannel *io, + const char *address); void register_session(guint32 id, struct obex_session *os); diff --git a/obexd/src/manager.c b/obexd/src/manager.c index e3524dd27..c465d482c 100644 --- a/obexd/src/manager.c +++ b/obexd/src/manager.c @@ -42,6 +42,7 @@ #include "obex.h" #include "dbus.h" #include "logging.h" +#include "btio.h" static const gchar *opp_record = " \ \ @@ -232,10 +233,10 @@ static struct agent *agent = NULL; struct pending_request { struct server *server; - gchar address[18]; gchar *adapter_path; + char address[18]; guint watch; - gint nsk; + GIOChannel *io; }; struct adapter_any { @@ -998,11 +999,32 @@ static void service_cancel(struct pending_request *pending) g_dbus_send_message(system_conn, msg); } +static void connect_event(GIOChannel *io, GError *err, gpointer user_data) +{ + struct server *server = user_data; + gint sk; + + if (err) { + error("%s", err->message); + return; + } + + sk = g_io_channel_unix_get_fd(io); + + if (obex_session_start(sk, server) == 0) + return; + + g_io_channel_shutdown(io, TRUE, NULL); +} + static void service_reply(DBusPendingCall *call, gpointer user_data) { struct pending_request *pending = user_data; + GIOChannel *io = pending->io; + struct server *server = pending->server; DBusMessage *reply = dbus_pending_call_steal_reply(call); DBusError derr; + GError *err = NULL; dbus_error_init(&derr); if (dbus_set_error_from_message(&derr, reply)) { @@ -1013,14 +1035,17 @@ static void service_reply(DBusPendingCall *call, gpointer user_data) service_cancel(pending); dbus_error_free(&derr); - close(pending->nsk); + g_io_channel_shutdown(io, TRUE, NULL); goto done; } debug("RequestAuthorization succeeded"); - if (obex_session_start(pending->nsk, pending->server) < 0) - close(pending->nsk); + if (!bt_io_accept(io, connect_event, server, NULL, &err)) { + error("%s", err->message); + g_error_free(err); + g_io_channel_shutdown(io, TRUE, NULL); + } done: if (pending->watch) @@ -1048,7 +1073,6 @@ static void find_adapter_reply(DBusPendingCall *call, gpointer user_data) DBusMessage *reply = dbus_pending_call_steal_reply(call); DBusMessage *msg; DBusPendingCall *pcall; - GIOChannel *io; const char *paddr = pending->address; const char *path; DBusError derr; @@ -1092,50 +1116,45 @@ static void find_adapter_reply(DBusPendingCall *call, gpointer user_data) dbus_pending_call_unref(pcall); /* Catches errors before authorization response comes */ - io = g_io_channel_unix_new(pending->nsk); - pending->watch = g_io_add_watch_full(io, G_PRIORITY_DEFAULT, + pending->watch = g_io_add_watch_full(pending->io, G_PRIORITY_DEFAULT, G_IO_HUP | G_IO_ERR | G_IO_NVAL, service_error, pending, NULL); - g_io_channel_unref(io); + g_io_channel_unref(pending->io); return; failed: g_free(pending->adapter_path); - close(pending->nsk); + g_io_channel_shutdown(pending->io, TRUE, NULL); + g_io_channel_unref(pending->io); g_free(pending); } -gint request_service_authorization(struct server *server, gint nsk) +gint request_service_authorization(struct server *server, GIOChannel *io, + const char *address) { - struct sockaddr_rc src, dst; - socklen_t addrlen; - gchar address[18]; - const gchar *paddr = address; struct pending_request *pending; + char source[18]; + GError *err = NULL; if (system_conn == NULL || any->path == NULL) return -1; - memset(&src, 0, sizeof(src)); - memset(&dst, 0, sizeof(dst)); - addrlen = sizeof(src); - - if (getsockname(nsk, (struct sockaddr *) &src, &addrlen) < 0) - return -1; - - ba2str(&src.rc_bdaddr, address); - - if (getpeername(nsk, (struct sockaddr *) &dst, &addrlen) < 0) - return -1; + bt_io_get(io, BT_IO_RFCOMM, &err, + BT_IO_OPT_SOURCE, source, + BT_IO_OPT_INVALID); + if (err) { + error("%s", err->message); + g_error_free(err); + return -EINVAL; + } pending = g_new0(struct pending_request, 1); pending->server = server; - pending->nsk = nsk; - - ba2str(&dst.rc_bdaddr, pending->address); + pending->io = g_io_channel_ref(io); + memcpy(pending->address, address, sizeof(pending->address)); - find_adapter(paddr, find_adapter_reply, pending); + find_adapter(source, find_adapter_reply, pending); return 0; } -- 2.47.3