summaryrefslogtreecommitdiff
path: root/lib9p/srv.c
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-04-06 03:28:09 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-04-12 21:37:47 -0600
commit7741ed43f5bc0be9473a281d050c6fbdbc6aea81 (patch)
treee4532cb4643bbf450bffc818d0194922b6b93b93 /lib9p/srv.c
parent52674d0483e3754b039857be1d11798859c5bcef (diff)
lib9p: Rename the server coroutine functions, pull out the read func
Diffstat (limited to 'lib9p/srv.c')
-rw-r--r--lib9p/srv.c162
1 files changed, 82 insertions, 80 deletions
diff --git a/lib9p/srv.c b/lib9p/srv.c
index ea8b932..0a561d3 100644
--- a/lib9p/srv.c
+++ b/lib9p/srv.c
@@ -243,110 +243,114 @@ static bool read_exactly(lo_interface net_stream_conn fd, uint8_t *buf, size_t g
static void handle_message(struct _lib9p_srv_req *ctx);
-[[noreturn]] void lib9p_srv_read_cr(struct lib9p_srv *srv, lo_interface net_stream_listener listener) {
+void lib9p_srv_accept_and_read_loop(struct lib9p_srv *srv, lo_interface net_stream_listener listener) {
assert(srv);
assert(srv->rootdir);
assert(!LO_IS_NULL(listener));
srv->readers++;
- uint32_t initial_rerror_overhead = lib9p_version_min_msg_size(LIB9P_VER_unknown);
-
for (;;) {
- struct _srv_conn conn = {
- .parent_srv = srv,
- .fd = LO_CALL(listener, accept),
- .reader = cr_getcid(),
- };
- if (LO_IS_NULL(conn.fd)) {
+ lo_interface net_stream_conn conn = LO_CALL(listener, accept);
+ if (LO_IS_NULL(conn)) {
nonrespond_errorf("accept: error");
srv->readers--;
if (srv->readers == 0)
while (srv->writers > 0)
_lib9p_srv_reqch_send_req(&srv->_reqch, NULL);
- cr_exit();
+ return;
}
+ lib9p_srv_read(srv, conn);
+ }
+}
- struct _srv_sess sess = {
- .parent_conn = &conn,
- .version = LIB9P_VER_unknown,
- .max_msg_size = CONFIG_9P_SRV_MAX_MSG_SIZE,
- .rerror_overhead = initial_rerror_overhead,
- .initialized = false,
- };
- for (;;) {
- nextmsg:
- /* Read the message. */
- size_t done = 0;
- uint8_t buf[7];
- if (read_exactly(conn.fd, buf, 4, &done))
- goto close;
- size_t goal = uint32le_decode(buf);
- if (goal < 7) {
- nonrespond_errorf("T-message is impossibly small");
- goto close;
- }
- if (read_exactly(conn.fd, buf, 7, &done))
- goto close;
- struct _lib9p_srv_req req = {
- .parent_sess = &sess,
- .tag = uint16le_decode(&buf[5]),
- .net_bytes = buf,
- .ctx = {
- .basectx = {
- .version = sess.version,
- .max_msg_size = sess.max_msg_size,
- },
- },
- };
- if (goal > sess.max_msg_size) {
- lib9p_errorf(&req.ctx.basectx,
- LINUX_EMSGSIZE, "T-message larger than %s limit (%zu > %"PRIu32")",
- sess.initialized ? "negotiated" : "server",
- goal,
- sess.max_msg_size);
- respond_error(&req);
- goto nextmsg;
- }
- req.net_bytes = malloc(goal);
- assert(req.net_bytes);
- memcpy(req.net_bytes, buf, done);
- if (read_exactly(conn.fd, req.net_bytes, goal, &done)) {
- free(req.net_bytes);
- goto close;
- }
+void lib9p_srv_read(struct lib9p_srv *srv, lo_interface net_stream_conn _conn) {
+ assert(srv);
+ assert(srv->rootdir);
+ assert(!LO_IS_NULL(_conn));
- /* Handle the message... */
- if (req.net_bytes[4] == LIB9P_TYP_Tversion)
- /* ...in this coroutine for Tversion, */
- handle_message(&req);
- else
- /* ...but usually in another coroutine. */
- _lib9p_srv_reqch_send_req(&srv->_reqch, &req);
+ struct _srv_conn conn = {
+ .parent_srv = srv,
+ .fd = _conn,
+ .reader = cr_getcid(),
+ };
+ struct _srv_sess sess = {
+ .parent_conn = &conn,
+ .version = LIB9P_VER_unknown,
+ .max_msg_size = CONFIG_9P_SRV_MAX_MSG_SIZE,
+ .rerror_overhead = lib9p_version_min_msg_size(LIB9P_VER_unknown),
+ .initialized = false,
+ };
+ for (;;) {
+ nextmsg:
+ /* Read the message. */
+ size_t done = 0;
+ uint8_t buf[7];
+ if (read_exactly(conn.fd, buf, 4, &done))
+ goto close;
+ size_t goal = uint32le_decode(buf);
+ if (goal < 7) {
+ nonrespond_errorf("T-message is impossibly small");
+ goto close;
}
- close:
- if (sess.reqs.len == 0)
- io_close(conn.fd);
- else {
- io_close_read(conn.fd);
- sess.closing = true;
- cr_pause_and_yield();
- assert(sess.reqs.len == 0);
- io_close_write(conn.fd);
+ if (read_exactly(conn.fd, buf, 7, &done))
+ goto close;
+ struct _lib9p_srv_req req = {
+ .parent_sess = &sess,
+ .tag = uint16le_decode(&buf[5]),
+ .net_bytes = buf,
+ .ctx = {
+ .basectx = {
+ .version = sess.version,
+ .max_msg_size = sess.max_msg_size,
+ },
+ },
+ };
+ if (goal > sess.max_msg_size) {
+ lib9p_errorf(&req.ctx.basectx,
+ LINUX_EMSGSIZE, "T-message larger than %s limit (%zu > %"PRIu32")",
+ sess.initialized ? "negotiated" : "server",
+ goal,
+ sess.max_msg_size);
+ respond_error(&req);
+ goto nextmsg;
+ }
+ req.net_bytes = malloc(goal);
+ assert(req.net_bytes);
+ memcpy(req.net_bytes, buf, done);
+ if (read_exactly(conn.fd, req.net_bytes, goal, &done)) {
+ free(req.net_bytes);
+ goto close;
}
+
+ /* Handle the message... */
+ if (req.net_bytes[4] == LIB9P_TYP_Tversion)
+ /* ...in this coroutine for Tversion, */
+ handle_message(&req);
+ else
+ /* ...but usually in another coroutine. */
+ _lib9p_srv_reqch_send_req(&srv->_reqch, &req);
+ }
+ close:
+ if (sess.reqs.len == 0)
+ io_close(conn.fd);
+ else {
+ io_close_read(conn.fd);
+ sess.closing = true;
+ cr_pause_and_yield();
+ assert(sess.reqs.len == 0);
+ io_close_write(conn.fd);
}
}
/* write coroutine ************************************************************/
-COROUTINE lib9p_srv_write_cr(void *_srv) {
+void lib9p_srv_worker_loop(struct lib9p_srv *srv) {
struct _lib9p_srv_req req;
_lib9p_srv_reqch_req_t rpc_handle;
- struct lib9p_srv *srv = _srv;
assert(srv);
assert(srv->rootdir);
- cr_begin();
srv->writers++;
@@ -356,7 +360,7 @@ COROUTINE lib9p_srv_write_cr(void *_srv) {
if (!rpc_handle.req) {
srv->writers--;
_lib9p_srv_reqch_send_resp(rpc_handle, 0);
- cr_exit();
+ return;
}
/* Copy the request from the reader coroutine's
* stack to our stack. */
@@ -377,8 +381,6 @@ COROUTINE lib9p_srv_write_cr(void *_srv) {
if (req.parent_sess->closing && !req.parent_sess->reqs.len)
cr_unpause(req.parent_sess->parent_conn->reader);
}
-
- cr_end();
}
#define _HANDLER_PROTO(typ) \