diff options
Diffstat (limited to 'common/glib-helper.c')
-rw-r--r-- | common/glib-helper.c | 142 |
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; |