summaryrefslogtreecommitdiffstats
path: root/common/glib-helper.c
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2008-05-14 22:16:16 +0000
committerLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2008-05-14 22:16:16 +0000
commit0094809955895c974fbe95f2d3ed13f420a6a6ed (patch)
tree0d45dff5770f69036e96539403bfd6e8bcfe7bb5 /common/glib-helper.c
parent2ce4523624b67b48da037beceffe5710144850ec (diff)
Make bt_io_callback_t to take both source and destination.
Diffstat (limited to 'common/glib-helper.c')
-rw-r--r--common/glib-helper.c142
1 files changed, 117 insertions, 25 deletions
diff --git a/common/glib-helper.c b/common/glib-helper.c
index 93ef262c..69b23d4c 100644
--- a/common/glib-helper.c
+++ b/common/glib-helper.c
@@ -43,6 +43,8 @@
#include "glib-helper.h"
+typedef int (*resolver_t) (int fd, bdaddr_t *src, bdaddr_t *dst);
+
int set_nonblocking(int fd)
{
long arg;
@@ -66,6 +68,7 @@ struct io_context {
int fd;
GIOChannel *io;
bt_io_callback_t cb;
+ resolver_t resolver;
gpointer user_data;
};
@@ -366,18 +369,91 @@ GSList *bt_string2list(const gchar *str)
return l;
}
+static inline int resolve_names(int fd, struct sockaddr *host,
+ struct sockaddr *peer, socklen_t len)
+{
+ int err;
+ socklen_t namelen;
+
+ namelen = len;
+ err = getsockname(fd, host, &namelen);
+ if (err < 0)
+ return err;
+
+ namelen = len;
+ err = getpeername(fd, peer, &namelen);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int rfcomm_resolver(int fd, bdaddr_t *src, bdaddr_t *dst)
+{
+ struct sockaddr_rc host, peer;
+ socklen_t len;
+ int err;
+
+ len = sizeof(host);
+ err = resolve_names(fd, (struct sockaddr *) &host,
+ (struct sockaddr *) &peer, len);
+ if (err < 0)
+ return err;
+
+ bacpy(src, &host.rc_bdaddr);
+ bacpy(dst, &peer.rc_bdaddr);
+
+ return 0;
+}
+
+static int l2cap_resolver(int fd, bdaddr_t *src, bdaddr_t *dst)
+{
+ struct sockaddr_l2 host, peer;
+ socklen_t len;
+ int err;
+
+ len = sizeof(host);
+ err = resolve_names(fd, (struct sockaddr *) &host,
+ (struct sockaddr *) &peer, len);
+ if (err < 0)
+ return err;
+
+ bacpy(src, &host.l2_bdaddr);
+ bacpy(dst, &peer.l2_bdaddr);
+
+ return 0;
+}
+
+static int sco_resolver(int fd, bdaddr_t *src, bdaddr_t *dst)
+{
+ struct sockaddr_sco host, peer;
+ socklen_t len;
+ int err;
+
+ len = sizeof(host);
+ err = resolve_names(fd, (struct sockaddr *) &host,
+ (struct sockaddr *) &peer, len);
+ if (err < 0)
+ return err;
+
+ bacpy(src, &host.sco_bdaddr);
+ bacpy(dst, &peer.sco_bdaddr);
+
+ return 0;
+}
+
static gboolean listen_cb(GIOChannel *chan, GIOCondition cond,
struct io_context *io_ctxt)
{
- int srv_sk, cli_sk, err = 0, ret;
+ int fd, err = 0;
GIOChannel *io;
+ struct sockaddr addr;
socklen_t len;
- struct sockaddr_rc addr;
+ bdaddr_t src, dst;
if (cond & G_IO_NVAL)
return FALSE;
- len = sizeof(ret);
if (cond & (G_IO_HUP | G_IO_ERR)) {
g_io_channel_close(chan);
g_io_channel_unref(chan);
@@ -385,22 +461,31 @@ static gboolean listen_cb(GIOChannel *chan, GIOCondition cond,
return FALSE;
}
- srv_sk = g_io_channel_unix_get_fd(chan);
+ len = sizeof(addr);
+ fd = accept(io_ctxt->fd, &addr, &len);
+ if (fd < 0)
+ goto drop;
- len = sizeof(struct sockaddr_rc);
- cli_sk = accept(srv_sk, (struct sockaddr *) &addr, &len);
- if (cli_sk < 0) {
- if (io_ctxt->cb)
- io_ctxt->cb(NULL, -errno, io_ctxt->user_data);
- return TRUE;
+ if (io_ctxt->resolver) {
+ err = io_ctxt->resolver(fd, &src, &dst);
+ if (err < 0) {
+ close(fd);
+ goto drop;
+ }
}
- io = g_io_channel_unix_new(cli_sk);
+ io = g_io_channel_unix_new(fd);
if (!io)
err = -ENOMEM;
if (io_ctxt->cb)
- io_ctxt->cb(io, err, io_ctxt->user_data);
+ io_ctxt->cb(io, err, &src, &dst, io_ctxt->user_data);
+
+ return TRUE;
+
+drop:
+ if (io_ctxt->cb)
+ io_ctxt->cb(NULL, -errno, NULL, NULL, io_ctxt->user_data);
return TRUE;
}
@@ -426,16 +511,15 @@ static int transport_listen(struct io_context *io_ctxt)
static gboolean connect_cb(GIOChannel *io, GIOCondition cond,
struct io_context *io_ctxt)
{
- int sk, err = 0, ret;
+ int err = 0, ret;
socklen_t len;
+ bdaddr_t src, dst;
if (cond & G_IO_NVAL)
return FALSE;
- sk = g_io_channel_unix_get_fd(io);
-
len = sizeof(ret);
- if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) {
+ if (getsockopt(io_ctxt->fd, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) {
err = -errno;
goto done;
}
@@ -445,11 +529,17 @@ static gboolean connect_cb(GIOChannel *io, GIOCondition cond,
goto done;
}
+ if (io_ctxt->resolver) {
+ err = io_ctxt->resolver(io_ctxt->fd, &src, &dst);
+ if (err < 0)
+ goto done;
+ }
+
io_ctxt->io = NULL;
done:
if (io_ctxt->cb)
- io_ctxt->cb(io, err, io_ctxt->user_data);
+ io_ctxt->cb(io, err, &src, &dst, io_ctxt->user_data);
if (io_ctxt->io) {
g_io_channel_close(io_ctxt->io);
g_io_channel_unref(io_ctxt->io);
@@ -682,14 +772,15 @@ static int rfcomm_connect(struct io_context *io_ctxt, const bdaddr_t *src,
return 0;
}
-static int create_io_context(struct io_context **io_ctxt, bt_io_callback_t cb,
- void *user_data)
+static int create_io_context(struct io_context **io_ctxt, gpointer cb,
+ gpointer resolver, gpointer user_data)
{
*io_ctxt = g_try_malloc0(sizeof(struct search_context));
if (!*io_ctxt)
return -ENOMEM;
(*io_ctxt)->cb = cb;
+ (*io_ctxt)->resolver = resolver;
(*io_ctxt)->user_data = user_data;
return 0;
@@ -710,7 +801,7 @@ GIOChannel *bt_rfcomm_listen(const bdaddr_t *src, uint8_t channel, uint32_t flag
struct io_context *io_ctxt;
int err;
- err = create_io_context(&io_ctxt, cb, user_data);
+ err = create_io_context(&io_ctxt, cb, rfcomm_resolver, user_data);
if (err < 0)
return NULL;
@@ -729,7 +820,7 @@ int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst,
struct io_context *io_ctxt;
int err;
- err = create_io_context(&io_ctxt, cb, user_data);
+ err = create_io_context(&io_ctxt, cb, rfcomm_resolver, user_data);
if (err < 0)
return err;
@@ -748,7 +839,7 @@ GIOChannel *bt_l2cap_listen(const bdaddr_t *src, uint16_t psm, uint16_t mtu,
struct io_context *io_ctxt;
int err;
- err = create_io_context(&io_ctxt, cb, user_data);
+ err = create_io_context(&io_ctxt, cb, l2cap_resolver, user_data);
if (err < 0)
return NULL;
@@ -762,12 +853,13 @@ GIOChannel *bt_l2cap_listen(const bdaddr_t *src, uint16_t psm, uint16_t mtu,
}
int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst,
- uint16_t psm, uint16_t mtu, bt_io_callback_t cb, void *user_data)
+ uint16_t psm, uint16_t mtu, bt_io_callback_t cb,
+ void *user_data)
{
struct io_context *io_ctxt;
int err;
- err = create_io_context(&io_ctxt, cb, user_data);
+ err = create_io_context(&io_ctxt, cb, l2cap_resolver, user_data);
if (err < 0)
return err;
@@ -786,7 +878,7 @@ int bt_sco_connect(const bdaddr_t *src, const bdaddr_t *dst,
struct io_context *io_ctxt;
int err;
- err = create_io_context(&io_ctxt, cb, user_data);
+ err = create_io_context(&io_ctxt, cb, sco_resolver, user_data);
if (err < 0)
return err;