generic-poky/meta/recipes-connectivity/gsm/files/0004-Handle-read-and-write-...

179 lines
5.1 KiB
Diff

Upstream-Status: Inappropriate [not used]
From 421b0fa14fefbd13a455c20380fecddda616b41a Mon Sep 17 00:00:00 2001
From: Andrzej Zaborowski <balrog@zabor.org>
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