summaryrefslogtreecommitdiff
path: root/9p/srv.c
diff options
context:
space:
mode:
Diffstat (limited to '9p/srv.c')
-rw-r--r--9p/srv.c194
1 files changed, 0 insertions, 194 deletions
diff --git a/9p/srv.c b/9p/srv.c
deleted file mode 100644
index 59326c9..0000000
--- a/9p/srv.c
+++ /dev/null
@@ -1,194 +0,0 @@
-#include <assert.h>
-
-#include "coroutine.h"
-#include "netio.h"
-#include "9p/9p.h"
-
-#include "9p/internal.h"
-
-struct p9_srvconn {
- /* immutable */
- p9_srv *srv;
- cid_t reader;
- int fd;
- /* mutable */
- uint32_t max_msg_size;
- enum p9_version version;
- unsigned int refcount;
-};
-
-struct p9_srvreq {
- p9_srvconn *conn;
- uint8_t *msg;
-};
-
-COROUTINE p9_srv_read_cr(void *_srv) {
- uint8_t buf[CONFIG_9P_MAX_MSG_SIZE];
-
- p9_srv *srv = _srv;
- assert(srv);
- cr_begin();
-
- for (;;) {
- struct p9_srvconn conn = {
- .srv = srv,
- .reader = cr_getcid();
-
- .max_msg_size = CONFIG_9P_MAX_MSG_SIZE;
- .version = P9_VER_UNINITIALIZED;
- .refcount = 1,
- };
- conn.fd = netio_accept(srv->sockfd);
- if (conn.fd < 0) {
- fprintf(stderr, "error: accept: %m", -conn.fd);
- continue;
- }
-
- for (;;) {
- /* Read the message size. */
- size_t goal = 4, done = 0;
- while (done < goal) {
- ssize_t r = netio_read(conn.fd, &buf[done], sizeof(buf)-done);
- if (r < 0) {
- fprintf(stderr, "error: read: %m", -r);
- goto close;
- } else if (r == 0) {
- if (done != 0)
- fprintf(stderr, "error: read: unexpected EOF");
- goto close;
- }
- done += r;
- }
- goal = decode_u32le(buf);
- if (goal < 7) {
- /* We can't respond with an Rerror becuase we wouldn't know what tag to use! */
- fprintf(stderr, "error: T-message is impossibly small");
- goto close;
- }
- if (goal > conn.max_msg_size) {
- struct p9_ctx ctx = {
- .version = conn.version,
- .max_msg_size = conn.max_msg_size,
- };
- if (initialized)
- p9_errorf(&ctx, LINUX_EMSGSIZE, "T-message larger than negotiated limit (%zu > %zu)", goal, conn.max_msg_size);
- else
- p9_errorf(&ctx, LINUX_EMSGSIZE, "T-message larger than server limit (%zu > %zu)", goal, conn.max_msg_size);
- marshal_error(&ctx, buf);
- netio_write(conn.fd, buf, decode_u32le(buf));
- continue;
- }
- /* Read the rest of the message. */
- while (done < goal) {
- ssize_t r = netio_read(conn.fd, &buf[done], sizeof(buf)-done);
- if (r < 0) {
- fprintf(stderr, "error: read: %m", -r);
- goto close;
- } else if (r == 0) {
- fprintf(stderr, "error: read: unexpected EOF");
- goto close;
- }
- done += r;
- }
-
- /* Handle the message... */
- if (conn.version == P9_VER_UNINITIALIZED) {
- /* ...synchronously if we haven't negotiated the protocol yet, ... */
- handle_message(&conn, buf);
- } else {
- /* ...asynchronously if we have. */
- cr_chan_send(&srv->reqch, buf);
- cr_pause_and_yield();
- }
- }
- close:
- netio_close(conn.fd, true, (--conn.refcount) == 0);
- if (conn.refcount) {
- cr_pause_and_yield();
- assert(conn.refcount == 0);
- netio_close(conn.fd, false, true);
- }
- }
-
- cr_end();
-}
-
-COROUTINE p9_srv_write_cr(void *_srv) {
- uint8_t net[CONFIG_9P_MAX_MSG_SIZE];
-
- p9_srv *srv = _srv;
- assert(srv);
- cr_begin();
-
- for (;;) {
- struct p9_srvreq req;
- cr_chan_recv(&srv->reqch, &req);
- memcpy(net, req.msg, decode_u32le(req.msg));
- req.conn->refcount++;
- cr_unpause(req.conn->reader);
-
- handle_message(&req.conn, net);
-
- if ((--req.conn->refcount) == 0)
- cr_unpause(req.conn->reader);
- }
-
- cr_end();
-}
-
-void handle_message(p9_srvconn *conn, uint8_t *net) {
- uint8_t host[CONFIG_9P_MAX_MSG_SIZE];
-
- struct p9_ctx ctx = {
- .version = req.conn->version,
- .max_msg_size = req.conn->max_msg_size,
- };
-
- size_t host_size = p9_unmarshal_size(&ctx, net);
- if (host_size == (size_t)-1)
- goto write;
- if (host_size > sizeof(host)) {
- p9_errorf(&ctx, LINUX_EMSGSIZE, "unmarshalled payload larger than server limit (%zu > %zu)", host_size, sizeof(host));
- goto write;
- }
-
- uint16_t tag;
- uint8_t typ = p9_unmarshal(&ctx, net, &tag, host);
- if (typ == (uint8_t)-1)
- goto write;
- if (typ % 2 != 0) {
- p9_errorf(&ctx, LINUX_EOPNOTSUPP, "expected a T-message but got an R-message");
- goto write;
- }
-
- TODO;
-
- write:
- if (ctx.err_num || ctx.err_msg[0])
- marshal_error(&ctx, net);
- else
- TODO;
- netio_write(req.conn->fd, net, decode_u32le(net));
-}
-
-static inline uint16_t min_u16(uint16_t a, b) {
- return (a < b) ? a : b;
-}
-
-/* We have special code for marshaling Rerror because we don't ever
- * want to produce an error because the err_msg is too long for the
- * `ctx->max_msg_size`! */
-void marshal_error(struct p9_ctx *ctx, uint16_t tag, uint8_t *net) {
- struct p9_msg_Rerror host = {
- .ename = {
- .len = strnlen(ctx->err_msg, CONFIG_9P_MAX_ERR_SIZE),
- .utf8 = ctx->err_msg,
- },
- };
- if (host.ename.len + ctx->Rerror_overhead > ctx->max_msg_size)
- host.ename.len = ctx->max_msg_size - overhead;
- p9_marshal(ctx, tag, host, net);
-}
-
-ERANGE for reply too large
-EPROTONOSUPPORT for version errors