diff --git a/obexd/src/bluetooth.c b/obexd/src/bluetooth.c
index 37d7b99..06dc29b 100644
--- a/obexd/src/bluetooth.c
+++ b/obexd/src/bluetooth.c
#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 cf89972..457fe06 100644
--- a/obexd/src/dbus.h
+++ b/obexd/src/dbus.h
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 e3524dd..c465d48 100644
--- a/obexd/src/manager.c
+++ b/obexd/src/manager.c
#include "obex.h"
#include "dbus.h"
#include "logging.h"
+#include "btio.h"
static const gchar *opp_record = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
<record> \
struct pending_request {
struct server *server;
- gchar address[18];
gchar *adapter_path;
+ char address[18];
guint watch;
- gint nsk;
+ GIOChannel *io;
};
struct adapter_any {
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)) {
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)
DBusMessage *reply = dbus_pending_call_steal_reply(call);
DBusMessage *msg;
DBusPendingCall *pcall;
- GIOChannel *io;
const char *paddr = pending->address;
const char *path;
DBusError derr;
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;
}