summaryrefslogtreecommitdiff
path: root/lib9p/srv.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p/srv.c')
-rw-r--r--lib9p/srv.c59
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;
+}