From 50f6b061054d1aa323521fa25c5e6c9576712f72 Mon Sep 17 00:00:00 2001 From: Aki Niemi Date: Tue, 16 Nov 2010 17:06:11 +0200 Subject: [PATCH] gisi: Split indication to use separate socket Some resources send INDs with non-zero unique transaction ID, which can conflict with pending RESPs. To fix this, we use two sockets, one dedicated for INDs, and one dedicated to REQs, NTFs and RESPs. --- gisi/modem.c | 63 ++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/gisi/modem.c b/gisi/modem.c index 72b9004..55d69af 100644 --- a/gisi/modem.c +++ b/gisi/modem.c @@ -56,8 +56,10 @@ struct _GIsiModem { unsigned index; GHashTable *services; gboolean subs_pending; - int fd; - guint source; + int req_fd; + int ind_fd; + guint req_watch; + guint ind_watch; GIsiNotifyFunc debug; void *ddata; }; @@ -134,7 +136,8 @@ static void pending_dispatch(GIsiPending *pend, GIsiMessage *msg) pend->notify(msg, pend->data); } -static void service_dispatch(GIsiServiceMux *mux, GIsiMessage *msg) +static void service_dispatch(GIsiServiceMux *mux, GIsiMessage *msg, + gboolean is_indication) { uint8_t msgid = g_isi_msg_id(msg); uint8_t utid = g_isi_msg_utid(msg); @@ -166,7 +169,7 @@ static void service_dispatch(GIsiServiceMux *mux, GIsiMessage *msg) pending_dispatch(pend, msg); } else if (pend->type == GISI_MESSAGE_TYPE_RESP && - pend->utid == utid) { + !is_indication && pend->utid == utid) { pending_dispatch(pend, msg); pend->notify = NULL; @@ -230,12 +233,14 @@ static gboolean isi_callback(GIOChannel *channel, GIOCondition cond, { GIsiModem *modem = data; int len; + int fd; if (cond & (G_IO_NVAL|G_IO_HUP)) { g_warning("Unexpected event on PhoNet channel %p", channel); return FALSE; } + fd = g_io_channel_unix_get_fd(channel); len = g_isi_phonet_peek_length(channel); if (len > 0) { @@ -273,7 +278,7 @@ static gboolean isi_callback(GIOChannel *channel, GIOCondition cond, if (g_isi_msg_id(&msg) == COMMON_MESSAGE) common_message_decode(mux, &msg); - service_dispatch(mux, &msg); + service_dispatch(mux, &msg, fd == modem->ind_fd); } return TRUE; } @@ -281,7 +286,8 @@ static gboolean isi_callback(GIOChannel *channel, GIOCondition cond, GIsiModem *g_isi_modem_create(unsigned index) { GIsiModem *modem; - GIOChannel *channel; + GIOChannel *inds; + GIOChannel *reqs; if (index == 0) { errno = ENODEV; @@ -294,17 +300,25 @@ GIsiModem *g_isi_modem_create(unsigned index) return NULL; } - channel = g_isi_phonet_new(index); - if (!channel) { + inds = g_isi_phonet_new(index); + reqs = g_isi_phonet_new(index); + + if (!inds || !reqs) { g_free(modem); return NULL; } - modem->fd = g_io_channel_unix_get_fd(channel); - modem->source = g_io_add_watch(channel, + modem->req_fd = g_io_channel_unix_get_fd(reqs); + modem->req_watch = g_io_add_watch(reqs, + G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, + isi_callback, modem); + modem->ind_fd = g_io_channel_unix_get_fd(inds); + modem->ind_watch = g_io_add_watch(inds, G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, isi_callback, modem); - g_io_channel_unref(channel); + + g_io_channel_unref(reqs); + g_io_channel_unref(inds); modem->index = index; modem->services = g_hash_table_new_full(g_int_hash, g_int_equal, @@ -328,7 +342,7 @@ static void service_name_register(GIsiServiceMux *mux) }; uint16_t object = 0; - if (ioctl(mux->modem->fd, SIOCPNGETOBJECT, &object) < 0) { + if (ioctl(mux->modem->req_fd, SIOCPNGETOBJECT, &object) < 0) { g_warning("ioctl(SIOCPNGETOBJECT): %s", strerror(errno)); return; } @@ -337,8 +351,8 @@ static void service_name_register(GIsiServiceMux *mux) msg[8] = object >> 8; msg[9] = object & 0xFF; - sendto(mux->modem->fd, msg, sizeof(msg), MSG_NOSIGNAL, (void *)&namesrv, - sizeof(namesrv)); + sendto(mux->modem->req_fd, msg, sizeof(msg), MSG_NOSIGNAL, + (void *)&namesrv, sizeof(namesrv)); } static void service_name_deregister(GIsiServiceMux *mux) @@ -348,8 +362,8 @@ static void service_name_deregister(GIsiServiceMux *mux) 0, 0, 0, mux->resource, }; - sendto(mux->modem->fd, msg, sizeof(msg), MSG_NOSIGNAL, (void *)&namesrv, - sizeof(namesrv)); + sendto(mux->modem->req_fd, msg, sizeof(msg), MSG_NOSIGNAL, + (void *)&namesrv, sizeof(namesrv)); } static gboolean modem_subs_update(gpointer data) @@ -376,7 +390,7 @@ static gboolean modem_subs_update(gpointer data) } msg[2] = count; - sendto(modem->fd, msg, 3 + msg[2], MSG_NOSIGNAL, (void *)&commgr, + sendto(modem->ind_fd, msg, 3 + msg[2], MSG_NOSIGNAL, (void *)&commgr, sizeof(commgr)); modem->subs_pending = FALSE; @@ -485,6 +499,13 @@ void g_isi_modem_destroy(GIsiModem *modem) g_hash_table_foreach_remove(modem->services, service_finalize, modem); g_hash_table_unref(modem->services); + + if (modem->ind_watch) + g_source_remove(modem->ind_watch); + + if (modem->req_watch) + g_source_remove(modem->req_watch); + g_free(modem); } @@ -641,7 +662,7 @@ GIsiPending *g_isi_request_vsendto(GIsiModem *modem, struct sockaddr_pn *dst, if (modem->debug) vdebug(dst, _iov, 1 + iovlen, len, modem->debug, modem->ddata); - ret = sendmsg(modem->fd, &msg, MSG_NOSIGNAL); + ret = sendmsg(modem->req_fd, &msg, MSG_NOSIGNAL); if (ret == -1) goto error; @@ -866,7 +887,7 @@ int g_isi_modem_vsendto(GIsiModem *modem, struct sockaddr_pn *dst, if (modem->debug) vdebug(dst, iov, iovlen, len, modem->debug, modem->ddata); - ret = sendmsg(modem->fd, &msg, MSG_NOSIGNAL); + ret = sendmsg(modem->req_fd, &msg, MSG_NOSIGNAL); if (ret == -1) return -errno; @@ -903,8 +924,8 @@ static int version_get_send(GIsiModem *modem, GIsiPending *ping) if (g_slist_find_custom(mux->pending, ping, utid_equal)) return -EBUSY; - ret = sendto(modem->fd, msg, sizeof(msg), MSG_NOSIGNAL, (void *)&dst, - sizeof(dst)); + ret = sendto(modem->req_fd, msg, sizeof(msg), MSG_NOSIGNAL, + (void *)&dst, sizeof(dst)); if (ret == -1) return -errno; -- 2.7.4