diff options
Diffstat (limited to 'lib9p/srv_include')
-rw-r--r-- | lib9p/srv_include/lib9p/srv.h | 145 |
1 files changed, 79 insertions, 66 deletions
diff --git a/lib9p/srv_include/lib9p/srv.h b/lib9p/srv_include/lib9p/srv.h index 89dc986..ce82e59 100644 --- a/lib9p/srv_include/lib9p/srv.h +++ b/lib9p/srv_include/lib9p/srv.h @@ -17,6 +17,11 @@ #include <lib9p/core.h> +#ifndef CONFIG_9P_SRV_MAX_ERR_SIZE + #error config.h must define CONFIG_9P_SRV_MAX_ERR_SIZE +#endif +static_assert(CONFIG_9P_SRV_MAX_ERR_SIZE <= UINT16_MAX); + /* context ********************************************************************/ struct lib9p_srv_userid { @@ -45,8 +50,7 @@ struct lib9p_srv_ctx { struct _lib9p_srv_sess *parent_sess; lib9p_tag_t tag; uint8_t *net_bytes; - _lib9p_srv_flush_ch_t flush_ch; - bool flush_acknowledged; + _lib9p_srv_flush_ch_t flush_ch; /* flushers for this req _read_ from here */ bool responded; END_PRIVATE(LIB9P_SRV_H); }; @@ -55,20 +59,13 @@ struct lib9p_srv_ctx { * Return whether there is an outstanding Tflush or Tversion * cancellation of this request. After becoming true, this may go * back to false if the Tflush itself is flushed. + * + * As a special case, returning E_POSIX_ECANCELED indicates that the + * flush has been observed, and a Rerror should not be sent ot the + * client. */ bool lib9p_srv_flush_requested(struct lib9p_srv_ctx *ctx); -/** - * Acknowledge that the handler is responding to an outstanding flush; - * a non-Rerror R-message will be elided in favor of Rflush/Rversion. - * lib9p_srv_flush_requested() must be true; so do not cr_yield() - * between checking lib9p_srv_flush_requested() and calling - * lib9p_srv_acknowledge_flush(). These are separate calls to - * facilitate cases where a flush merely truncates a call, instead of - * totally canceling it. - */ -void lib9p_srv_acknowledge_flush(struct lib9p_srv_ctx *ctx); - /* version-independent stat ***************************************************/ struct lib9p_srv_stat { @@ -95,18 +92,22 @@ struct lib9p_srv_stat { struct lib9p_s extension; #endif }; +typedef struct lib9p_srv_stat lib9p_srv_stat; +DECLARE_ERROR_OR(lib9p_srv_stat); void lib9p_srv_stat_assert(struct lib9p_srv_stat stat); /* interface definitions ******************************************************/ +typedef struct iovec iovec; +DECLARE_ERROR_OR(iovec); + struct lib9p_srv_dirent { struct lib9p_qid qid; struct lib9p_s name; }; - -lo_interface lib9p_srv_fio; -lo_interface lib9p_srv_dio; +typedef struct lib9p_srv_dirent lib9p_srv_dirent; +DECLARE_ERROR_OR(lib9p_srv_dirent); /* FIXME: I don't like that the pointer returned by pread() has to * remain live after it returns. Perhaps a `respond()`-callback? But @@ -114,6 +115,46 @@ lo_interface lib9p_srv_dio; * * FIXME: It would be nice if pread() could return more than 1 iovec. */ +#define lib9p_srv_fio_LO_IFACE /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ \ + LO_FUNC(struct lib9p_qid , qid ) \ + LO_FUNC(void , iofree ) \ + LO_FUNC(uint32_t , iounit ) \ + LO_FUNC(iovec_or_error , pread , struct lib9p_srv_ctx *, \ + uint32_t byte_count, \ + uint64_t byte_offset) \ + /** \ + * If the file was append-only when fopen()ed, then byte_offset will \ + * always be 0. \ + */ \ + LO_FUNC(uint32_t_or_error , pwrite , struct lib9p_srv_ctx *, \ + void *buf, \ + uint32_t byte_count, \ + uint64_t byte_offset) +LO_INTERFACE(lib9p_srv_fio); /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ +typedef lo_interface lib9p_srv_fio lib9p_srv_fio; +DECLARE_ERROR_OR(lib9p_srv_fio); + +#define lib9p_srv_dio_LO_IFACE /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ \ + LO_FUNC(struct lib9p_qid , qid ) \ + LO_FUNC(void , iofree ) \ + /** \ + * Return the idx-th dirent. idx will always be either 0 or \ + * prev_idx+1. A dirent with an empty name signals EOF. The string \ + * must remain valid until the next dread() call or iofree(). \ + */ \ + LO_FUNC(lib9p_srv_dirent_or_error , dread , struct lib9p_srv_ctx *, \ + size_t idx) +LO_INTERFACE(lib9p_srv_dio); /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ +typedef lo_interface lib9p_srv_dio lib9p_srv_dio; +DECLARE_ERROR_OR(lib9p_srv_dio); + +struct _lo_lib9p_srv_file_vtable; +lo_interface lib9p_srv_file { + void *self; + const struct _lo_lib9p_srv_file_vtable *vtable; +}; +typedef lo_interface lib9p_srv_file lib9p_srv_file; +DECLARE_ERROR_OR(lib9p_srv_file); #define lib9p_srv_file_LO_IFACE /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ \ /* resource management **********************************************/ \ \ @@ -139,16 +180,16 @@ lo_interface lib9p_srv_dio; /* non-"opened" generic I/O *****************************************/ \ \ /** Strings returned from stat() must remain valid until free(). */ \ - LO_FUNC(struct lib9p_srv_stat , stat , struct lib9p_srv_ctx *) \ - LO_FUNC(void , wstat , struct lib9p_srv_ctx *, \ + LO_FUNC(lib9p_srv_stat_or_error , stat , struct lib9p_srv_ctx *) \ + LO_FUNC(error , wstat , struct lib9p_srv_ctx *, \ struct lib9p_srv_stat) \ - LO_FUNC(void , remove , struct lib9p_srv_ctx *) \ + LO_FUNC(error , remove , struct lib9p_srv_ctx *) \ \ /* non-"opened" directory I/O ***************************************/ \ \ - LO_FUNC(lo_interface lib9p_srv_file, dwalk , struct lib9p_srv_ctx *, \ + LO_FUNC(lib9p_srv_file_or_error , dwalk , struct lib9p_srv_ctx *, \ struct lib9p_s childname) \ - LO_FUNC(lo_interface lib9p_srv_file, dcreate, struct lib9p_srv_ctx *, \ + LO_FUNC(lib9p_srv_file_or_error , dcreate, struct lib9p_srv_ctx *, \ struct lib9p_s childname, \ struct lib9p_srv_userid *user, \ struct lib9p_srv_userid *group, \ @@ -156,50 +197,22 @@ lo_interface lib9p_srv_dio; \ /* open() for I/O ***************************************************/ \ \ - LO_FUNC(lo_interface lib9p_srv_fio , fopen , struct lib9p_srv_ctx *, \ + LO_FUNC(lib9p_srv_fio_or_error , fopen , struct lib9p_srv_ctx *, \ bool rd, bool wr, \ bool trunc) \ - LO_FUNC(lo_interface lib9p_srv_dio , dopen , struct lib9p_srv_ctx *) + LO_FUNC(lib9p_srv_dio_or_error , dopen , struct lib9p_srv_ctx *) LO_INTERFACE(lib9p_srv_file); /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ -#define lib9p_srv_fio_LO_IFACE /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ \ - LO_FUNC(struct lib9p_qid , qid ) \ - LO_FUNC(void , iofree ) \ - LO_FUNC(uint32_t , iounit ) \ - LO_FUNC(void , pread , struct lib9p_srv_ctx *, \ - uint32_t byte_count, \ - uint64_t byte_offset, \ - struct iovec *ret) \ - /** \ - * If the file was append-only when fopen()ed, then byte_offset will \ - * always be 0. \ - */ \ - LO_FUNC(uint32_t , pwrite , struct lib9p_srv_ctx *, \ - void *buf, \ - uint32_t byte_count, \ - uint64_t byte_offset) -LO_INTERFACE(lib9p_srv_fio); /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - -#define lib9p_srv_dio_LO_IFACE /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ \ - LO_FUNC(struct lib9p_qid , qid ) \ - LO_FUNC(void , iofree ) \ - /** \ - * Return the idx-th dirent. idx will always be either 0 or \ - * prev_idx+1. A dirent with an empty name signals EOF. The string \ - * must remain valid until the next dread() call or iofree(). \ - */ \ - LO_FUNC(struct lib9p_srv_dirent , dread , struct lib9p_srv_ctx *, \ - size_t idx) -LO_INTERFACE(lib9p_srv_dio); /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - #define LIB9P_SRV_NOTDIR(TYP, NAM) \ - static lo_interface lib9p_srv_file NAM##_dwalk (TYP *, struct lib9p_srv_ctx *, struct lib9p_s) { assert_notreached("not a directory"); } \ - static lo_interface lib9p_srv_file NAM##_dcreate(TYP *, struct lib9p_srv_ctx *, struct lib9p_s, \ - struct lib9p_srv_userid *, struct lib9p_srv_userid *, lib9p_dm_t) { assert_notreached("not a directory"); } \ - static lo_interface lib9p_srv_dio NAM##_dopen (TYP *, struct lib9p_srv_ctx *) { assert_notreached("not a directory"); } + static lib9p_srv_file_or_error NAM##_dwalk (TYP *, struct lib9p_srv_ctx *, struct lib9p_s) { assert_notreached("not a directory"); } \ + static lib9p_srv_file_or_error NAM##_dcreate(TYP *, struct lib9p_srv_ctx *, struct lib9p_s, \ + struct lib9p_srv_userid *, struct lib9p_srv_userid *, lib9p_dm_t) { assert_notreached("not a directory"); } \ + static lib9p_srv_dio_or_error NAM##_dopen (TYP *, struct lib9p_srv_ctx *) { assert_notreached("not a directory"); } \ + LM_FORCE_SEMICOLON #define LIB9P_SRV_NOTFILE(TYP, NAM) \ - static lo_interface lib9p_srv_fio NAM##_fopen (TYP *, struct lib9p_srv_ctx *, bool, bool, bool) { assert_notreached("not a file"); } + static lib9p_srv_fio_or_error NAM##_fopen (TYP *, struct lib9p_srv_ctx *, bool, bool, bool) { assert_notreached("not a file"); } \ + LM_FORCE_SEMICOLON /* main server entrypoints ****************************************************/ @@ -215,9 +228,9 @@ LO_INTERFACE(net_stream_conn_unix); struct lib9p_srv { /* Things you provide */ - void /*TODO*/ (*auth )(struct lib9p_srv_ctx *, struct lib9p_s treename); /* optional */ - lo_interface lib9p_srv_file (*rootdir)(struct lib9p_srv_ctx *, struct lib9p_s treename); - void (*msglog )(struct lib9p_srv_ctx *, enum lib9p_msg_type, void *hostmsg); /* optional */ + error /*TODO*/ (*auth )(struct lib9p_srv_ctx *, struct lib9p_s treename); /* optional */ + lib9p_srv_file_or_error (*rootdir)(struct lib9p_srv_ctx *, struct lib9p_s treename); + void (*msglog )(struct lib9p_srv_ctx *, enum lib9p_msg_type, void *hostmsg); /* optional */ #if CONFIG_9P_ENABLE_9P2000_p9p lo_interface net_stream_conn_unix (*type_assert_unix)(lo_interface net_stream_conn); /* optional */ #endif @@ -263,10 +276,10 @@ void lib9p_srv_accept_and_read_loop(struct lib9p_srv *srv, lo_interface net_stre * * Errors that this function itself may send to clients: * - * @errno L_EMSGSIZE T-message has size[4] bigger than max_msg_size - * @errno L_EDOM Tversion specified an impossibly small max_msg_size - * @errno L_EOPNOTSUPP T-message has an R-message type, or an unrecognized T-message type - * @errno L_EBADMSG T-message has wrong size[4] for its content, or has invalid UTF-8 + * @errno E_POSIX_EMSGSIZE T-message has size[4] bigger than max_msg_size + * @errno E_POSIX_EDOM Tversion specified an impossibly small max_msg_size + * @errno E_POSIX_EOPNOTSUPP T-message has an R-message type, or an unrecognized T-message type + * @errno E_POSIX_EBADMSG T-message has wrong size[4] for its content, or has invalid UTF-8 */ void lib9p_srv_read(struct lib9p_srv *srv, lo_interface net_stream_conn conn); @@ -291,7 +304,7 @@ void lib9p_srv_worker_loop(struct lib9p_srv *srv); * * Errors that this function itself may send to clients: * - * @errno L_ERANGE R-message does not fit into max_msg_size + * @errno E_POSIX_ERANGE R-message does not fit into max_msg_size */ void lib9p_srv_worker(struct lib9p_srv_ctx *req); |