diff options
Diffstat (limited to 'lib9p')
-rw-r--r-- | lib9p/include/lib9p/srv.h | 64 | ||||
-rw-r--r-- | lib9p/srv.c | 438 |
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"); } |