diff options
Diffstat (limited to 'lib9p/tests')
-rw-r--r-- | lib9p/tests/client_config/config.h | 1 | ||||
-rw-r--r-- | lib9p/tests/test_compile_config/config.h | 2 | ||||
-rw-r--r-- | lib9p/tests/test_server/config/config.h | 3 | ||||
-rw-r--r-- | lib9p/tests/test_server/fs_flush.c | 46 | ||||
-rw-r--r-- | lib9p/tests/test_server/fs_flush.h | 1 | ||||
-rw-r--r-- | lib9p/tests/test_server/fs_shutdown.c | 33 | ||||
-rw-r--r-- | lib9p/tests/test_server/fs_shutdown.h | 1 | ||||
-rw-r--r-- | lib9p/tests/test_server/fs_whoami.c | 45 | ||||
-rw-r--r-- | lib9p/tests/test_server/fs_whoami.h | 1 | ||||
-rw-r--r-- | lib9p/tests/test_server/main.c | 33 | ||||
-rw-r--r-- | lib9p/tests/testclient-hangup.c | 100 | ||||
-rw-r--r-- | lib9p/tests/testclient-hangup.explog | 14 | ||||
-rw-r--r-- | lib9p/tests/testclient-sess.c | 23 | ||||
-rw-r--r-- | lib9p/tests/testclient-sess.explog | 2 |
14 files changed, 206 insertions, 99 deletions
diff --git a/lib9p/tests/client_config/config.h b/lib9p/tests/client_config/config.h index bcf030d..4bba4ec 100644 --- a/lib9p/tests/client_config/config.h +++ b/lib9p/tests/client_config/config.h @@ -7,7 +7,6 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ -#define CONFIG_9P_MAX_ERR_SIZE 128 #define CONFIG_9P_MAX_9P2000_e_WELEM 16 #define CONFIG_9P_ENABLE_9P2000 1 /* bool */ diff --git a/lib9p/tests/test_compile_config/config.h b/lib9p/tests/test_compile_config/config.h index 02cb8e5..cb3709e 100644 --- a/lib9p/tests/test_compile_config/config.h +++ b/lib9p/tests/test_compile_config/config.h @@ -9,11 +9,11 @@ /* 9P *************************************************************************/ -#define CONFIG_9P_MAX_ERR_SIZE 128 #define CONFIG_9P_MAX_9P2000_e_WELEM 16 /* 9P_SRV *********************************************************************/ +#define CONFIG_9P_SRV_MAX_ERR_SIZE 128 #define CONFIG_9P_SRV_MAX_MSG_SIZE ((4*1024)+24) #define CONFIG_9P_SRV_MAX_HOSTMSG_SIZE CONFIG_9P_SRV_MAX_MSG_SIZE+16 diff --git a/lib9p/tests/test_server/config/config.h b/lib9p/tests/test_server/config/config.h index f49894b..a657f60 100644 --- a/lib9p/tests/test_server/config/config.h +++ b/lib9p/tests/test_server/config/config.h @@ -12,8 +12,6 @@ /* 9P *************************************************************************/ -#define CONFIG_9P_MAX_ERR_SIZE 128 /* 128 is what Plan 9 4e uses */ - #define CONFIG_9P_ENABLE_9P2000 1 /* bool */ #define CONFIG_9P_ENABLE_9P2000_u 1 /* bool */ #define CONFIG_9P_ENABLE_9P2000_e 0 /* bool */ @@ -42,6 +40,7 @@ * (8*1024)+160 in 2e and 3e. */ #define CONFIG_9P_SRV_MAX_MSG_SIZE ((4*1024)+24) +#define CONFIG_9P_SRV_MAX_ERR_SIZE 128 /* 128 is what Plan 9 4e uses */ /** * Maximum host-data-structure size. A message may be larger in * unmarshaled-host-structures than marshaled-net-bytes due to (1) diff --git a/lib9p/tests/test_server/fs_flush.c b/lib9p/tests/test_server/fs_flush.c index e6408d7..63a52af 100644 --- a/lib9p/tests/test_server/fs_flush.c +++ b/lib9p/tests/test_server/fs_flush.c @@ -31,10 +31,10 @@ static struct lib9p_qid flush_file_qid(struct flush_file *self) { }; } -static struct lib9p_srv_stat flush_file_stat(struct flush_file *self, struct lib9p_srv_ctx *ctx) { +static lib9p_srv_stat_or_error flush_file_stat(struct flush_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - return (struct lib9p_srv_stat){ + return ERROR_NEW_VAL(lib9p_srv_stat, ((struct lib9p_srv_stat){ .qid = flush_file_qid(self), .mode = 0444, .atime_sec = UTIL9P_ATIME, @@ -45,29 +45,29 @@ static struct lib9p_srv_stat flush_file_stat(struct flush_file *self, struct lib .owner_gid = { .name = lib9p_str("root"), .num = 0 }, .last_modifier_uid = { .name = lib9p_str("root"), .num = 0 }, .extension = lib9p_str(NULL), - }; + })); } -static void flush_file_wstat(struct flush_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) { +static error flush_file_wstat(struct flush_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "cannot wstat API file"); + return error_new(E_POSIX_EROFS, "cannot wstat API file"); } -static void flush_file_remove(struct flush_file *self, struct lib9p_srv_ctx *ctx) { +static error flush_file_remove(struct flush_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "cannot remove API file"); + return error_new(E_POSIX_EROFS, "cannot remove API file"); } -LIB9P_SRV_NOTDIR(struct flush_file, flush_file) +LIB9P_SRV_NOTDIR(struct flush_file, flush_file); -static lo_interface lib9p_srv_fio flush_file_fopen(struct flush_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { +static lib9p_srv_fio_or_error flush_file_fopen(struct flush_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { assert(self); assert(ctx); struct flush_fio *ret = heap_alloc(1, struct flush_fio); ret->parent = self; - return lo_box_flush_fio_as_lib9p_srv_fio(ret); + return ERROR_NEW_VAL(lib9p_srv_fio, LO_BOX(lib9p_srv_fio, ret)); } /* srv_fio ********************************************************************/ @@ -87,19 +87,17 @@ static uint32_t flush_fio_iounit(struct flush_fio *self) { return 0; } -static uint32_t flush_fio_pwrite(struct flush_fio *LM_UNUSED(self), +static uint32_t_or_error flush_fio_pwrite(struct flush_fio *LM_UNUSED(self), struct lib9p_srv_ctx *LM_UNUSED(ctx), void *LM_UNUSED(buf), uint32_t LM_UNUSED(byte_count), uint64_t LM_UNUSED(offset)) { assert_notreached("not writable"); } -static void flush_fio_pread(struct flush_fio *self, struct lib9p_srv_ctx *ctx, - uint32_t byte_count, uint64_t LM_UNUSED(byte_offset), - struct iovec *ret) { +static iovec_or_error flush_fio_pread(struct flush_fio *self, struct lib9p_srv_ctx *ctx, + uint32_t byte_count, uint64_t LM_UNUSED(byte_offset)) { assert(self); assert(ctx); - assert(ret); /* Wait for first Tflush */ while (!lib9p_srv_flush_requested(ctx)) @@ -111,21 +109,21 @@ static void flush_fio_pread(struct flush_fio *self, struct lib9p_srv_ctx *ctx, while (cr_chan_num_waiters(&ctx->flush_ch) != self->parent->flush_cnt) cr_yield(); + /* Yield one more time, just because. */ + cr_yield(); + /* Return */ switch (self->parent->flush_behavior) { case FLUSH_READ: - *ret = (struct iovec){ + return ERROR_NEW_VAL(iovec, ((struct iovec){ .iov_base = "Sloth\n", .iov_len = 6 < byte_count ? 6 : byte_count, - }; - break; + })); case FLUSH_ERROR: - lib9p_srv_acknowledge_flush(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_ECANCELED, "request canceled by flush"); - break; + return ERROR_NEW_ERR(iovec, error_new(E_POSIX_EAGAIN, "request canceled by flush")); case FLUSH_SILENT: - lib9p_srv_acknowledge_flush(ctx); - break; + return ERROR_NEW_ERR(iovec, error_new(E_POSIX_ECANCELED, "request canceled by flush")); + default: + assert_notreached("invalid flush_behavior"); } - cr_yield(); } diff --git a/lib9p/tests/test_server/fs_flush.h b/lib9p/tests/test_server/fs_flush.h index 2b08850..023434b 100644 --- a/lib9p/tests/test_server/fs_flush.h +++ b/lib9p/tests/test_server/fs_flush.h @@ -22,6 +22,5 @@ struct flush_file { } flush_behavior; }; LO_IMPLEMENTATION_H(lib9p_srv_file, struct flush_file, flush_file); -#define lo_box_flush_file_as_lib9p_srv_file(obj) util9p_box(flush_file, obj) #endif /* _LIB9P_TESTS_TEST_SERVER_FS_FLUSH_H_ */ diff --git a/lib9p/tests/test_server/fs_shutdown.c b/lib9p/tests/test_server/fs_shutdown.c index d4ae67e..079442e 100644 --- a/lib9p/tests/test_server/fs_shutdown.c +++ b/lib9p/tests/test_server/fs_shutdown.c @@ -30,10 +30,10 @@ static struct lib9p_qid shutdown_file_qid(struct shutdown_file *self) { }; } -static struct lib9p_srv_stat shutdown_file_stat(struct shutdown_file *self, struct lib9p_srv_ctx *ctx) { +static lib9p_srv_stat_or_error shutdown_file_stat(struct shutdown_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - return (struct lib9p_srv_stat){ + return ERROR_NEW_VAL(lib9p_srv_stat, ((struct lib9p_srv_stat){ .qid = shutdown_file_qid(self), .mode = 0222 | LIB9P_DM_APPEND, .atime_sec = UTIL9P_ATIME, @@ -44,29 +44,29 @@ static struct lib9p_srv_stat shutdown_file_stat(struct shutdown_file *self, stru .owner_gid = { .name=lib9p_str("root"), .num=0 }, .last_modifier_uid = { .name=lib9p_str("root"), .num=0 }, .extension = lib9p_str(NULL), - }; + })); } -static void shutdown_file_wstat(struct shutdown_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) { +static error shutdown_file_wstat(struct shutdown_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "cannot wstat API file"); + return error_new(E_POSIX_EROFS, "cannot wstat API file"); } -static void shutdown_file_remove(struct shutdown_file *self, struct lib9p_srv_ctx *ctx) { +static error shutdown_file_remove(struct shutdown_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "cannot remove API file"); + return error_new(E_POSIX_EROFS, "cannot remove API file"); } -LIB9P_SRV_NOTDIR(struct shutdown_file, shutdown_file) +LIB9P_SRV_NOTDIR(struct shutdown_file, shutdown_file); -static lo_interface lib9p_srv_fio shutdown_file_fopen(struct shutdown_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { +static lib9p_srv_fio_or_error shutdown_file_fopen(struct shutdown_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { assert(self); assert(ctx); struct shutdown_fio *ret = heap_alloc(1, struct shutdown_fio); ret->parent = self; - return lo_box_shutdown_fio_as_lib9p_srv_fio(ret); + return ERROR_NEW_VAL(lib9p_srv_fio, LO_BOX(lib9p_srv_fio, ret)); } /* srv_fio ********************************************************************/ @@ -86,19 +86,18 @@ static uint32_t shutdown_fio_iounit(struct shutdown_fio *self) { return 0; } -static uint32_t shutdown_fio_pwrite(struct shutdown_fio *self, struct lib9p_srv_ctx *ctx, void *buf, uint32_t byte_count, uint64_t offset) { +static uint32_t_or_error shutdown_fio_pwrite(struct shutdown_fio *self, struct lib9p_srv_ctx *ctx, void *buf, uint32_t byte_count, uint64_t offset) { assert(self); assert(ctx); assert(buf); assert(offset == 0); if (byte_count == 0) - return 0; + return ERROR_NEW_VAL(uint32_t, 0); for (size_t i = 0; i < self->parent->nlisteners; i++) - LO_CALL(lo_box_hostnet_tcplist_as_net_stream_listener(&self->parent->listeners[i]), close); - return byte_count; + LO_CALL(LO_BOX(net_stream_listener, &self->parent->listeners[i]), close); + return ERROR_NEW_VAL(uint32_t, byte_count); } -static void shutdown_fio_pread(struct shutdown_fio *LM_UNUSED(self), struct lib9p_srv_ctx *LM_UNUSED(ctx), - uint32_t LM_UNUSED(byte_count), uint64_t LM_UNUSED(byte_offset), - struct iovec *LM_UNUSED(ret)) { +static iovec_or_error shutdown_fio_pread(struct shutdown_fio *LM_UNUSED(self), struct lib9p_srv_ctx *LM_UNUSED(ctx), + uint32_t LM_UNUSED(byte_count), uint64_t LM_UNUSED(byte_offset)) { assert_notreached("not readable"); } diff --git a/lib9p/tests/test_server/fs_shutdown.h b/lib9p/tests/test_server/fs_shutdown.h index 6b8683c..7b8d327 100644 --- a/lib9p/tests/test_server/fs_shutdown.h +++ b/lib9p/tests/test_server/fs_shutdown.h @@ -18,6 +18,5 @@ struct shutdown_file { size_t nlisteners; }; LO_IMPLEMENTATION_H(lib9p_srv_file, struct shutdown_file, shutdown_file); -#define lo_box_shutdown_file_as_lib9p_srv_file(obj) util9p_box(shutdown_file, obj) #endif /* _LIB9P_TESTS_TEST_SERVER_FS_SHUTDOWN_H_ */ diff --git a/lib9p/tests/test_server/fs_whoami.c b/lib9p/tests/test_server/fs_whoami.c index 7e1d635..3cc0683 100644 --- a/lib9p/tests/test_server/fs_whoami.c +++ b/lib9p/tests/test_server/fs_whoami.c @@ -53,11 +53,11 @@ static struct lib9p_qid whoami_file_qid(struct whoami_file *self) { }; } -static struct lib9p_srv_stat whoami_file_stat(struct whoami_file *self, struct lib9p_srv_ctx *ctx) { +static lib9p_srv_stat_or_error whoami_file_stat(struct whoami_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - return (struct lib9p_srv_stat){ + return ERROR_NEW_VAL(lib9p_srv_stat, ((struct lib9p_srv_stat){ .qid = whoami_file_qid(self), .mode = 0444, .atime_sec = UTIL9P_ATIME, @@ -68,22 +68,22 @@ static struct lib9p_srv_stat whoami_file_stat(struct whoami_file *self, struct l .owner_gid = { .name=lib9p_str("root"), .num=0 }, .last_modifier_uid = { .name=lib9p_str("root"), .num=0 }, .extension = lib9p_str(NULL), - }; + })); } -static void whoami_file_wstat(struct whoami_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) { +static error whoami_file_wstat(struct whoami_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "cannot wstat API file"); + return error_new(E_POSIX_EROFS, "cannot wstat API file"); } -static void whoami_file_remove(struct whoami_file *self, struct lib9p_srv_ctx *ctx) { +static error whoami_file_remove(struct whoami_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "cannot remove API file"); + return error_new(E_POSIX_EROFS, "cannot remove API file"); } -LIB9P_SRV_NOTDIR(struct whoami_file, whoami_file) +LIB9P_SRV_NOTDIR(struct whoami_file, whoami_file); -static lo_interface lib9p_srv_fio whoami_file_fopen(struct whoami_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { +static lib9p_srv_fio_or_error whoami_file_fopen(struct whoami_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { assert(self); assert(ctx); @@ -92,7 +92,7 @@ static lo_interface lib9p_srv_fio whoami_file_fopen(struct whoami_file *self, st ret->buf_len = 0; ret->buf = NULL; - return lo_box_whoami_fio_as_lib9p_srv_fio(ret); + return ERROR_NEW_VAL(lib9p_srv_fio, LO_BOX(lib9p_srv_fio, ret)); } /* srv_fio ********************************************************************/ @@ -115,18 +115,16 @@ static uint32_t whoami_fio_iounit(struct whoami_fio *self) { return 0; } -static uint32_t whoami_fio_pwrite(struct whoami_fio *LM_UNUSED(self), - struct lib9p_srv_ctx *LM_UNUSED(ctx), - void *LM_UNUSED(buf), uint32_t LM_UNUSED(byte_count), - uint64_t LM_UNUSED(offset)) { +static uint32_t_or_error whoami_fio_pwrite(struct whoami_fio *LM_UNUSED(self), + struct lib9p_srv_ctx *LM_UNUSED(ctx), + void *LM_UNUSED(buf), uint32_t LM_UNUSED(byte_count), + uint64_t LM_UNUSED(offset)) { assert_notreached("not writable"); } -static void whoami_fio_pread(struct whoami_fio *self, struct lib9p_srv_ctx *ctx, - uint32_t byte_count, uint64_t byte_offset, - struct iovec *ret) { +static iovec_or_error whoami_fio_pread(struct whoami_fio *self, struct lib9p_srv_ctx *ctx, + uint32_t byte_count, uint64_t byte_offset) { assert(self); assert(ctx); - assert(ret); size_t data_size = whoami_len(ctx); if (self->buf_len < data_size+1) { @@ -136,19 +134,16 @@ static void whoami_fio_pread(struct whoami_fio *self, struct lib9p_srv_ctx *ctx, snprintf(self->buf, self->buf_len, "%"PRIu32" %.*s\n", ctx->user->num, ctx->user->name.len, ctx->user->name.utf8); - if (byte_offset > (uint64_t)data_size) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EINVAL, "offset is past end-of-file length"); - return; - } + if (byte_offset > (uint64_t)data_size) + return ERROR_NEW_ERR(iovec, error_new(E_POSIX_EINVAL, "offset is past end-of-file length")); size_t beg_off = (size_t)byte_offset; size_t end_off = beg_off + (size_t)byte_count; if (end_off > data_size) end_off = data_size; - *ret = (struct iovec){ + return ERROR_NEW_VAL(iovec, ((struct iovec){ .iov_base = &self->buf[beg_off], .iov_len = end_off-beg_off, - }; + })); } diff --git a/lib9p/tests/test_server/fs_whoami.h b/lib9p/tests/test_server/fs_whoami.h index 5e1aee9..518e11d 100644 --- a/lib9p/tests/test_server/fs_whoami.h +++ b/lib9p/tests/test_server/fs_whoami.h @@ -15,6 +15,5 @@ struct whoami_file { uint64_t pathnum; }; LO_IMPLEMENTATION_H(lib9p_srv_file, struct whoami_file, whoami_file); -#define lo_box_whoami_file_as_lib9p_srv_file(obj) util9p_box(whoami_file, obj) #endif /* _LIB9P_TESTS_TEST_SERVER_FS_WHOAMI_H_ */ diff --git a/lib9p/tests/test_server/main.c b/lib9p/tests/test_server/main.c index f2a73bf..0431c40 100644 --- a/lib9p/tests/test_server/main.c +++ b/lib9p/tests/test_server/main.c @@ -5,10 +5,13 @@ */ #include <errno.h> -#include <error.h> #include <stdio.h> #include <stdlib.h> /* for atoi() */ +#define error __error +#include <error.h> +#undef error + #include <lib9p/srv.h> #include <libcr/coroutine.h> #include <libhw/generic/alarmclock.h> @@ -36,7 +39,7 @@ /* globals ********************************************************************/ -static lo_interface lib9p_srv_file get_root(struct lib9p_srv_ctx *, struct lib9p_s); +static lib9p_srv_file_or_error get_root(struct lib9p_srv_ctx *, struct lib9p_s); static const char *hexdig = "0123456789abcdef"; @@ -60,11 +63,11 @@ static struct { #define STATIC_DIR(N, STRNAME, ...) \ UTIL9P_STATIC_DIR(N, STRNAME, __VA_ARGS__) -#define API_FILE(N, STRNAME, SYMNAME, ...) \ - lo_box_##SYMNAME##_file_as_lib9p_srv_file(&((struct SYMNAME##_file){ \ - .name = STRNAME, \ - .pathnum = N \ - __VA_OPT__(,) __VA_ARGS__ \ +#define API_FILE(N, STRNAME, SYMNAME, ...) \ + LO_BOX(lib9p_srv_file, &((struct SYMNAME##_file){ \ + .name = STRNAME, \ + .pathnum = N \ + __VA_OPT__(,) __VA_ARGS__ \ })) static struct lib9p_srv_file root = @@ -84,8 +87,8 @@ static struct lib9p_srv_file root = API_FILE(13, "flush-slowread", flush, .flush_cnt=0, .flush_behavior=FLUSH_READ), ); -static lo_interface lib9p_srv_file get_root(struct lib9p_srv_ctx *LM_UNUSED(ctx), struct lib9p_s LM_UNUSED(treename)) { - return root; +static lib9p_srv_file_or_error get_root(struct lib9p_srv_ctx *LM_UNUSED(ctx), struct lib9p_s LM_UNUSED(treename)) { + return ERROR_NEW_VAL(lib9p_srv_file, root); } /* main ***********************************************************************/ @@ -96,7 +99,7 @@ static COROUTINE read_cr(void *_i) { hostnet_tcp_listener_init(&globals.listeners[i], globals.port); - lib9p_srv_accept_and_read_loop(&globals.srv, lo_box_hostnet_tcplist_as_net_stream_listener(&globals.listeners[i])); + lib9p_srv_accept_and_read_loop(&globals.srv, LO_BOX(net_stream_listener, &globals.listeners[i])); cr_end(); } @@ -117,12 +120,12 @@ static COROUTINE init_cr(void *) { for (int i = 0; i < _CONFIG_9P_MAX_CONNS; i++) { char name[] = {'r', 'e', 'a', 'd', '-', hexdig[i], '\0'}; if (!coroutine_add(name, read_cr, &i)) - error(1, 0, "coroutine_add(read_cr, &i)"); + __error(1, 0, "coroutine_add(read_cr, &i)"); } for (int i = 0; i < _CONFIG_9P_MAX_REQS; i++) { char name[] = {'w', 'r', 'i', 't', 'e', '-', hexdig[i], '\0'}; if (!coroutine_add(name, write_cr, NULL)) - error(1, 0, "coroutine_add(write_cr, NULL)"); + __error(1, 0, "coroutine_add(write_cr, NULL)"); } cr_exit(); @@ -153,18 +156,18 @@ static void tstlog_msg(struct lib9p_srv_ctx *ctx, enum lib9p_msg_type typ, void int main(int argc, char *argv[]) { if (argc != 3) - error(2, 0, "usage: %s PORT_NUMBER LOGFILE", argv[0]); + __error(2, 0, "usage: %s PORT_NUMBER LOGFILE", argv[0]); globals.port = atoi(argv[1]); globals.logstream = fopen(argv[2], "w"); if (!globals.logstream) - error(2, errno, "fopen"); + __error(2, errno, "fopen"); globals.srv.msglog = tstlog_msg; struct hostclock clock_monotonic = { .clock_id = CLOCK_MONOTONIC, }; - bootclock = lo_box_hostclock_as_alarmclock(&clock_monotonic); + bootclock = LO_BOX(alarmclock, &clock_monotonic); coroutine_add("init", init_cr, NULL); coroutine_main(); fclose(globals.logstream); diff --git a/lib9p/tests/testclient-hangup.c b/lib9p/tests/testclient-hangup.c new file mode 100644 index 0000000..2efb49a --- /dev/null +++ b/lib9p/tests/testclient-hangup.c @@ -0,0 +1,100 @@ +/* lib9p/tests/testclient-hangup.c - Test the 9P `test_server`'s handling of TCP hangups + * + * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <arpa/inet.h> /* for htons(), inet_addr() */ +#include <errno.h> +#include <netinet/in.h> /* for struct sockaddr{,_in} */ +#include <stdlib.h> /* for atoi() */ +#include <sys/socket.h> /* for socket(), connect() */ +#include <sys/uio.h> /* for writev() */ +#include <unistd.h> /* for read() */ + +#define error __error +#include <error.h> +#undef error + +#include <lib9p/core.h> +#include <libmisc/assert.h> +#include <libmisc/endian.h> + +#define MAX_MSG_SIZE (8*1024) + +static void _send9p(int fd, struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body) { + struct lib9p_Tmsg_send_buf buf; + error err = lib9p_Tmsg_marshal(ctx, typ, body, &buf); + assert(ERROR_IS_NULL(err)); + size_t exp = 0; + for (size_t i = 0; i < buf.iov_cnt; i++) + exp += buf.iov[i].iov_len; + ssize_t act = writev(fd, buf.iov, buf.iov_cnt); + if (act < 0) + __error(1, errno, "writev"); + assert((size_t)act == exp); +} + +#define send9p(typ, ...) _send9p(fd, &ctx, LIB9P_TYP_##typ, &((struct lib9p_msg_##typ){ __VA_ARGS__ })) + +static void _recv9p(int fd) { + uint8_t buf[MAX_MSG_SIZE]; + size_t goal = 4; + size_t done = 0; + while (done < goal) { + ssize_t n = read(fd, &buf[done], goal-done); + if (n < 0) + __error(1, errno, "read"); + done += n; + } + goal = uint32le_decode(buf); + assert(goal <= MAX_MSG_SIZE); + while (done < goal) { + ssize_t n = read(fd, &buf[done], goal-done); + if (n < 0) + __error(1, errno, "read"); + done += n; + } +} + +#define recv9p() _recv9p(fd) + +int main(int argc, char *argv[]) { + if (argc != 2) + __error(2, 0, "Usage: %s SERVER_PORT", argv[0]); + uint16_t server_port = atoi(argv[1]); + + union { + struct sockaddr gen; + struct sockaddr_in in; + } server_addr = {}; + server_addr.in.sin_family = AF_INET; + server_addr.in.sin_addr.s_addr = inet_addr("127.0.0.1"); + server_addr.in.sin_port = htons(server_port); + + int fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) + __error(1, errno, "socket"); + if (connect(fd, &server_addr.gen, sizeof(server_addr)) < 0) + __error(1, errno, "connect"); + + struct lib9p_ctx ctx = { + .max_msg_size = 16*1024, + }; + + struct lib9p_s wname[1]; + + /**********************************************************************/ + + send9p(Tversion, .tag=0, .max_msg_size=(8*1024), .version=lib9p_str("9P2000")); + recv9p(); /* Rversion */ + ctx.version = LIB9P_VER_9P2000; + send9p(Tattach, .tag=0, .fid=0, .afid=LIB9P_FID_NOFID, .uname=lib9p_str("nobody"), .aname=lib9p_str("")); + recv9p(); /* Rattach */ + wname[0] = lib9p_str("shutdown"); send9p(Twalk, .tag=0, .fid=0, .newfid=0, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + send9p(Topen, .tag=0, .fid=0, .mode=LIB9P_O_MODE_WRITE); + recv9p(); /* Ropen */ + send9p(Twrite, .tag=0, .fid=0, .offset=0, .count=2, .data="1\n"); + return 0; /* Hang up without waiting for Rwrite. */ +} diff --git a/lib9p/tests/testclient-hangup.explog b/lib9p/tests/testclient-hangup.explog new file mode 100644 index 0000000..568b0fc --- /dev/null +++ b/lib9p/tests/testclient-hangup.explog @@ -0,0 +1,14 @@ +# lib9p/tests/testclient-hangup.explog - Expected 9P logfile of testclient-hangup +# +# Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> +# SPDX-License-Identifier: AGPL-3.0-or-later +> Tversion { tag=0 max_msg_size=8192 version="9P2000" } +< Rversion { tag=0 max_msg_size=4120 version="9P2000" } +> Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" unum=0 } +< Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } +> Twalk { tag=0 fid=0 newfid=0 nwname=1 wname=[ "shutdown" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(APPEND) vers=1 path=5 } ] } +> Topen { tag=0 fid=0 mode=(MODE_WRITE) } +< Ropen { tag=0 qid={ type=(APPEND) vers=1 path=5 } iounit=0 } +> Twrite { tag=0 fid=0 offset=0 count=2 data="1\n" } +< Rwrite { tag=0 count=2 } diff --git a/lib9p/tests/testclient-sess.c b/lib9p/tests/testclient-sess.c index eef9d2c..0cec6c6 100644 --- a/lib9p/tests/testclient-sess.c +++ b/lib9p/tests/testclient-sess.c @@ -4,15 +4,18 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -#include <arpa/inet.h> /* for htons(), inet_addr() */ +#include <arpa/inet.h> /* for htons(), inet_addr() */ #include <errno.h> -#include <error.h> #include <netinet/in.h> /* for struct sockaddr{,_in} */ #include <stdlib.h> /* for atoi() */ #include <sys/socket.h> /* for socket(), connect() */ #include <sys/uio.h> /* for writev() */ #include <unistd.h> /* for read() */ +#define error __error +#include <error.h> +#undef error + #include <lib9p/core.h> #include <libmisc/assert.h> #include <libmisc/endian.h> @@ -21,14 +24,14 @@ static void _send9p(int fd, struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body) { struct lib9p_Tmsg_send_buf buf; - bool err = lib9p_Tmsg_marshal(ctx, typ, body, &buf); - assert(!err); + error err = lib9p_Tmsg_marshal(ctx, typ, body, &buf); + assert(ERROR_IS_NULL(err)); size_t exp = 0; for (size_t i = 0; i < buf.iov_cnt; i++) exp += buf.iov[i].iov_len; ssize_t act = writev(fd, buf.iov, buf.iov_cnt); if (act < 0) - error(1, errno, "writev"); + __error(1, errno, "writev"); assert((size_t)act == exp); } @@ -41,7 +44,7 @@ static void _recv9p(int fd) { while (done < goal) { ssize_t n = read(fd, &buf[done], goal-done); if (n < 0) - error(1, errno, "read"); + __error(1, errno, "read"); done += n; } goal = uint32le_decode(buf); @@ -49,7 +52,7 @@ static void _recv9p(int fd) { while (done < goal) { ssize_t n = read(fd, &buf[done], goal-done); if (n < 0) - error(1, errno, "read"); + __error(1, errno, "read"); done += n; } } @@ -58,7 +61,7 @@ static void _recv9p(int fd) { int main(int argc, char *argv[]) { if (argc != 2) - error(2, 0, "Usage: %s SERVER_PORT", argv[0]); + __error(2, 0, "Usage: %s SERVER_PORT", argv[0]); uint16_t server_port = atoi(argv[1]); union { @@ -71,9 +74,9 @@ int main(int argc, char *argv[]) { int fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) - error(1, errno, "socket"); + __error(1, errno, "socket"); if (connect(fd, &server_addr.gen, sizeof(server_addr)) < 0) - error(1, errno, "connect"); + __error(1, errno, "connect"); struct lib9p_ctx ctx = { .max_msg_size = 16*1024, diff --git a/lib9p/tests/testclient-sess.explog b/lib9p/tests/testclient-sess.explog index a3838ac..ec8d9c9 100644 --- a/lib9p/tests/testclient-sess.explog +++ b/lib9p/tests/testclient-sess.explog @@ -103,7 +103,7 @@ < Ropen { tag=0 qid={ type=(0) vers=1 path=10 } iounit=0 } > Tread { tag=0 fid=2 offset=0 count=10 } > Tflush { tag=1 oldtag=0 } -< Rerror { tag=0 errstr="request canceled by flush" errnum=L_ECANCELED } +< Rerror { tag=0 errstr="request canceled by flush" errnum=L_EAGAIN } < Rflush { tag=1 } # flush, original request is aborted without error |