summaryrefslogtreecommitdiffstats
path: root/lib/ringbuf.c
diff options
context:
space:
mode:
authorRafael Zalamena <rzalamena@opensourcerouting.org>2021-03-05 22:14:11 +0100
committerRafael Zalamena <rzalamena@opensourcerouting.org>2021-03-05 22:17:27 +0100
commitd9d7af1a52d77ed0074ebb72f87678308296e74e (patch)
treee5663c17ea0780bbf043527e31a374de1f163a65 /lib/ringbuf.c
parentMerge pull request #8188 from volta-networks/fix_ospf6_cost_flag (diff)
downloadfrr-d9d7af1a52d77ed0074ebb72f87678308296e74e.tar.xz
frr-d9d7af1a52d77ed0074ebb72f87678308296e74e.zip
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>
Diffstat (limited to 'lib/ringbuf.c')
-rw-r--r--lib/ringbuf.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/lib/ringbuf.c b/lib/ringbuf.c
index 1c3c3e975..26c4e744b 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;
+}