From d9d7af1a52d77ed0074ebb72f87678308296e74e Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 5 Mar 2021 18:14:11 -0300 Subject: [PATCH] lib: add ringbuf socket read function Implement new ringbuf function to do the proper socket reads without the need of intermediary buffers. Signed-off-by: Rafael Zalamena --- lib/ringbuf.c | 35 +++++++++++++++++++++++++++++++++++ lib/ringbuf.h | 11 +++++++++++ 2 files changed, 46 insertions(+) diff --git a/lib/ringbuf.c b/lib/ringbuf.c index 1c3c3e9753..26c4e744b4 100644 --- a/lib/ringbuf.c +++ b/lib/ringbuf.c @@ -131,3 +131,38 @@ void ringbuf_wipe(struct ringbuf *buf) memset(buf->data, 0x00, buf->size); ringbuf_reset(buf); } + +ssize_t ringbuf_read(struct ringbuf *buf, int sock) +{ + size_t to_read = ringbuf_space(buf); + size_t bytes_to_end = buf->size - buf->end; + ssize_t bytes_read; + struct iovec iov[2] = {}; + + /* Calculate amount of read blocks. */ + if (to_read > bytes_to_end) { + iov[0].iov_base = buf->data + buf->end; + iov[0].iov_len = bytes_to_end; + iov[1].iov_base = buf->data; + iov[1].iov_len = to_read - bytes_to_end; + } else { + iov[0].iov_base = buf->data + buf->end; + iov[0].iov_len = to_read; + } + + /* Do the system call. */ + bytes_read = readv(sock, iov, 2); + if (bytes_read <= 0) + return bytes_read; + + /* Calculate the new end. */ + if ((size_t)bytes_read > bytes_to_end) + buf->end = bytes_read - bytes_to_end; + else + buf->end += bytes_read; + + /* Set emptiness state. */ + buf->empty = (buf->start == buf->end) && (buf->empty && !bytes_read); + + return bytes_read; +} diff --git a/lib/ringbuf.h b/lib/ringbuf.h index b8f4d9798d..209687512b 100644 --- a/lib/ringbuf.h +++ b/lib/ringbuf.h @@ -126,6 +126,17 @@ void ringbuf_reset(struct ringbuf *buf); */ void ringbuf_wipe(struct ringbuf *buf); +/** + * Perform a socket/file `read()` in to the ring buffer. + * + * \param buf the ring buffer pointer. + * \param sock the file descriptor. + * \returns the number of bytes read, `0` on connection close or `-1` with + * `errno` pointing the error (see `readv()` man page for more + * information.) + */ +ssize_t ringbuf_read(struct ringbuf *buf, int sock); + #ifdef __cplusplus } #endif