Upstream-Status: Inappropriate [not used] 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 63' href='#n63'>63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234