diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2006-02-24 21:32:36 +0000 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2006-02-24 21:32:36 +0000 |
commit | 404d81cde832cb1d64bd5f49a60bcfd1ba096be8 (patch) | |
tree | c7ea4514dc70217efa12169de707f76d642312a6 | |
parent | 3467d91677938f2c16ccc9886b9c48bf144b407d (diff) |
Add session handling and generic error response
-rw-r--r-- | hcid/sdp.c | 83 |
1 files changed, 74 insertions, 9 deletions
@@ -33,42 +33,107 @@ #include <bluetooth/bluetooth.h> #include <bluetooth/l2cap.h> +#include <bluetooth/sdp.h> + +#include <netinet/in.h> #include "glib-ectomy.h" #include "sdp.h" +struct session { + uint16_t omtu; + uint16_t imtu; +}; + +static void session_destory(gpointer data) +{ + struct session *session_data = data; + + syslog(LOG_DEBUG, "Cleanup of SDP session"); + + if (session_data) + free(session_data); +} + static gboolean session_event(GIOChannel *chan, GIOCondition cond, gpointer data) { + unsigned char buf[672], *ptr = buf; + sdp_pdu_hdr_t *hdr; + gsize len; + GIOError err; int sk; - sk = g_io_channel_unix_get_fd(chan); + if (cond & (G_IO_HUP | G_IO_ERR)) + return FALSE; + + syslog(LOG_DEBUG, "Incoming SDP transaction"); + + err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len); + if (err == G_IO_ERROR_AGAIN) + return TRUE; - sleep(1); + hdr = (sdp_pdu_hdr_t *) ptr; + + hdr->pdu_id = SDP_ERROR_RSP; + hdr->plen = htons(2); + memset(ptr + 5, 0, 2); + + sk = g_io_channel_unix_get_fd(chan); - close(sk); + write(sk, ptr, 7); - return FALSE; + return TRUE; } static gboolean connect_event(GIOChannel *chan, GIOCondition cond, gpointer data) { GIOChannel *io; + struct session *session_data; struct sockaddr_l2 addr; - socklen_t len; + struct l2cap_options opts; + socklen_t optlen; int sk, nsk; - syslog(LOG_INFO, "Incoming SDP connection"); + syslog(LOG_DEBUG, "Incoming SDP connection"); sk = g_io_channel_unix_get_fd(chan); - len = sizeof(addr); + memset(&addr, 0, sizeof(addr)); + optlen = sizeof(addr); + + nsk = accept(sk, (struct sockaddr *) &addr, &optlen); + if (nsk < 0) { + syslog(LOG_ERR, "Can't accept L2CAP connection: %s (%d)", + strerror(errno), errno); + return TRUE; + } + + memset(&opts, 0, sizeof(opts)); + optlen = sizeof(opts); + + if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen) < 0) { + syslog(LOG_ERR, "Can't get L2CAP options: %s (%d)", + strerror(errno), errno); + close(nsk); + return TRUE; + } + + session_data = malloc(sizeof(*session_data)); + if (!session_data) { + close(nsk); + return TRUE; + } + + memset(session_data, 0, sizeof(*session_data)); - nsk = accept(sk, (struct sockaddr *) &addr, &len); + session_data->omtu = opts.omtu; + session_data->imtu = opts.imtu; io = g_io_channel_unix_new(nsk); - g_io_add_watch(io, G_IO_IN, session_event, NULL); + g_io_add_watch_full(io, 0, G_IO_IN, session_event, + session_data, session_destory); return TRUE; } |