summaryrefslogtreecommitdiff
path: root/lib9p/tests/test_server/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p/tests/test_server/main.c')
-rw-r--r--lib9p/tests/test_server/main.c154
1 files changed, 154 insertions, 0 deletions
diff --git a/lib9p/tests/test_server/main.c b/lib9p/tests/test_server/main.c
new file mode 100644
index 0000000..2743629
--- /dev/null
+++ b/lib9p/tests/test_server/main.c
@@ -0,0 +1,154 @@
+/* lib9p/tests/test_server/main.c - Main entry point for test 9P server
+ *
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <error.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h> /* for atoi() */
+
+#include <lib9p/srv.h>
+#include <libcr/coroutine.h>
+#include <libhw/generic/net.h>
+#include <libhw/generic/alarmclock.h>
+#include <libhw/host_alarmclock.h>
+#include <libhw/host_net.h>
+#include <libmisc/macro.h>
+#include <util9p/static.h>
+
+#include "static.h"
+#include "fs_shutdown.h"
+#include "fs_slowread.h"
+
+/* configuration **************************************************************/
+
+#include "config.h"
+
+#ifndef CONFIG_SRV9P_NUM_CONNS
+ #error config.h must define CONFIG_SRV9P_NUM_CONNS
+#endif
+
+/* globals ********************************************************************/
+
+static lo_interface lib9p_srv_file get_root(struct lib9p_srv_ctx *, struct lib9p_s);
+
+const char *hexdig = "0123456789abcdef";
+
+struct {
+ uint16_t port;
+ struct hostnet_tcp_listener listeners[CONFIG_SRV9P_NUM_CONNS];
+ struct lib9p_srv srv;
+ FILE *logstream;
+} globals = {
+ .srv = (struct lib9p_srv){
+ .rootdir = get_root,
+ },
+};
+
+/* file tree ******************************************************************/
+
+#define STATIC_FILE(N, STRNAME, SYMNAME) \
+ UTIL9P_STATIC_FILE(N, STRNAME, \
+ .data_start = _binary_static_##SYMNAME##_start, \
+ .data_end = _binary_static_##SYMNAME##_end)
+#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__ \
+ }))
+
+struct lib9p_srv_file root =
+ STATIC_DIR(1, "",
+ STATIC_DIR(2, "Documentation",
+ STATIC_FILE(3, "x", Documentation_x_txt),
+ ),
+ STATIC_FILE(4, "README.md", README_md),
+ API_FILE(5, "shutdown", shutdown,
+ .listeners = globals.listeners,
+ .nlisteners = LM_ARRAY_LEN(globals.listeners)),
+ API_FILE(6, "slowread", slowread,
+ .flushable = false),
+ API_FILE(7, "slowread-flushable", slowread,
+ .flushable = true),
+ );
+
+static lo_interface lib9p_srv_file get_root(struct lib9p_srv_ctx *LM_UNUSED(ctx), struct lib9p_s LM_UNUSED(treename)) {
+ return root;
+}
+
+/* main ***********************************************************************/
+
+static COROUTINE read_cr(void *_i) {
+ int i = *((int *)_i);
+ cr_begin();
+
+ hostnet_tcp_listener_init(&globals.listeners[i], globals.port);
+
+ lib9p_srv_read_cr(&globals.srv, lo_box_hostnet_tcplist_as_net_stream_listener(&globals.listeners[i]));
+
+ cr_end();
+}
+
+static COROUTINE init_cr(void *) {
+ cr_begin();
+
+ sleep_for_ms(1);
+
+ for (int i = 0; i < CONFIG_SRV9P_NUM_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)");
+ }
+ for (int i = 0; i < 2*CONFIG_SRV9P_NUM_CONNS; i++) {
+ char name[] = {'w', 'r', 'i', 't', 'e', '-', hexdig[i], '\0'};
+ if (!coroutine_add(name, lib9p_srv_write_cr, &globals.srv))
+ error(1, 0, "coroutine_add(lib9p_srv_write_cr, &globals.srv)");
+ }
+
+ cr_exit();
+}
+
+static void log_fct(char character, void *_stream) {
+ FILE *stream = _stream;
+ putc(character, stream);
+ putchar(character);
+}
+
+static void log_msg(struct lib9p_srv_ctx *ctx, enum lib9p_msg_type typ, void *hostmsg) {
+ /* It sucks that %v trips -Wformat and -Wformat-extra-args
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47781 */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat"
+#pragma GCC diagnostic ignored "-Wformat-extra-args"
+ fmt_fctprintf(log_fct, globals.logstream,
+ "%c %v\n", typ % 2 ? '<' : '>',
+ lo_box_lib9p_msg_as_fmt_formatter(&ctx->basectx, typ, hostmsg));
+#pragma GCC diagnostic pop
+ fflush(globals.logstream);
+}
+
+int main(int argc, char *argv[]) {
+ if (argc != 3)
+ 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");
+ globals.srv.msglog = log_msg;
+
+ struct hostclock clock_monotonic = {
+ .clock_id = CLOCK_MONOTONIC,
+ };
+ bootclock = lo_box_hostclock_as_alarmclock(&clock_monotonic);
+ coroutine_add("init", init_cr, NULL);
+ coroutine_main();
+ fclose(globals.logstream);
+ return 0;
+}