1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
/* lib9p_util/tests/demo_server.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 <errno.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>
#include <libhw/generic/net.h>
#include <libhw/host_alarmclock.h>
#include <libhw/host_net.h>
#include <libmisc/macro.h>
#include <util9p/coroutine.h>
#include <util9p/static.h>
#include <util9p/uptime.h>
#include <util9p/whoami.h>
#include <util9p/nut.h>
/* 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),
API_FILE(6, "proc.txt", coroutine),
);
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;
}
|