diff --git a/CMakeLists.txt b/CMakeLists.txt index a31eef4..9f2273b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,16 +2,21 @@ cmake_minimum_required(VERSION 3.10.0) project(bsock C) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -set(CFLAGS -Wall -Wextra -Werror -std=c17 -march=native -O2 -g) -set(LIBVER 1.0.0) +set(CFLAGS -Wall -Wextra -Werror -std=c17 -march=native -O3 -g -DNDEBUG) +set(CFLAGS_DBG -Wall -Wextra -Werror -std=c17 -march=native -Og -g) +set(LIBVER 1.1.0) add_library(bsock SHARED bsock.c ringbuf.c) target_compile_options(bsock PRIVATE ${CFLAGS}) target_include_directories(bsock PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +add_library(bsock_debug SHARED bsock.c ringbuf.c) +target_compile_options(bsock_debug PRIVATE ${CFLAGS_DBG}) +target_include_directories(bsock_debug PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + add_executable(test test.c) -target_link_libraries(test PRIVATE bsock) -target_compile_options(test PRIVATE ${CFLAGS}) +target_link_libraries(test PRIVATE bsock_debug) +target_compile_options(test PRIVATE ${CFLAGS_DBG}) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/bsock.pc.in diff --git a/bsock.c b/bsock.c index fd1d9f1..a9fb30b 100644 --- a/bsock.c +++ b/bsock.c @@ -4,25 +4,25 @@ #include "ringbuf.h" static ssize_t -bsock_posix_io_read(void * ctx, void *buf, size_t nbytes) +bsock_posix_io_read(void *ctx, void *buf, size_t nbytes) { return read((int)(uintptr_t)ctx, buf, nbytes); } static ssize_t -bsock_posix_io_write(void * ctx, void *buf, size_t nbytes) +bsock_posix_io_write(void *ctx, void *buf, size_t nbytes) { return write((int)(uintptr_t)ctx, buf, nbytes); } static ssize_t -bsock_posix_io_readv(void * ctx, const struct iovec *iovec, int nvec) +bsock_posix_io_readv(void *ctx, const struct iovec *iovec, int nvec) { return readv((int)(uintptr_t)ctx, iovec, nvec); } static ssize_t -bsock_posix_io_writev(void * ctx, const struct iovec *iovec, int nvec) +bsock_posix_io_writev(void *ctx, const struct iovec *iovec, int nvec) { return writev((int)(uintptr_t)ctx, iovec, nvec); } @@ -39,7 +39,7 @@ bsock_io_posix() } struct bsock * -bsock_create(void * io_ctx, struct bsock_ringbuf_io *io, size_t rbuf_sz, size_t wbuf_sz) +bsock_create(void *io_ctx, struct bsock_ringbuf_io *io, size_t rbuf_sz, size_t wbuf_sz) { struct bsock *bsock = malloc(sizeof(struct bsock)); if (bsock == NULL) { @@ -104,13 +104,15 @@ bsock_peek(struct bsock *bsock, char *buf, size_t len) int bsock_flush(struct bsock *bsock) { - return bsock_ringbuf_flush(&bsock->wbuf, bsock->io_ctx, &bsock->io, bsock_ringbuf_size(&bsock->wbuf)); + return bsock_ringbuf_flush(&bsock->wbuf, bsock->io_ctx, &bsock->io, + bsock_ringbuf_size(&bsock->wbuf)); } int bsock_poll(struct bsock *bsock) { - return bsock_ringbuf_poll(&bsock->rbuf, bsock->io_ctx, &bsock->io, bsock_ringbuf_free_size(&bsock->rbuf)); + return bsock_ringbuf_poll(&bsock->rbuf, bsock->io_ctx, &bsock->io, + bsock_ringbuf_free_size(&bsock->rbuf)); } int diff --git a/bsock.h b/bsock.h index 07bc915..7f0f845 100644 --- a/bsock.h +++ b/bsock.h @@ -34,15 +34,15 @@ bsock_init(struct bsock *bsock, void *io_ctx, struct bsock_ringbuf_io *io, /** * returns: - * success: 0 - * failure: -1 + errno (ERANGE if not enough data present) + * success: # of bytes written + * failure: -1 + errno */ int bsock_write(struct bsock *sock, char *buf, size_t len); /** * returns: - * success: 0 - * failure: -1 + errno (ERANGE if not enough data present) + * success: # of bytes read + * failure: -1 + errno */ int bsock_read(struct bsock *sock, char *buf, size_t len); @@ -52,28 +52,28 @@ int bsock_read(struct bsock *sock, char *buf, size_t len); int bsock_read_avail_size(struct bsock *sock); /** - * returns: # of bytes available for write + * returns: # of bytes available for write before forcing a flush */ int bsock_write_avail_size(struct bsock *sock); /** * returns: - * success: 0 - * failure: -1 + errno (ERANGE if not enough data present) + * success: # of bytes read + * failure: -1 + errno */ int bsock_peek(struct bsock *sock, char *buf, size_t len); /** * returns: * success: # of bytes polled - * failure: -1 + errno (ERANGE if not enough data present) + * failure: -1 + errno */ int bsock_poll(struct bsock *sock); /** * returns: * success: # of bytes flushed - * failure: -1 + errno (ERANGE if not enough data present) + * failure: -1 + errno */ int bsock_flush(struct bsock *sock); diff --git a/ringbuf.c b/ringbuf.c index e50277f..36b6b0a 100644 --- a/ringbuf.c +++ b/ringbuf.c @@ -27,9 +27,9 @@ bsock_ringbuf_wrap_ptr(struct bsock_ringbuf *rb, char *ptr) static void bsock_ringbuf_peek_nochk(struct bsock_ringbuf *rb, char *buf, size_t len) { - assert(len <= rb->sz); + assert(len <= rb->sz && len > 0); - if (rb->end > rb->start) { + if (rb->end >= rb->start) { // no wrapping memcpy(buf, rb->start, len); } else { @@ -47,37 +47,52 @@ bsock_ringbuf_peek_nochk(struct bsock_ringbuf *rb, char *buf, size_t len) int bsock_ringbuf_peek(struct bsock_ringbuf *rb, char *buf, size_t len) { - if (len > rb->sz) { - errno = ERANGE; - return -1; + if (len == 0) { + return 0; } - bsock_ringbuf_peek_nochk(rb, buf, len); - return 0; + if (len > rb->sz) { + len = rb->sz; + } + + if (len > 0) { + bsock_ringbuf_peek_nochk(rb, buf, len); + } + return len; } int bsock_ringbuf_read(struct bsock_ringbuf *rb, char *buf, size_t len) { - if (len > rb->sz) { - errno = ERANGE; - return -1; + if (len == 0) { + return 0; } - bsock_ringbuf_peek_nochk(rb, buf, len); - rb->start = bsock_ringbuf_wrap_ptr(rb, rb->start + len); - rb->sz -= len; - return 0; + if (len > rb->sz) { + len = rb->sz; + } + + if (len > 0) { + bsock_ringbuf_peek_nochk(rb, buf, len); + rb->start = bsock_ringbuf_wrap_ptr(rb, rb->start + len); + rb->sz -= len; + } + return len; } int -bsock_ringbuf_write(struct bsock_ringbuf *rb, void * ctx, struct bsock_ringbuf_io * io, char *buf, size_t len) +bsock_ringbuf_write(struct bsock_ringbuf *rb, void *ctx, struct bsock_ringbuf_io *io, char *buf, + size_t len) { + if (len == 0) { + return 0; + } + size_t free_sz = rb->max_sz - rb->sz; if (len > free_sz) { int ret = bsock_ringbuf_flush(rb, ctx, io, rb->sz); if (ret < 0) { - return -1; + return ret; } assert(rb->sz == 0); @@ -102,19 +117,23 @@ bsock_ringbuf_write(struct bsock_ringbuf *rb, void * ctx, struct bsock_ringbuf_i rb->sz += len; rb->end = bsock_ringbuf_wrap_ptr(rb, rb->end + len); - return 0; + return len; } int -bsock_ringbuf_poll(struct bsock_ringbuf *rb, void * ctx, struct bsock_ringbuf_io * io, size_t len) +bsock_ringbuf_poll(struct bsock_ringbuf *rb, void *ctx, struct bsock_ringbuf_io *io, size_t len) { size_t free_sz = rb->max_sz - rb->sz; - if (len > free_sz) { - errno = ERANGE; - return -1; + + if (len == 0 || free_sz == 0) { + return 0; } - int ret = 0; + if (len > free_sz) { + len = free_sz; + } + + int ret; if (rb->end >= rb->start) { // no wrapping size_t rem_size = rb->buf + rb->max_sz - rb->end; @@ -141,14 +160,17 @@ bsock_ringbuf_poll(struct bsock_ringbuf *rb, void * ctx, struct bsock_ringbuf_io } int -bsock_ringbuf_flush(struct bsock_ringbuf *rb, void * ctx, struct bsock_ringbuf_io * io, size_t len) +bsock_ringbuf_flush(struct bsock_ringbuf *rb, void *ctx, struct bsock_ringbuf_io *io, size_t len) { - if (len > rb->sz) { - errno = ERANGE; - return -1; + if (rb->sz == 0 || len == 0) { + return 0; } - int ret = 0; + if (len > rb->sz) { + len = rb->sz; + } + + int ret; if (rb->end >= rb->start) { // no wrapping ret = io->write(ctx, rb->start, len); diff --git a/ringbuf.h b/ringbuf.h index f9412f6..b3d8492 100644 --- a/ringbuf.h +++ b/ringbuf.h @@ -1,15 +1,17 @@ #pragma once +#include + #include #include #include #include #include #include -#include -/* Both functions should return -1 on error otherwise the # of bytes written. errno should be used to set the error code */ -typedef ssize_t (*bsock_ringbuf_io_fn) (void * ctx, void * buf, size_t nbytes); -typedef ssize_t (*bsock_ringbuf_iov_fn) (void * ctx, const struct iovec *iov, int iovcnt); +/* Both functions should return -1 on error otherwise the # of bytes written. errno should be used + * to set the error code */ +typedef ssize_t (*bsock_ringbuf_io_fn)(void *ctx, void *buf, size_t nbytes); +typedef ssize_t (*bsock_ringbuf_iov_fn)(void *ctx, const struct iovec *iov, int iovcnt); struct bsock_ringbuf_io { bsock_ringbuf_io_fn read; @@ -26,7 +28,6 @@ struct bsock_ringbuf { size_t max_sz; }; - static inline size_t bsock_ringbuf_size(struct bsock_ringbuf *rb) { @@ -74,18 +75,21 @@ int bsock_ringbuf_read(struct bsock_ringbuf *rb, char *buf, size_t len); * success: # of bytes written * failure: -1 + errno */ -int bsock_ringbuf_write(struct bsock_ringbuf *rb, void * ctx, struct bsock_ringbuf_io * io, char *buf, size_t len); +int bsock_ringbuf_write(struct bsock_ringbuf *rb, void *ctx, struct bsock_ringbuf_io *io, char *buf, + size_t len); /** * returns: * success: # of bytes read * failure: -1 + errno (ERANGE if not enough data present) */ -int bsock_ringbuf_poll(struct bsock_ringbuf *rb, void * ctx, struct bsock_ringbuf_io *io, size_t len); +int bsock_ringbuf_poll(struct bsock_ringbuf *rb, void *ctx, struct bsock_ringbuf_io *io, + size_t len); /** * returns: * success: # of bytes written * failure: -1 + errno (ERANGE if not enough data present) */ -int bsock_ringbuf_flush(struct bsock_ringbuf *rb, void * ctx, struct bsock_ringbuf_io *io, size_t len); +int bsock_ringbuf_flush(struct bsock_ringbuf *rb, void *ctx, struct bsock_ringbuf_io *io, + size_t len); diff --git a/test.c b/test.c index 2fb0fbb..68c5cea 100644 --- a/test.c +++ b/test.c @@ -5,7 +5,7 @@ #include "ringbuf.h" static int -ringbuf_verify(struct bsock_ringbuf *buf, char * start, size_t sz) +ringbuf_verify(struct bsock_ringbuf *buf, char *start, size_t sz) { int ret = 1; @@ -22,11 +22,12 @@ ringbuf_verify(struct bsock_ringbuf *buf, char * start, size_t sz) } static void -assert_write(struct bsock_ringbuf *rbuf, void * ctx, struct bsock_ringbuf_io * io, char *buf, size_t sz) +assert_write(struct bsock_ringbuf *rbuf, void *ctx, struct bsock_ringbuf_io *io, char *buf, + size_t sz) { char *start = rbuf->start; size_t ssz = rbuf->sz; - assert(bsock_ringbuf_write(rbuf, ctx, io, buf, sz) == 0); + assert(bsock_ringbuf_write(rbuf, ctx, io, buf, sz) == (int)sz); assert(ringbuf_verify(rbuf, start, ssz + sz)); } @@ -35,7 +36,7 @@ assert_read(struct bsock_ringbuf *rbuf, char *buf, size_t sz) { char *start = rbuf->start; size_t ssz = rbuf->sz; - assert(bsock_ringbuf_read(rbuf, buf, sz) == 0); + assert(bsock_ringbuf_read(rbuf, buf, sz) == (int)(sz)); if (start + sz > rbuf->buf + rbuf->max_sz) { start = start + sz - rbuf->max_sz; } else { @@ -77,14 +78,13 @@ bsock_test(void) printf("ringbuf - read overflow\n"); memset(buf3, 0, 1024); bsock_ringbuf_init(&rbuf, buf, 1024); - assert_write(&rbuf, NULL, NULL, sbuf, 128); - assert(bsock_ringbuf_read(&rbuf, buf3, 129) == -1); - assert(errno == ERANGE); + assert_write(&rbuf, NULL, NULL, sbuf, 128); + assert(bsock_ringbuf_read(&rbuf, buf3, 129) == 128); printf("ringbuf - read/write [1024]\n"); memset(buf3, 0, 1024); bsock_ringbuf_init(&rbuf, buf, 1024); - assert_write(&rbuf, NULL, NULL, sbuf, 1024); + assert_write(&rbuf, NULL, NULL, sbuf, 1024); assert_read(&rbuf, buf3, 1024); assert(memcmp(sbuf, buf3, 128) == 0); @@ -119,9 +119,9 @@ bsock_test(void) assert(pipe(pipes) == 0); memset(buf3, 0, 1024); bsock_ringbuf_init(&rbuf, buf, 1024); - assert_write(&rbuf, (void*)(uintptr_t)pipes[1], &io, sbuf, 768); - assert(bsock_ringbuf_write(&rbuf, (void*)(uintptr_t)pipes[1], &io, sbuf, 512)); - assert(ringbuf_verify(&rbuf, 0, 512)); + assert_write(&rbuf, (void *)(uintptr_t)pipes[1], &io, sbuf, 768); + assert(bsock_ringbuf_write(&rbuf, (void *)(uintptr_t)pipes[1], &io, sbuf, 512) == 512); + assert(ringbuf_verify(&rbuf, buf + 768, 512)); assert(read(pipes[0], buf3, 768) == 768); assert(memcmp(sbuf, buf3, 768) == 0); assert_read(&rbuf, buf3, 512); @@ -131,9 +131,8 @@ bsock_test(void) assert(pipe(pipes) == 0); memset(buf3, 0, 1024); bsock_ringbuf_init(&rbuf, buf, 768); - assert_write(&rbuf, (void*)(uintptr_t)pipes[1], &io, sbuf, 512); - assert(bsock_ringbuf_write(&rbuf, (void*)(uintptr_t)pipes[1], &io, sbuf, 1024)); - assert(ringbuf_verify(struct bsock_ringbuf *buf, char *start, size_t sz)) + assert_write(&rbuf, (void *)(uintptr_t)pipes[1], &io, sbuf, 512); + assert(bsock_ringbuf_write(&rbuf, (void *)(uintptr_t)pipes[1], &io, sbuf, 1024)); assert(read(pipes[0], buf3, 512) == 512); assert(memcmp(sbuf, buf3, 512) == 0); assert(read(pipes[0], buf3, 1024) == 1024);