From d1b7b2dbccd20ef72c54b7e06117ef1f92500c04 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sun, 25 Sep 2022 22:01:25 +0200 Subject: [PATCH] fd: Improve read_pattern(), rename it to read_and_compare(). The old name was a poor choice because the pattern argument actually is neither a regular expression nor a filename pattern. More importantly, the function receives a buffer size and tries to read this many bytes but then compares only the first part of the received buffer to the expected string. This is a rather weird calling convention. The only two callers are the http sender and receiver which both call the function during the initial handshake where no other data is available. Thus we can change the function to read only the minimal amount of data (length of the expected string), and drop the bufsize parameter. Remove the unnecessary log message in the error case and streamline the documentation while at it. --- fd.c | 40 +++++++++++++++++----------------------- fd.h | 2 +- http_recv.c | 2 +- http_send.c | 2 +- 4 files changed, 20 insertions(+), 26 deletions(-) diff --git a/fd.c b/fd.c index 23649451..d858ae62 100644 --- a/fd.c +++ b/fd.c @@ -260,46 +260,40 @@ int read_nonblock(int fd, void *buf, size_t sz, size_t *num_bytes) } /** - * Read a buffer and check its content for a pattern. + * Read a buffer and compare its contents to a string, ignoring case. * - * \param fd The file descriptor to receive from. - * \param pattern The expected pattern. - * \param bufsize The size of the internal buffer. - * - * This function tries to read at most \a bufsize bytes from the non-blocking - * file descriptor \a fd. If at least \p strlen(\a pattern) bytes have been - * received, the beginning of the received buffer is compared with \a pattern, - * ignoring case. + * \param fd The file descriptor to read from. + * \param expectation The expected string to compare to. * - * \return Positive if \a pattern was received, negative on errors, zero if no data - * was available to read. + * The given file descriptor is expected to be in non-blocking mode. The string + * comparison is performed using strncasecmp(3). * - * \sa \ref read_nonblock(), \sa strncasecmp(3). + * \return Zero if no data was available, positive if a buffer was read whose + * contents compare as equal to the expected string, negative otherwise. + * Possible errors: (a) not enough data was read, (b) the buffer contents + * compared as non-equal, (c) a read error occurred. In the first two cases, + * -E_READ_PATTERN is returned. In the read error case the (negative) return + * value of the underlying call to \ref read_nonblock() is returned. */ -int read_pattern(int fd, const char *pattern, size_t bufsize) +int read_and_compare(int fd, const char *expectation) { - size_t n, len; - char *buf = alloc(bufsize + 1); - int ret = read_nonblock(fd, buf, bufsize, &n); + size_t n, len = strlen(expectation); + char *buf = alloc(len + 1); + int ret = read_nonblock(fd, buf, len, &n); - buf[n] = '\0'; if (ret < 0) goto out; + buf[n] = '\0'; ret = 0; if (n == 0) goto out; ret = -E_READ_PATTERN; - len = strlen(pattern); if (n < len) goto out; - if (strncasecmp(buf, pattern, len) != 0) + if (strncasecmp(buf, expectation, len) != 0) goto out; ret = 1; out: - if (ret < 0) { - PARA_NOTICE_LOG("%s\n", para_strerror(-ret)); - PARA_NOTICE_LOG("recvd %zu bytes: %s\n", n, buf); - } free(buf); return ret; } diff --git a/fd.h b/fd.h index 9f11dc85..da480f0b 100644 --- a/fd.h +++ b/fd.h @@ -19,7 +19,7 @@ int write_ok(int fd); void valid_fd_012(void); int readv_nonblock(int fd, struct iovec *iov, int iovcnt, size_t *num_bytes); int read_nonblock(int fd, void *buf, size_t sz, size_t *num_bytes); -int read_pattern(int fd, const char *pattern, size_t bufsize); +int read_and_compare(int fd, const char *expectation); int xwrite(int fd, const char *buf, size_t len); int xwritev(int fd, struct iovec *iov, int iovcnt); int for_each_file_in_dir(const char *dirname, diff --git a/http_recv.c b/http_recv.c index 32c9e7b9..8d2add19 100644 --- a/http_recv.c +++ b/http_recv.c @@ -105,7 +105,7 @@ static int http_recv_post_monitor(struct sched *s, void *context) return 0; } if (phd->status == HTTP_SENT_GET_REQUEST) { - ret = read_pattern(rn->fd, HTTP_OK_MSG, strlen(HTTP_OK_MSG)); + ret = read_and_compare(rn->fd, HTTP_OK_MSG); if (ret < 0) { PARA_ERROR_LOG("did not receive HTTP OK message\n"); goto out; diff --git a/http_send.c b/http_send.c index 90e3ee57..429b4662 100644 --- a/http_send.c +++ b/http_send.c @@ -170,7 +170,7 @@ static void http_post_monitor(__a_unused struct sched *s) case HTTP_STREAMING: /* nothing to do */ break; case HTTP_CONNECTED: /* need to recv get request */ - ret = read_pattern(sc->fd, HTTP_GET_MSG, MAXLINE); + ret = read_and_compare(sc->fd, HTTP_GET_MSG); if (ret < 0) phsd->status = HTTP_INVALID_GET_REQUEST; else if (ret > 0) { -- 2.39.2