summaryrefslogtreecommitdiff
path: root/lib9p
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-10-05 21:14:39 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-10-05 21:14:39 -0600
commitcb108cfecb78c01ae8a2957ca5a32b58f9ddc4aa (patch)
tree686450953fb9e6c5c7e6e7b0a4d3385bb798ff2d /lib9p
parent41dd5694f46247805c161a4120c8c0364f2ee9c0 (diff)
lib9p: srv: clean up
Diffstat (limited to 'lib9p')
-rw-r--r--lib9p/include/lib9p/srv.h64
-rw-r--r--lib9p/srv.c438
2 files changed, 289 insertions, 213 deletions
diff --git a/lib9p/include/lib9p/srv.h b/lib9p/include/lib9p/srv.h
index 55bcba0..c56ee3f 100644
--- a/lib9p/include/lib9p/srv.h
+++ b/lib9p/include/lib9p/srv.h
@@ -7,26 +7,27 @@
#include <lib9p/9p.h>
-CR_RPC_DECLARE(_lib9p_srv_reqch, struct lib9p_req *, bool)
+/* context ********************************************************************/
+
CR_CHAN_DECLARE(_lib9p_srv_flushch, bool)
-struct lib9p_srv_reqctx {
- struct lib9p_ctx *base;
+struct lib9p_srv_ctx {
+ struct lib9p_ctx basectx;
uint32_t uid;
char *uname;
_lib9p_srv_flushch_t _flushch;
};
-static inline bool lib9p_srv_flush_requested(struct lib9p_srv_reqctx *ctx) {
+static inline bool lib9p_srv_flush_requested(struct lib9p_srv_ctx *ctx) {
assert(ctx);
return _lib9p_srv_flushch_can_send(&ctx->_flushch);
}
-static inline int lib9p_srv_acknowledge_flush(struct lib9p_srv_reqctx *ctx) {
+static inline int lib9p_srv_acknowledge_flush(struct lib9p_srv_ctx *ctx) {
assert(ctx);
assert(_lib9p_srv_flushch_can_send(&ctx->_flushch));
- lib9p_error(ctx->base, LINUX_ECANCELED, "request canceled by flush");
+ lib9p_error(&ctx->basectx, LINUX_ECANCELED, "request canceled by flush");
_lib9p_srv_flushch_send(&ctx->_flushch, true);
return -1;
}
@@ -35,31 +36,35 @@ static inline int lib9p_srv_acknowledge_flush(struct lib9p_srv_reqctx *ctx) {
struct lib9p_srv_file_vtable {
/* all */
- struct lib9p_srv_io (*io )(struct lib9p_srv_reqctx *ctx, void *impldata,
- lib9p_o_t flags);
- struct lib9p_stat (*stat )(struct lib9p_srv_reqctx *ctx, void *impldata);
- void (*wstat )(struct lib9p_srv_reqctx *ctx, void *impldata,
- struct lib9p_stat new);
- void (*remove )(struct lib9p_srv_reqctx *ctx, void *impldata);
- void (*free )(struct lib9p_srv_reqctx *ctx, void *impldata);
+ struct lib9p_srv_io (*io )(struct lib9p_srv_ctx *ctx, void *impl,
+ lib9p_o_t flags);
+ struct lib9p_stat (*stat )(struct lib9p_srv_ctx *ctx, void *impl);
+ void (*wstat )(struct lib9p_srv_ctx *ctx, void *impl,
+ struct lib9p_stat new);
+ void (*remove )(struct lib9p_srv_ctx *ctx, void *impl);
+ void (*free )(struct lib9p_srv_ctx *ctx, void *impl);
/* dir */
- struct lib9p_srv_file (*openchild )(struct lib9p_srv_reqctx *ctx, void *impldata,
- char *childname);
- struct lib9p_srv_file (*createchild)(struct lib9p_srv_reqctx *ctx, void *impldata,
- char *childname, lib9p_dm_t perm, lib9p_o_t flags);
+ struct lib9p_srv_file (*dopen )(struct lib9p_srv_ctx *ctx, void *impl,
+ char *childname);
+ struct lib9p_srv_file (*dcreate)(struct lib9p_srv_ctx *ctx, void *impl,
+ char *childname,
+ lib9p_dm_t perm, lib9p_o_t flags);
};
struct lib9p_srv_io_dir_vtable {
- size_t (*readdir )(struct lib9p_srv_reqctx *ctx, void *impldata,
- struct lib9p_stat *buf, size_t count, size_t offset);
+ size_t (*readdir)(struct lib9p_srv_ctx *ctx, void *impl,
+ struct lib9p_stat *buf, size_t count,
+ size_t offset);
};
struct lib9p_srv_io_file_vtable {
- uint32_t (*pread )(struct lib9p_srv_reqctx *ctx, void *impldata,
- void *buf, uint32_t count, uint64_t offset);
- uint32_t (*pwrite )(struct lib9p_srv_reqctx *ctx, void *impldata,
- void *buf, uint32_t count, uint64_t offset);
+ uint32_t (*pread )(struct lib9p_srv_ctx *ctx, void *impl,
+ void *buf, uint32_t count,
+ uint64_t offset);
+ uint32_t (*pwrite )(struct lib9p_srv_ctx *ctx, void *impl,
+ void *buf, uint32_t count,
+ uint64_t offset);
};
/* objects you'll deal with ***************************************************/
@@ -84,20 +89,23 @@ struct lib9p_srv_io {
void *impldata;
};
-/******************************************************************************/
+/* main server entrypoints ****************************************************/
+
+CR_RPC_DECLARE(_lib9p_srv_reqch, struct _lib9p_srv_req *, bool)
struct lib9p_srv {
/* Things you provide */
- int sockfd;
- void /*TODO*/ (*auth)(struct lib9p_srv_reqctx *ctx, char *treename);
- struct lib9p_srv_file (*rootdir)(struct lib9p_srv_reqctx *ctx, char *treename);
+ int sockfd;
+ void /*TODO*/ (*auth )(struct lib9p_srv_ctx *ctx, char *treename);
+ struct lib9p_srv_file (*rootdir)(struct lib9p_srv_ctx *ctx, char *treename);
/* For internal use */
- _lib9p_srv_reqch_t _reqch;
+ _lib9p_srv_reqch_t _reqch;
};
/**
* Will just close the connection if a T-message has a size[4] <7.
+ *
* @errno LINUX_EMSGSIZE T-message has size[4] bigger than max_msg_size
* @errno LINUX_EDOM Tversion specified an impossibly small max_msg_size
* @errno LINUX_EOPNOTSUPP T-message has an R-message type, or an unrecognized T-message type
diff --git a/lib9p/srv.c b/lib9p/srv.c
index 478a642..077db83 100644
--- a/lib9p/srv.c
+++ b/lib9p/srv.c
@@ -21,7 +21,7 @@
#define NAME reqmap
#define KEY_T uint32_t
-#define VAL_T struct lib9p_srv_reqctx
+#define VAL_T struct _lib9p_srv_req *
#define CAP CONFIG_9P_MAX_REQS
#include "map.h"
@@ -31,9 +31,9 @@
*
*/
-/* struct lib9p_srv {} is defined in <lib9p/srv.h> */
+/* struct _srv_srv {} is defined in <lib9p/srv.h> */
-struct lib9p_conn {
+struct _srv_conn {
/* immutable */
struct lib9p_srv *parent_srv;
int fd;
@@ -42,9 +42,9 @@ struct lib9p_conn {
cr_mutex_t writelock;
};
-struct lib9p_sess {
+struct _srv_sess {
/* immutable */
- struct lib9p_conn *parent_conn;
+ struct _srv_conn *parent_conn;
enum lib9p_version version;
uint32_t max_msg_size;
uint32_t rerror_overhead;
@@ -55,56 +55,78 @@ struct lib9p_sess {
struct fidmap fids;
};
-struct lib9p_req {
+struct _lib9p_srv_req {
/* immutable */
- struct lib9p_sess *parent_sess;
+ struct _srv_sess *parent_sess;
uint16_t tag;
/* mutable */
uint8_t *net_bytes; /* CONFIG_9P_MAX_MSG_SIZE-sized */
- struct lib9p_ctx ctx;
+ struct lib9p_srv_ctx ctx;
};
/* base utilities *************************************************************/
-#define nonrespond_errorf(fmt, ...) fprintf(stderr, "error: " fmt "\n" __VA_OPT__(,) __VA_ARGS__)
+#define nonrespond_errorf(fmt, ...) \
+ fprintf(stderr, "error: " fmt "\n" __VA_OPT__(,) __VA_ARGS__)
-static uint32_t rerror_overhead_for_version(enum lib9p_version version, uint8_t *scratch) {
+static uint32_t rerror_overhead_for_version(enum lib9p_version version,
+ uint8_t *scratch) {
struct lib9p_ctx empty_ctx = {
.version = version,
.max_msg_size = CONFIG_9P_MAX_MSG_SIZE,
};
struct lib9p_msg_Rerror empty_error = { 0 };
+ bool e;
+
+ e = lib9p_marshal(&empty_ctx, LIB9P_TYP_Rerror,
+ 0, /* tag */
+ &empty_error, /* host_body */
+ scratch); /* net_bytes */
+ assert(!e);
- assert(!lib9p_marshal(&empty_ctx, LIB9P_TYP_Rerror, 0, &empty_error, scratch));
uint32_t min_msg_size = decode_u32le(scratch);
+
+ /* Assert that min_msg_size + biggest_possible_MAX_ERR_SIZE
+ * won't overflow uint32... because using
+ * __builtin_add_overflow in respond_error() would be a bit
+ * much. */
assert(min_msg_size < (UINT32_MAX - UINT16_MAX));
+ /* Assert that min_msg_size doesn't overflow MAX_MSG_SIZE. */
assert(CONFIG_9P_MAX_MSG_SIZE >= min_msg_size);
return min_msg_size;
}
-static void respond_error(struct lib9p_req *req) {
- assert(req->ctx.err_num);
- assert(req->ctx.err_msg[0]);
+static void respond_error(struct _lib9p_srv_req *req) {
+ assert(req->ctx.basectx.err_num);
+ assert(req->ctx.basectx.err_msg[0]);
ssize_t r;
struct lib9p_msg_Rerror host = {
.ename = {
- .len = strnlen(req->ctx.err_msg, CONFIG_9P_MAX_ERR_SIZE),
- .utf8 = req->ctx.err_msg,
+ .len = strnlen(req->ctx.basectx.err_msg,
+ CONFIG_9P_MAX_ERR_SIZE),
+ .utf8 = req->ctx.basectx.err_msg,
},
- .errno = req->ctx.err_num,
+ .errno = req->ctx.basectx.err_num,
};
- /* Truncate the error-string if necessary to avoid needing to return ERANGE. */
- if (((uint32_t)host.ename.len) + req->parent_sess->rerror_overhead > req->parent_sess->max_msg_size)
- host.ename.len = req->parent_sess->max_msg_size - req->parent_sess->rerror_overhead;
+ struct _srv_sess *sess = req->parent_sess;
- lib9p_marshal(&req->ctx, LIB9P_TYP_Rerror, req->tag, &host, req->net_bytes);
+ /* Truncate the error-string if necessary to avoid needing to
+ * return ERANGE. The assert() in
+ * rerror_overhead_for_version() has checked that this
+ * addition doesn't overflow. */
+ if (((uint32_t)host.ename.len) + sess->rerror_overhead > sess->max_msg_size)
+ host.ename.len = sess->max_msg_size - sess->rerror_overhead;
- cr_mutex_lock(&req->parent_sess->parent_conn->writelock);
- r = netio_write(req->parent_sess->parent_conn->fd, req->net_bytes, decode_u32le(req->net_bytes));
- cr_mutex_unlock(&req->parent_sess->parent_conn->writelock);
+ lib9p_marshal(&req->ctx.basectx, LIB9P_TYP_Rerror,
+ req->tag, &host, req->net_bytes);
+
+ cr_mutex_lock(&sess->parent_conn->writelock);
+ r = netio_write(sess->parent_conn->fd,
+ req->net_bytes, decode_u32le(req->net_bytes));
+ cr_mutex_unlock(&sess->parent_conn->writelock);
if (r < 0)
nonrespond_errorf("write: %s", strerror(-r));
}
@@ -130,7 +152,7 @@ static bool read_at_least(int fd, uint8_t *buf, size_t goal, size_t *done) {
return false;
}
-static bool handle_Tmessage(struct lib9p_req *);
+static bool handle_Tmessage(struct _lib9p_srv_req *ctx);
COROUTINE lib9p_srv_read_cr(void *_srv) {
uint8_t buf[CONFIG_9P_MAX_MSG_SIZE];
@@ -142,7 +164,7 @@ COROUTINE lib9p_srv_read_cr(void *_srv) {
uint32_t initial_rerror_overhead = rerror_overhead_for_version(0, buf);
for (;;) {
- struct lib9p_conn conn = {
+ struct _srv_conn conn = {
.parent_srv = srv,
.fd = netio_accept(srv->sockfd),
.reader = cr_getcid(),
@@ -152,9 +174,9 @@ COROUTINE lib9p_srv_read_cr(void *_srv) {
continue;
}
- struct lib9p_sess sess = {
+ struct _srv_sess sess = {
.parent_conn = &conn,
- .version = 0,
+ .version = LIB9P_VER_unknown,
.max_msg_size = CONFIG_9P_MAX_MSG_SIZE,
.rerror_overhead = initial_rerror_overhead,
.initialized = false,
@@ -171,18 +193,23 @@ COROUTINE lib9p_srv_read_cr(void *_srv) {
}
if (read_at_least(conn.fd, buf, 7, &done))
goto close;
- struct lib9p_req req = {
+ struct _lib9p_srv_req req = {
.parent_sess = &sess,
.tag = decode_u16le(&buf[5]),
.net_bytes = buf,
.ctx = {
- .version = sess.version,
- .max_msg_size = sess.max_msg_size,
+ .basectx = {
+ .version = sess.version,
+ .max_msg_size = sess.max_msg_size,
+ },
},
};
if (goal > sess.max_msg_size) {
- lib9p_errorf(&req.ctx, LINUX_EMSGSIZE, "T-message larger than %s limit (%zu > %"PRIu32")",
- sess.initialized ? "negotiated" : "server", 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);
continue;
}
@@ -207,42 +234,33 @@ COROUTINE lib9p_srv_read_cr(void *_srv) {
/* write coroutine ************************************************************/
-static void handle_Tversion(struct lib9p_req *ctx, struct lib9p_msg_Tversion *req, struct lib9p_msg_Rversion *resp);
-static void handle_Tauth(struct lib9p_req *ctx, struct lib9p_msg_Tauth *req, struct lib9p_msg_Rauth *resp);
-static void handle_Tattach(struct lib9p_req *ctx, struct lib9p_msg_Tattach *req, struct lib9p_msg_Rattach *resp);
-static void handle_Tflush(struct lib9p_req *ctx, struct lib9p_msg_Tflush *req, struct lib9p_msg_Rflush *resp);
-static void handle_Twalk(struct lib9p_req *ctx, struct lib9p_msg_Twalk *req, struct lib9p_msg_Rwalk *resp);
-static void handle_Topen(struct lib9p_req *ctx, struct lib9p_msg_Topen *req, struct lib9p_msg_Ropen *resp);
-static void handle_Tcreate(struct lib9p_req *ctx, struct lib9p_msg_Tcreate *req, struct lib9p_msg_Rcreate *resp);
-static void handle_Tread(struct lib9p_req *ctx, struct lib9p_msg_Tread *req, struct lib9p_msg_Rread *resp);
-static void handle_Twrite(struct lib9p_req *ctx, struct lib9p_msg_Twrite *req, struct lib9p_msg_Rwrite *resp);
-static void handle_Tclunk(struct lib9p_req *ctx, struct lib9p_msg_Tclunk *req, struct lib9p_msg_Rclunk *resp);
-static void handle_Tremove(struct lib9p_req *ctx, struct lib9p_msg_Tremove *req, struct lib9p_msg_Rremove *resp);
-static void handle_Tstat(struct lib9p_req *ctx, struct lib9p_msg_Tstat *req, struct lib9p_msg_Rstat *resp);
-static void handle_Twstat(struct lib9p_req *ctx, struct lib9p_msg_Twstat *req, struct lib9p_msg_Rwstat *resp);
-static void handle_Tsession(struct lib9p_req *ctx, struct lib9p_msg_Tsession *req, struct lib9p_msg_Rsession *resp);
-static void handle_Tsread(struct lib9p_req *ctx, struct lib9p_msg_Tsread *req, struct lib9p_msg_Rsread *resp);
-static void handle_Tswrite(struct lib9p_req *ctx, struct lib9p_msg_Tswrite *req, struct lib9p_msg_Rswrite *resp);
-
COROUTINE lib9p_srv_write_cr(void *_srv) {
- uint8_t net[CONFIG_9P_MAX_MSG_SIZE];
+ uint8_t net[CONFIG_9P_MAX_MSG_SIZE];
+ struct _lib9p_srv_req req;
+ _lib9p_srv_reqch_req_t rpc_handle;
struct lib9p_srv *srv = _srv;
assert(srv);
cr_begin();
for (;;) {
- /* Receive the request from the reader coroutine. */
- struct lib9p_req req;
- _lib9p_srv_reqch_req_t req_handle;
- req_handle = _lib9p_srv_reqch_recv_req(&srv->_reqch);
- req = *req_handle.req;
+ /* Receive the request from the reader coroutine. ************/
+ rpc_handle = _lib9p_srv_reqch_recv_req(&srv->_reqch);
+ /* Deep-copy the request from the reader coroutine's
+ * stack to our stack. */
+ req = *rpc_handle.req;
memcpy(net, req.net_bytes, decode_u32le(req.net_bytes));
req.net_bytes = net;
- _lib9p_srv_reqch_send_resp(req_handle, 0); /* notify that we've copied req */
+ /* Record that we have it. */
+ reqmap_store(&req.parent_sess->reqs, req.tag, &req);
+ /* Notify the reader coroutine that we're done with
+ * its data. */
+ _lib9p_srv_reqch_send_resp(rpc_handle, 0);
+ /* Process the request. **************************************/
handle_Tmessage(&req);
+ /* Release resources. ****************************************/
reqmap_del(&req.parent_sess->reqs, req.tag);
if (req.parent_sess->closing && !req.parent_sess->reqs.len)
cr_unpause(req.parent_sess->parent_conn->reader);
@@ -251,96 +269,95 @@ COROUTINE lib9p_srv_write_cr(void *_srv) {
cr_end();
}
-static bool handle_Tmessage(struct lib9p_req *req) {
+#define _HANDLER_PROTO(typ) \
+ static void handle_T##typ(struct _lib9p_srv_req *, \
+ struct lib9p_msg_T##typ *, \
+ struct lib9p_msg_R##typ *)
+_HANDLER_PROTO(version);
+_HANDLER_PROTO(auth);
+_HANDLER_PROTO(attach);
+_HANDLER_PROTO(flush);
+_HANDLER_PROTO(walk);
+_HANDLER_PROTO(open);
+_HANDLER_PROTO(create);
+_HANDLER_PROTO(read);
+_HANDLER_PROTO(write);
+_HANDLER_PROTO(clunk);
+_HANDLER_PROTO(remove);
+_HANDLER_PROTO(stat);
+_HANDLER_PROTO(wstat);
+_HANDLER_PROTO(session); /* 9P2000.e */
+_HANDLER_PROTO(sread); /* 9P2000.e */
+_HANDLER_PROTO(swrite); /* 9P2000.e */
+
+typedef void (*tmessage_handler)(struct _lib9p_srv_req *, void *, void *);
+
+static tmessage_handler tmessage_handlers[0x100] = {
+ [LIB9P_TYP_Tversion] = (tmessage_handler)handle_Tversion,
+ [LIB9P_TYP_Tauth] = (tmessage_handler)handle_Tauth,
+ [LIB9P_TYP_Tattach] = (tmessage_handler)handle_Tattach,
+ [LIB9P_TYP_Tflush] = (tmessage_handler)handle_Tflush,
+ [LIB9P_TYP_Twalk] = (tmessage_handler)handle_Twalk,
+ [LIB9P_TYP_Topen] = (tmessage_handler)handle_Topen,
+ [LIB9P_TYP_Tcreate] = (tmessage_handler)handle_Tcreate,
+ [LIB9P_TYP_Tread] = (tmessage_handler)handle_Tread,
+ [LIB9P_TYP_Twrite] = (tmessage_handler)handle_Twrite,
+ [LIB9P_TYP_Tclunk] = (tmessage_handler)handle_Tclunk,
+ [LIB9P_TYP_Tremove] = (tmessage_handler)handle_Tremove,
+ [LIB9P_TYP_Tstat] = (tmessage_handler)handle_Tstat,
+ [LIB9P_TYP_Twstat] = (tmessage_handler)handle_Twstat,
+ [LIB9P_TYP_Tsession] = (tmessage_handler)handle_Tsession, /* 9P2000.e */
+ [LIB9P_TYP_Tsread] = (tmessage_handler)handle_Tsread, /* 9P2000.e */
+ [LIB9P_TYP_Tswrite] = (tmessage_handler)handle_Tswrite, /* 9P2000.e */
+};
+
+static bool handle_Tmessage(struct _lib9p_srv_req *ctx) {
uint8_t host_req[CONFIG_9P_MAX_HOSTMSG_SIZE];
uint8_t host_resp[CONFIG_9P_MAX_HOSTMSG_SIZE];
/* Unmarshal it. */
- enum lib9p_msg_type typ = req->net_bytes[4];
+ enum lib9p_msg_type typ = ctx->net_bytes[4];
if (typ % 2 != 0) {
- lib9p_errorf(&req->ctx, LINUX_EOPNOTSUPP, "expected a T-message but got an R-message: message_type=%s",
+ lib9p_errorf(&ctx->ctx.basectx,
+ LINUX_EOPNOTSUPP, "expected a T-message but got an R-message: message_type=%s",
lib9p_msg_type_str(typ));
goto write;
}
- ssize_t host_size = lib9p_validate(&req->ctx, req->net_bytes);
+ ssize_t host_size = lib9p_validate(&ctx->ctx.basectx, ctx->net_bytes);
if (host_size < 0)
goto write;
if ((size_t)host_size > sizeof(host_req)) {
- lib9p_errorf(&req->ctx, LINUX_EMSGSIZE, "unmarshalled payload larger than server limit (%zu > %zu)",
+ lib9p_errorf(&ctx->ctx.basectx,
+ LINUX_EMSGSIZE, "unmarshalled payload larger than server limit (%zu > %zu)",
host_size, sizeof(host_req));
goto write;
}
- lib9p_unmarshal(&req->ctx, req->net_bytes, &typ, &req->tag, host_req);
+ lib9p_unmarshal(&ctx->ctx.basectx, ctx->net_bytes,
+ &typ, &ctx->tag, host_req);
/* Handle it. */
- switch (typ) {
- case LIB9P_TYP_Tversion:
- handle_Tversion(req, (struct lib9p_msg_Tversion *)host_req, (struct lib9p_msg_Rversion *)host_resp);
- break;
- case LIB9P_TYP_Tauth:
- handle_Tauth(req, (struct lib9p_msg_Tauth *)host_req, (struct lib9p_msg_Rauth *)host_resp);
- break;
- case LIB9P_TYP_Tattach:
- handle_Tattach(req, (struct lib9p_msg_Tattach *)host_req, (struct lib9p_msg_Rattach *)host_resp);
- break;
- case LIB9P_TYP_Tflush:
- handle_Tflush(req, (struct lib9p_msg_Tflush *)host_req, (struct lib9p_msg_Rflush *)host_resp);
- break;
- case LIB9P_TYP_Twalk:
- handle_Twalk(req, (struct lib9p_msg_Twalk *)host_req, (struct lib9p_msg_Rwalk *)host_resp);
- break;
- case LIB9P_TYP_Topen:
- handle_Topen(req, (struct lib9p_msg_Topen *)host_req, (struct lib9p_msg_Ropen *)host_resp);
- break;
- case LIB9P_TYP_Tcreate:
- handle_Tcreate(req, (struct lib9p_msg_Tcreate *)host_req, (struct lib9p_msg_Rcreate *)host_resp);
- break;
- case LIB9P_TYP_Tread:
- handle_Tread(req, (struct lib9p_msg_Tread *)host_req, (struct lib9p_msg_Rread *)host_resp);
- break;
- case LIB9P_TYP_Twrite:
- handle_Twrite(req, (struct lib9p_msg_Twrite *)host_req, (struct lib9p_msg_Rwrite *)host_resp);
- break;
- case LIB9P_TYP_Tclunk:
- handle_Tclunk(req, (struct lib9p_msg_Tclunk *)host_req, (struct lib9p_msg_Rclunk *)host_resp);
- break;
- case LIB9P_TYP_Tremove:
- handle_Tremove(req, (struct lib9p_msg_Tremove *)host_req, (struct lib9p_msg_Rremove *)host_resp);
- break;
- case LIB9P_TYP_Tstat:
- handle_Tstat(req, (struct lib9p_msg_Tstat *)host_req, (struct lib9p_msg_Rstat *)host_resp);
- break;
- case LIB9P_TYP_Twstat:
- handle_Twstat(req, (struct lib9p_msg_Twstat *)host_req, (struct lib9p_msg_Rwstat *)host_resp);
- break;
- case LIB9P_TYP_Tsession: /* 9P2000.e */
- handle_Tsession(req, (struct lib9p_msg_Tsession *)host_req, (struct lib9p_msg_Rsession *)host_resp);
- break;
- case LIB9P_TYP_Tsread: /* 9P2000.e */
- handle_Tsread(req, (struct lib9p_msg_Tsread *)host_req, (struct lib9p_msg_Rsread *)host_resp);
- break;
- case LIB9P_TYP_Tswrite: /* 9P2000.e */
- handle_Tswrite(req, (struct lib9p_msg_Tswrite *)host_req, (struct lib9p_msg_Rswrite *)host_resp);
- break;
- default:
- assert(false);
- }
+ tmessage_handlers[typ](ctx, (void *)host_req, (void *)host_resp);
write:
- if (lib9p_ctx_has_error(&req->ctx)) {
- respond_error(req);
+ if (lib9p_ctx_has_error(&ctx->ctx.basectx)) {
+ respond_error(ctx);
return true;
} else {
- if (lib9p_marshal(&req->ctx, typ+1, req->tag, host_resp, req->net_bytes))
+ if (lib9p_marshal(&ctx->ctx.basectx, typ+1, ctx->tag, host_resp,
+ ctx->net_bytes))
goto write;
- cr_mutex_lock(&req->parent_sess->parent_conn->writelock);
- netio_write(req->parent_sess->parent_conn->fd, req->net_bytes, decode_u32le(req->net_bytes));
- cr_mutex_unlock(&req->parent_sess->parent_conn->writelock);
+
+ cr_mutex_lock(&ctx->parent_sess->parent_conn->writelock);
+ netio_write(ctx->parent_sess->parent_conn->fd,
+ ctx->net_bytes, decode_u32le(ctx->net_bytes));
+ cr_mutex_unlock(&ctx->parent_sess->parent_conn->writelock);
return false;
}
}
-static void handle_Tversion(struct lib9p_req *ctx, struct lib9p_msg_Tversion *req, struct lib9p_msg_Rversion *resp) {
+static void handle_Tversion(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 &&
@@ -361,14 +378,12 @@ static void handle_Tversion(struct lib9p_req *ctx, struct lib9p_msg_Tversion *re
uint32_t min_msg_size = rerror_overhead_for_version(version, ctx->net_bytes);
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")",
+ lib9p_errorf(&ctx->ctx.basectx,
+ LINUX_EDOM, "requested max_msg_size is less than minimum for %s (%"PRIu32" < %"PRIu32")",
version, req->max_msg_size, min_msg_size);
return;
}
- struct lib9p_srv_reqctx subctx = {
- .base = &ctx->ctx,
- };
if (ctx->parent_sess->reqs.len) {
ctx->parent_sess->closing = true;
// TODO: send flush events
@@ -379,7 +394,7 @@ static void handle_Tversion(struct lib9p_req *ctx, struct lib9p_msg_Tversion *re
uint32_t fid;
struct lib9p_srv_file *fptr;
MAP_FOREACH(&ctx->parent_sess->fids, fid, fptr) {
- fptr->vtable.free(&subctx, fptr->impldata);
+ fptr->vtable.free(&ctx->ctx, fptr->impldata);
fidmap_del(&ctx->parent_sess->fids, fid);
}
}
@@ -395,75 +410,89 @@ static void handle_Tversion(struct lib9p_req *ctx, struct lib9p_msg_Tversion *re
: req->max_msg_size;
}
-static void handle_Tauth(struct lib9p_req *ctx, struct lib9p_msg_Tauth *req, struct lib9p_msg_Rauth *UNUSED(resp)) {
- if (!ctx->parent_sess->parent_conn->parent_srv->auth) {
- lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "authentication not required");
+static void handle_Tauth(struct _lib9p_srv_req *ctx,
+ struct lib9p_msg_Tauth *req,
+ struct lib9p_msg_Rauth *UNUSED(resp)) {
+ ctx->ctx.uid = req->n_uname;
+ ctx->ctx.uname = req->uname.utf8;
+ struct lib9p_srv *srv = ctx->parent_sess->parent_conn->parent_srv;
+
+ if (!srv->auth) {
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EOPNOTSUPP, "authentication not required");
return;
}
- struct lib9p_srv_reqctx subctx = {
- .base = &ctx->ctx,
- .uid = req->n_uname,
- .uname = req->uname.utf8,
- };
- ctx->parent_sess->parent_conn->parent_srv->auth(&subctx, req->aname.utf8);
- lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "TODO: auth not implemented");
+
+ srv->auth(&ctx->ctx, req->aname.utf8);
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EOPNOTSUPP, "TODO: auth not implemented");
}
-static void handle_Tattach(struct lib9p_req *ctx, struct lib9p_msg_Tattach *req, struct lib9p_msg_Rattach *resp) {
- struct lib9p_srv_reqctx subctx = {
- .base = &ctx->ctx,
- .uid = req->n_uname,
- .uname = req->uname.utf8,
- };
- if (ctx->parent_sess->parent_conn->parent_srv->auth) {
+static void handle_Tattach(struct _lib9p_srv_req *ctx,
+ struct lib9p_msg_Tattach *req,
+ struct lib9p_msg_Rattach *resp) {
+ ctx->ctx.uid = req->n_uname;
+ ctx->ctx.uname = req->uname.utf8;
+ struct lib9p_srv *srv = ctx->parent_sess->parent_conn->parent_srv;
+
+ if (srv->auth) {
/*
struct lib9p_srv_filehandle *fh = fidmap_get(req->afid);
if (!fh)
- lib9p_error(&ctx->ctx, LINUX_EACCES, "FID provided as auth-file is not a valid FID");
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EACCES, "FID provided as auth-file is not a valid FID");
else if (fh->type != FH_AUTH)
- lib9p_error(&ctx->ctx, LINUX_EACCES, "FID provided as auth-file is not an auth-file");
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EACCES, "FID provided as auth-file is not an auth-file");
else if (strcmp(fh->data.auth.uname, req->uname.utf8) != 0)
- lib9p_errorf(&ctx->ctx, LINUX_EACCES, "FID provided as auth-file is for user=\"%s\" and cannot be used for user=\"%s\"",
+ lib9p_errorf(&ctx->ctx.basectx,
+ LINUX_EACCES, "FID provided as auth-file is for user=\"%s\" and cannot be used for user=\"%s\"",
fh->data.auth.uname, req->uname.utf8);
else if (strcmp(fh->data.auth.aname, req->aname.utf8) != 0)
- lib9p_errorf(&ctx->ctx, LINUX_EACCES, "FID provided as auth-file is for tree=\"%s\" and cannot be used for tree=\"%s\"",
+ lib9p_errorf(&ctx->ctx.basectx,
+ LINUX_EACCES, "FID provided as auth-file is for tree=\"%s\" and cannot be used for tree=\"%s\"",
fh->data.auth.aname, req->aname.utf8);
else if (!fh->data.auth.authenticated)
- lib9p_error(&ctx->ctx, LINUX_EACCES, "FID provided as auth-file has not completed authentication");
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EACCES, "FID provided as auth-file has not completed authentication");
fh->refcount--;
if (lib9p_ctx_has_error(&ctx->ctx))
return;
*/
- lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "TODO: auth not implemented");
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EOPNOTSUPP, "TODO: auth not implemented");
return;
} else {
if (req->afid != LIB9P_NOFID) {
- lib9p_error(&ctx->ctx, LINUX_EACCES, "FID provided as auth-file, but no auth-file is required");
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EACCES, "FID provided as auth-file, but no auth-file is required");
return;
}
}
if (fidmap_load(&ctx->parent_sess->fids, req->fid)) {
- lib9p_error(&ctx->ctx, LINUX_EBADF, "FID already in use");
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EBADF, "FID already in use");
return;
}
- struct lib9p_srv_file rootdir = ctx->parent_sess->parent_conn->parent_srv->rootdir(&subctx, req->aname.utf8);
- if (lib9p_ctx_has_error(&ctx->ctx))
+ struct lib9p_srv_file rootdir = srv->rootdir(&ctx->ctx, req->aname.utf8);
+ if (lib9p_ctx_has_error(&ctx->ctx.basectx))
return;
- struct lib9p_stat stat = rootdir.vtable.stat(&subctx, rootdir.impldata);
- if (lib9p_ctx_has_error(&ctx->ctx)) {
+ struct lib9p_stat stat = rootdir.vtable.stat(&ctx->ctx, rootdir.impldata);
+ if (lib9p_ctx_has_error(&ctx->ctx.basectx)) {
if (rootdir.vtable.free)
- rootdir.vtable.free(&subctx, rootdir.impldata);
+ rootdir.vtable.free(&ctx->ctx, rootdir.impldata);
return;
}
struct lib9p_srv_file *rootdir_ptr = fidmap_store(&ctx->parent_sess->fids, req->fid, rootdir);
if (!rootdir_ptr) {
- lib9p_error(&ctx->ctx, LINUX_EMFILE, "too many open files");
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EMFILE, "too many open files");
if (rootdir.vtable.free)
- rootdir.vtable.free(&subctx, rootdir.impldata);
+ rootdir.vtable.free(&ctx->ctx, rootdir.impldata);
return;
}
@@ -471,54 +500,93 @@ static void handle_Tattach(struct lib9p_req *ctx, struct lib9p_msg_Tattach *req,
return;
}
-static void handle_Tflush(struct lib9p_req *ctx, struct lib9p_msg_Tflush *UNUSED(req), struct lib9p_msg_Rflush *UNUSED(resp)) {
- lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "flush not yet implemented");
+static void handle_Tflush(struct _lib9p_srv_req *ctx,
+ struct lib9p_msg_Tflush *UNUSED(req),
+ struct lib9p_msg_Rflush *UNUSED(resp)) {
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EOPNOTSUPP, "flush not yet implemented");
}
-static void handle_Twalk(struct lib9p_req *ctx, struct lib9p_msg_Twalk *UNUSED(req), struct lib9p_msg_Rwalk *UNUSED(resp)) {
- lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "walk not yet implemented");
+static void handle_Twalk(struct _lib9p_srv_req *ctx,
+ struct lib9p_msg_Twalk *UNUSED(req),
+ struct lib9p_msg_Rwalk *UNUSED(resp)) {
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EOPNOTSUPP, "walk not yet implemented");
}
-static void handle_Topen(struct lib9p_req *ctx, struct lib9p_msg_Topen *UNUSED(req), struct lib9p_msg_Ropen *UNUSED(resp)) {
- lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "open not yet implemented");
+static void handle_Topen(struct _lib9p_srv_req *ctx,
+ struct lib9p_msg_Topen *UNUSED(req),
+ struct lib9p_msg_Ropen *UNUSED(resp)) {
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EOPNOTSUPP, "open not yet implemented");
}
-static void handle_Tcreate(struct lib9p_req *ctx, struct lib9p_msg_Tcreate *UNUSED(req), struct lib9p_msg_Rcreate *UNUSED(resp)) {
- lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "create not yet implemented");
+static void handle_Tcreate(struct _lib9p_srv_req *ctx,
+ struct lib9p_msg_Tcreate *UNUSED(req),
+ struct lib9p_msg_Rcreate *UNUSED(resp)) {
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EOPNOTSUPP, "create not yet implemented");
}
-static void handle_Tread(struct lib9p_req *ctx, struct lib9p_msg_Tread *UNUSED(req), struct lib9p_msg_Rread *UNUSED(resp)) {
- lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "read not yet implemented");
+static void handle_Tread(struct _lib9p_srv_req *ctx,
+ struct lib9p_msg_Tread *UNUSED(req),
+ struct lib9p_msg_Rread *UNUSED(resp)) {
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EOPNOTSUPP, "read not yet implemented");
}
-static void handle_Twrite(struct lib9p_req *ctx, struct lib9p_msg_Twrite *UNUSED(req), struct lib9p_msg_Rwrite *UNUSED(resp)) {
- lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "write not yet implemented");
+static void handle_Twrite(struct _lib9p_srv_req *ctx,
+ struct lib9p_msg_Twrite *UNUSED(req),
+ struct lib9p_msg_Rwrite *UNUSED(resp)) {
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EOPNOTSUPP, "write not yet implemented");
}
-static void handle_Tclunk(struct lib9p_req *ctx, struct lib9p_msg_Tclunk *UNUSED(req), struct lib9p_msg_Rclunk *UNUSED(resp)) {
- lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "clunk not yet implemented");
+static void handle_Tclunk(struct _lib9p_srv_req *ctx,
+ struct lib9p_msg_Tclunk *UNUSED(req),
+ struct lib9p_msg_Rclunk *UNUSED(resp)) {
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EOPNOTSUPP, "clunk not yet implemented");
}
-static void handle_Tremove(struct lib9p_req *ctx, struct lib9p_msg_Tremove *UNUSED(req), struct lib9p_msg_Rremove *UNUSED(resp)) {
- lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "remove not yet implemented");
+static void handle_Tremove(struct _lib9p_srv_req *ctx,
+ struct lib9p_msg_Tremove *UNUSED(req),
+ struct lib9p_msg_Rremove *UNUSED(resp)) {
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EOPNOTSUPP, "remove not yet implemented");
}
-static void handle_Tstat(struct lib9p_req *ctx, struct lib9p_msg_Tstat *UNUSED(req), struct lib9p_msg_Rstat *UNUSED(resp)) {
- lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "stat not yet implemented");
+static void handle_Tstat(struct _lib9p_srv_req *ctx,
+ struct lib9p_msg_Tstat *UNUSED(req),
+ struct lib9p_msg_Rstat *UNUSED(resp)) {
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EOPNOTSUPP, "stat not yet implemented");
}
-static void handle_Twstat(struct lib9p_req *ctx, struct lib9p_msg_Twstat *UNUSED(req), struct lib9p_msg_Rwstat *UNUSED(resp)) {
- lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "wstat not yet implemented");
+static void handle_Twstat(struct _lib9p_srv_req *ctx,
+ struct lib9p_msg_Twstat *UNUSED(req),
+ struct lib9p_msg_Rwstat *UNUSED(resp)) {
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EOPNOTSUPP, "wstat not yet implemented");
}
-static void handle_Tsession(struct lib9p_req *ctx, struct lib9p_msg_Tsession *UNUSED(req), struct lib9p_msg_Rsession *UNUSED(resp)) {
- lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "session not yet implemented");
+static void handle_Tsession(struct _lib9p_srv_req *ctx,
+ struct lib9p_msg_Tsession *UNUSED(req),
+ struct lib9p_msg_Rsession *UNUSED(resp)) {
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EOPNOTSUPP, "session not yet implemented");
}
-static void handle_Tsread(struct lib9p_req *ctx, struct lib9p_msg_Tsread *UNUSED(req), struct lib9p_msg_Rsread *UNUSED(resp)) {
- lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "sread not yet implemented");
+static void handle_Tsread(struct _lib9p_srv_req *ctx,
+ struct lib9p_msg_Tsread *UNUSED(req),
+ struct lib9p_msg_Rsread *UNUSED(resp)) {
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EOPNOTSUPP, "sread not yet implemented");
}
-static void handle_Tswrite(struct lib9p_req *ctx, struct lib9p_msg_Tswrite *UNUSED(req), struct lib9p_msg_Rswrite *UNUSED(resp)) {
- lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "swrite not yet implemented");
+static void handle_Tswrite(struct _lib9p_srv_req *ctx,
+ struct lib9p_msg_Tswrite *UNUSED(req),
+ struct lib9p_msg_Rswrite *UNUSED(resp)) {
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EOPNOTSUPP, "swrite not yet implemented");
}