From 12cbd6bdd90d05babf202d50cf0e8b555ae65dd1 Mon Sep 17 00:00:00 2001 From: danw Date: Wed, 15 Jul 1998 20:39:31 +0000 Subject: [PATCH] provide non-blocking interfaces to mr_receive and mr_accept --- lib/mr_call.c | 58 +++++++++++++++++++++++++----------- lib/mr_connect.c | 77 ++++++++++++++++++++++++++++++------------------ lib/mr_private.h | 7 +++-- 3 files changed, 94 insertions(+), 48 deletions(-) diff --git a/lib/mr_call.c b/lib/mr_call.c index d5d287d8..8193380d 100644 --- a/lib/mr_call.c +++ b/lib/mr_call.c @@ -111,43 +111,65 @@ int mr_send(int fd, struct mr_params *params) } int mr_receive(int fd, struct mr_params *reply) +{ + int status; + + memset(reply, 0, sizeof(struct mr_params)); + do + status = mr_cont_receive(fd, reply); + while (status == -1); + + return status; +} + +int mr_cont_receive(int fd, struct mr_params *reply) { u_long length, data; ssize_t size, more; char *p; int i; - memset(reply, 0, sizeof(struct mr_params)); - - size = read(fd, &data, 4); - if (size != 4) - return size ? MR_ABORTED : MR_NOT_CONNECTED; - length = ntohl(data) - 4; - reply->mr_flattened = malloc(length); if (!reply->mr_flattened) - return ENOMEM; - - for (size = 0; size < length; size += more) { - more = read(fd, reply->mr_flattened + size, length - size); - if (!more) - break; + char lbuf[4]; + + size = read(fd, lbuf, 4); + if (size != 4) + return size ? MR_ABORTED : MR_NOT_CONNECTED; + getlong(lbuf, length); + reply->mr_flattened = malloc(length); + if (!reply->mr_flattened) + return ENOMEM; + memcpy(reply->mr_flattened, lbuf, 4); + reply->mr_filled = 4; + + return -1; } - if (size != length) + else + getlong(reply->mr_flattened, length); + + more = read(fd, reply->mr_flattened + reply->mr_filled, + length - reply->mr_filled); + if (more == -1) { mr_destroy_reply(*reply); return MR_ABORTED; } - getlong(reply->mr_flattened, data); + reply->mr_filled += more; + + if (reply->mr_filled != length) + return -1; + + getlong(reply->mr_flattened + 4, data); if (data != MR_VERSION_2) { mr_destroy_reply(*reply); return MR_VERSION_MISMATCH; } - getlong(reply->mr_flattened + 4, reply->u.mr_status); - getlong(reply->mr_flattened + 8, reply->mr_argc); + getlong(reply->mr_flattened + 8, reply->u.mr_status); + getlong(reply->mr_flattened + 12, reply->mr_argc); reply->mr_argv = malloc(reply->mr_argc * sizeof(char *)); reply->mr_argl = malloc(reply->mr_argc * sizeof(int)); if (reply->mr_argc && (!reply->mr_argv || !reply->mr_argl)) @@ -156,7 +178,7 @@ int mr_receive(int fd, struct mr_params *reply) return ENOMEM; } - for (i = 0, p = reply->mr_flattened + 12; i < reply->mr_argc; i++) + for (i = 0, p = reply->mr_flattened + 16; i < reply->mr_argc; i++) { getlong(p, reply->mr_argl[i]); reply->mr_argv[i] = p + 4; diff --git a/lib/mr_connect.c b/lib/mr_connect.c index 7c8624de..517d464e 100644 --- a/lib/mr_connect.c +++ b/lib/mr_connect.c @@ -170,7 +170,7 @@ int mr_connect_internal(char *server, char *port) for (size = 0; size < sizeof(actualresponse); size += more) { more = read(fd, actualresponse + size, sizeof(actualresponse) - size); - if (!more) + if (more <= 0) break; } if (size != sizeof(actualresponse)) @@ -270,61 +270,82 @@ int mr_listen(char *port) return s; } +/* mr_accept returns -1 on accept() error, 0 on bad connection, + or connection fd on success */ + int mr_accept(int s, struct sockaddr_in *sin) { - int conn, addrlen = sizeof(struct sockaddr_in); - char lbuf[4], *buf; - long len, size, more; + int conn, addrlen = sizeof(struct sockaddr_in), nread, status; + char *buf; conn = accept(s, (struct sockaddr *)sin, &addrlen); if (conn < 0) return -1; - /* Now do mrgdb accept protocol */ - /* XXX timeout */ + do + status = mr_cont_accept(conn, &buf, &nread); + while (status == -1); - if (read(conn, lbuf, 4) != 4) - { - close(conn); - return -1; - } - getlong(lbuf, len); + return status; +} - buf = malloc(len); - if (!buf || len < 54) +int mr_cont_accept(int conn, char **buf, int *nread) +{ + long len, more; + + if (!*buf) { - close(conn); - free(buf); + char lbuf[4]; + if (read(conn, lbuf, 4) != 4) + { + close(conn); + return -1; + } + getlong(lbuf, len); + len += 4; + + *buf = malloc(len); + if (!*buf || len < 58) + { + close(conn); + free(buf); + return 0; + } + putlong(*buf, len); + *nread = 4; return -1; } + else + getlong(*buf, len); - for (size = 0; size < len; size += more) - { - more = read(conn, buf + size, len - size); - if (!more) - break; - } - if (size != len) + more = read(conn, *buf + *nread, len - *nread); + + if (more == -1 && errno != EINTR) { close(conn); - free(buf); + free(*buf); return 0; } - if (memcmp(buf, challenge + 4, 34)) + *nread += more; + + if (*nread != len) + return -1; + + if (memcmp(*buf + 4, challenge + 4, 34)) { close(conn); - free(buf); + free(*buf); return 0; } /* good enough */ - free(buf); + free(*buf); if (write(conn, response, sizeof(response)) != sizeof(response)) { close(conn); - return -1; + return 0; } return conn; } diff --git a/lib/mr_private.h b/lib/mr_private.h index 7ce27109..90a3b304 100644 --- a/lib/mr_private.h +++ b/lib/mr_private.h @@ -26,21 +26,24 @@ typedef struct mr_params { char **mr_argv; int *mr_argl; unsigned char *mr_flattened; + u_long mr_filled; } mr_params; #define CHECK_CONNECTED if (!_mr_conn) return MR_NOT_CONNECTED -#define getlong(cp, l) l = ((((unsigned char *)cp)[0] * 256 + ((unsigned char *)cp)[1]) * 256 + ((unsigned char *)cp)[2]) * 256 + ((unsigned char *)cp)[3] -#define putlong(cp, l) do { ((unsigned char *)cp)[0] = l >> 24; ((unsigned char *)cp)[1] = l >> 16; ((unsigned char *)cp)[2] = l >> 8; ((unsigned char *)cp)[3] = l; } while(0); +#define getlong(cp, l) do { l = ((((unsigned char *)cp)[0] * 256 + ((unsigned char *)cp)[1]) * 256 + ((unsigned char *)cp)[2]) * 256 + ((unsigned char *)cp)[3]; } while(0) +#define putlong(cp, l) do { ((unsigned char *)cp)[0] = l >> 24; ((unsigned char *)cp)[1] = l >> 16; ((unsigned char *)cp)[2] = l >> 8; ((unsigned char *)cp)[3] = l; } while(0) /* prototypes from mr_call.h */ int mr_do_call(struct mr_params *params, struct mr_params *reply); int mr_send(int fd, struct mr_params *params); int mr_receive(int fd, struct mr_params *params); +int mr_cont_receive(int fd, struct mr_params *params); void mr_destroy_reply(mr_params reply); /* prototypes from mr_connect.h */ int mr_accept(int s, struct sockaddr_in *sin); +int mr_cont_accept(int conn, char **buf, int *nread); int mr_connect_internal(char *server, char *port); int mr_listen(char *port); -- 2.45.2