]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib: add ringbuf socket read function
authorRafael Zalamena <rzalamena@opensourcerouting.org>
Fri, 5 Mar 2021 21:14:11 +0000 (18:14 -0300)
committerRafael Zalamena <rzalamena@opensourcerouting.org>
Fri, 5 Mar 2021 21:17:27 +0000 (18:17 -0300)
Implement new ringbuf function to do the proper socket reads without
the need of intermediary buffers.

Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
lib/ringbuf.c
lib/ringbuf.h

index 1c3c3e9753653282478e7880d83c3a853b5ef5e3..26c4e744b4973c85c9aac52a1c83a0f022c5516b 100644 (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;
+}
index b8f4d9798dc97f2391c6358271111bf30758328e..209687512bed8f2bd71bb15be7d27ae30981acca 100644 (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