179 lines
5.1 KiB
Diff
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
|
|
|