change API to align with POSIX

This commit is contained in:
quackerd 2023-03-05 14:51:24 +01:00
parent 09281732e9
commit 2afb7741d0
6 changed files with 101 additions and 69 deletions

View File

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

16
bsock.c
View File

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

18
bsock.h
View File

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

View File

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

View File

@ -1,15 +1,17 @@
#pragma once
#include <sys/uio.h>
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/uio.h>
/* 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);

27
test.c
View File

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