From 421b0fa14fefbd13a455c20380fecddda616b41a Mon Sep 17 00:00:00 2001 From: Andrzej Zaborowski Date: Wed, 19 Sep 2007 18:30:36 +0200 Subject: [PATCH] Handle read() and write() return values. --- include/libgsmd/libgsmd.h | 3 +- src/gsmd/usock.c | 38 ++++++++++++++++----------- src/libgsmd/lgsm_internals.h | 2 + src/libgsmd/libgsmd.c | 58 ++++++++++++++++++++++++++--------------- 4 files changed, 63 insertions(+), 38 deletions(-) diff --git a/include/libgsmd/libgsmd.h b/include/libgsmd/libgsmd.h index fc56890..db15aa9 100644 --- a/include/libgsmd/libgsmd.h +++ b/include/libgsmd/libgsmd.h @@ -65,6 +65,7 @@ extern int lgsm_subscriptions(struct lgsm_handle *lh, u_int32_t subscriptions); extern struct gsmd_msg_hdr *lgsm_gmh_fill(int type, int subtype, int payload_len); extern int lgsm_send(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh); -extern int lgsm_handle_packet(struct lgsm_handle *lh, char *buf, int len); +extern int lgsm_handle_packet(struct lgsm_handle *lh, + const char *buf, int len); #endif diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c index bac5f0c..2283600 100644 --- a/src/gsmd/usock.c +++ b/src/gsmd/usock.c @@ -1569,23 +1569,29 @@ static int gsmd_usock_user_cb(int fd, unsigned int what, void *data) struct gsmd_ucmd *ucmd, *uctmp; llist_for_each_entry_safe(ucmd, uctmp, &gu->finished_ucmds, list) { - int rc; - - rc = write(fd, &ucmd->hdr, sizeof(ucmd->hdr) + ucmd->hdr.len); - if (rc < 0) { - DEBUGP("write return %d\n", rc); - return rc; - } - if (rc == 0) { - DEBUGP("write returns zero!!\n"); - break; + const void *pos = &ucmd->hdr; + size_t len = sizeof(ucmd->hdr) + ucmd->hdr.len; + + while (len) { + ssize_t rc; + + rc = write(fd, pos, len); + if (rc < 0 && errno != EINTR) { + DEBUGP("write returned %s\n", + strerror(errno)); + return rc; + } + if (rc == 0 && pos == &ucmd->hdr) { + DEBUGP("write returns zero!!\n"); + return 0; + } + if (rc > 0) { + len -= rc; + pos += rc; + } } - if (rc != sizeof(ucmd->hdr) + ucmd->hdr.len) { - DEBUGP("short write\n"); - break; - } - - DEBUGP("successfully sent cmd %p to user %p, freeing\n", ucmd, gu); + DEBUGP("successfully sent cmd %p to user %p, " + "freeing\n", ucmd, gu); llist_del(&ucmd->list); talloc_free(ucmd); } diff --git a/src/libgsmd/lgsm_internals.h b/src/libgsmd/lgsm_internals.h index c826723..f1b1a23 100644 --- a/src/libgsmd/lgsm_internals.h +++ b/src/libgsmd/lgsm_internals.h @@ -8,6 +8,8 @@ struct lgsm_handle { int fd; lgsm_msg_handler *handler[__NUM_GSMD_MSGS]; enum lgsm_netreg_state netreg_state; + char usock_fifo[1024]; + int usock_len; }; int lgsm_send(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh); diff --git a/src/libgsmd/libgsmd.c b/src/libgsmd/libgsmd.c index 9906ea8..cc804ed 100644 --- a/src/libgsmd/libgsmd.c +++ b/src/libgsmd/libgsmd.c @@ -86,34 +86,37 @@ static int lgsm_open_backend(struct lgsm_handle *lh, const char *device) } /* handle a packet that was received on the gsmd socket */ -int lgsm_handle_packet(struct lgsm_handle *lh, char *buf, int len) +int lgsm_handle_packet(struct lgsm_handle *lh, const char *buf, int len) { struct gsmd_msg_hdr *gmh; lgsm_msg_handler *handler; int rc = 0; - while (len) { - if (len < sizeof(*gmh)) - return -EINVAL; - gmh = (struct gsmd_msg_hdr *) buf; - - if (len - sizeof(*gmh) < gmh->len) - return -EINVAL; - len -= sizeof(*gmh) + gmh->len; - buf += sizeof(*gmh) + gmh->len; - - if (gmh->msg_type >= __NUM_GSMD_MSGS) - return -EINVAL; - - handler = lh->handler[gmh->msg_type]; + if (lh->usock_len + len > sizeof(lh->usock_fifo)) + return -ENOMEM; - if (handler) + memcpy(lh->usock_fifo + lh->usock_len, buf, len); + lh->usock_len += len; + gmh = (struct gsmd_msg_hdr *) lh->usock_fifo; + while (lh->usock_len >= sizeof(*gmh) && + lh->usock_len >= sizeof(*gmh) + gmh->len) { + if (gmh->msg_type < __NUM_GSMD_MSGS && + (handler = lh->handler[gmh->msg_type])) rc |= handler(lh, gmh); - else - fprintf(stderr, "unable to handle packet type=%u\n", - gmh->msg_type); + else { + fprintf(stderr, "unable to handle packet " + "type=%u id=%u\n", + gmh->msg_type, gmh->id); + rc |= EINVAL; + } + + lh->usock_len -= gmh->len + sizeof(*gmh); + memmove(lh->usock_fifo, + lh->usock_fifo + gmh->len + sizeof(*gmh), + lh->usock_len); } - return rc; + + return -rc; } int lgsm_register_handler(struct lgsm_handle *lh, int type, lgsm_msg_handler *handler) @@ -193,8 +196,21 @@ static u_int16_t next_msg_id; int lgsm_send(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh) { + ssize_t rc; + size_t len = sizeof(*gmh) + gmh->len; + const void *pos = gmh; + gmh->id = next_msg_id++; - return send(lh->fd, (char *) gmh, sizeof(*gmh) + gmh->len, 0); + while (len) { + rc = send(lh->fd, pos, len, 0); + if (rc < 0 && errno != EINTR) + return -errno; + if (rc > 0) { + len -= rc; + pos += rc; + } + } + return 0; } struct gsmd_msg_hdr *lgsm_gmh_fill(int type, int subtype, int payload_len) -- 1.5.2.1