/* lib9p_util/tests/demo_server.c - Main entry point for test 9P server * * Copyright (C) 2024-2025 Luke T. Shumaker * SPDX-License-Identifier: AGPL-3.0-or-later */ #include #include #include /* for atoi() */ #define error __error #include #undef error #include #include #include #include #include #include #include #include #include #include #include /* configuration **************************************************************/ #include "config.h" #ifndef _CONFIG_9P_MAX_CONNS #error config.h must define _CONFIG_9P_MAX_CONNS #endif #ifndef _CONFIG_9P_MAX_REQS #error config.h must define _CONFIG_9P_MAX_REQS #endif /* globals ********************************************************************/ static lib9p_srv_file_or_error get_root(struct lib9p_srv_ctx *, struct lib9p_s); static const char *hexdig = "0123456789abcdef"; static struct { uint16_t port; struct hostnet_tcp_listener listeners[_CONFIG_9P_MAX_CONNS]; struct lib9p_srv srv; uint8_t framebuffer[NUT_FB_W*NUT_FB_H]; } globals = { .srv = (struct lib9p_srv){ .rootdir = get_root, }, }; /* file tree ******************************************************************/ #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__ \ })) const char *const _statictxt_start = "Hello, world!"; const size_t _statictxt_size = 13; static struct lib9p_srv_file root = STATIC_DIR(1, "", UTIL9P_STATIC_FILE(2, "static.txt", .data_start = _statictxt_start, .data_size = _statictxt_size), API_FILE(3, "whoami.txt", whoami), API_FILE(4, "uptime.txt", uptime), API_FILE(5, "video.nut", nut, .framebuffer = globals.framebuffer), ); 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 ***********************************************************************/ static COROUTINE read_cr(void *_i) { int i = *((int *)_i); cr_begin(); hostnet_tcp_listener_init(&globals.listeners[i], globals.port); lib9p_srv_accept_and_read_loop(&globals.srv, LO_BOX(net_stream_listener, &globals.listeners[i])); cr_end(); } static COROUTINE write_cr(void *) { cr_begin(); lib9p_srv_worker_loop(&globals.srv); cr_end(); } int main(int argc, char *argv[]) { if (argc != 2) __error(2, 0, "usage: %s PORT_NUMBER", argv[0]); globals.port = atoi(argv[1]); struct hostclock clock_monotonic = { .clock_id = CLOCK_MONOTONIC, }; bootclock = LO_BOX(alarmclock, &clock_monotonic); 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)"); } 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)"); } coroutine_main(); return 0; }