diff options
Diffstat (limited to 'lib9p/srv.c')
-rw-r--r-- | lib9p/srv.c | 59 |
1 files changed, 51 insertions, 8 deletions
diff --git a/lib9p/srv.c b/lib9p/srv.c index 039b4c2..74c2014 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -10,18 +10,24 @@ #include <lib9p/srv.h> #include "internal.h" -struct lib9p_srvconn { +/* The hierarchy of concepts is: + * + * server -> connection -> session -> request + * + */ + +struct lib9p_srv_sess { /* immutable */ struct lib9p_srv *srv; - cid_t reader; - int fd; + int connfd; + cid_t reader; /* the lib9p_srv_read_cr() coroutine for this session */ /* mutable */ struct lib9p_ctx ctx; unsigned int refcount; }; -struct lib9p_srvreq { - struct lib9p_srvconn *conn; +struct lib9p_srv_req { + struct lib9p_srv_sess *sess; uint8_t *msg; }; @@ -79,7 +85,7 @@ COROUTINE lib9p_srv_read_cr(void *_srv) { } goal = decode_u32le(buf); if (goal < 7) { - /* We can't respond with an Rerror becuase we wouldn't know what tag to use! */ + /* We can't even respond with an Rerror becuase we wouldn't know what tag to use! */ fprintf(stderr, "error: T-message is impossibly small"); goto close; } @@ -184,5 +190,42 @@ void handle_message(struct lib9p_srvconn *conn, uint8_t *net) { netio_write(req.conn->fd, net, decode_u32le(net)); } -// EMSGSIZE for request too large -// EPROTONOSUPPORT for version errors +void _version(struct lib9p_srv_req *ctx, struct lib9p_msg_Tversion *req, struct lib9p_msg_Rversion *resp) { + enum lib9p_version version = LIB9P_VER_unknown; + + if (req->version.len >= 6 && + req->version.utf8[0] == '9' && + req->version.utf8[1] == 'P' && + '0' <= req->version.utf8[2] && req->version.utf8[2] <= '9' && + '0' <= req->version.utf8[3] && req->version.utf8[3] <= '9' && + '0' <= req->version.utf8[4] && req->version.utf8[4] <= '9' && + '0' <= req->version.utf8[5] && req->version.utf8[5] <= '9' && + (req->version.utf8[6] == '\0' || req->version.utf8[6] == '.')) { + if (strcmp(&req->version.utf8[6], ".u") == 0) + version = LIB9P_VER_9P2000_u; + //else if (strcmp(&req->version.utf8[6], ".e") == 0) + // version = LIB9P_VER_9P2000_e; + else + version = LIB9P_VER_9P2000; + } + + struct lib9p_ctx empty_ctx = { + .version = version, + .max_msg_size = CONFIG_9P_MAX_MSG_SIZE, + }; + struct lib9p_msg_Rerror empty_error = { 0 }; + assert(!lib9p_marshal(&empty_ctx, LIB9P_TYP_Rerror, 0, &empty_error, ctx->net)); + uint32_t min_msg_size = decode_u32le(ctx->net); + assert(CONFIG_9P_MAX_MSG_SIZE >= min_msg_size); + + if (req->max_msg_size < min_msg_size) { + lib9p_errorf(&ctx->ctx, LINUX_EDOM, "requested max_msg_size is less than minimum for %s (%"PRIu32" < %"PRIu32")", + version, req->max_msg_size, min_msg_size); + return; + } + + resp->version = lib9p_version_str(version); + resp->max_msg_size = (CONFIG_9P_MAX_MSG_SIZE < req->max_msg_size) + ? CONFIG_9P_MAX_MSG_SIZE + : req->max_msg_size; +} |