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 <rzalamena@opensourcerouting.org>
This commit is contained in:
Rafael Zalamena 2021-03-05 18:14:11 -03:00
parent 130daf24ae
commit d9d7af1a52
2 changed files with 46 additions and 0 deletions

View File

@ -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;
}

View File

@ -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