summaryrefslogtreecommitdiff
path: root/lib9p
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p')
-rw-r--r--lib9p/9p.c32
-rwxr-xr-xlib9p/idl.gen44
-rw-r--r--lib9p/internal.h6
-rw-r--r--lib9p/map.h4
-rw-r--r--lib9p/srv.c10
5 files changed, 67 insertions, 29 deletions
diff --git a/lib9p/9p.c b/lib9p/9p.c
index 51ff2eb..c54dae7 100644
--- a/lib9p/9p.c
+++ b/lib9p/9p.c
@@ -124,10 +124,12 @@ ssize_t _lib9p_validate(uint8_t xxx_low_typ_bit,
struct lib9p_ctx *ctx, uint8_t *net_bytes) {
/* Inspect the first 5 bytes ourselves. */
struct _validate_ctx subctx = {
+ /* input */
.ctx = ctx,
.net_size = uint32le_decode(net_bytes),
.net_bytes = net_bytes,
+ /* output */
.net_offset = 0,
.host_extra = 0,
};
@@ -171,17 +173,19 @@ static
void _lib9p_unmarshal(const struct _lib9p_recv_tentry xxx_table[LIB9P_VER_NUM][0x80],
struct lib9p_ctx *ctx, uint8_t *net_bytes,
enum lib9p_msg_type *ret_typ, void *ret_body) {
+ enum lib9p_msg_type typ = net_bytes[4];
+ *ret_typ = typ;
+ struct _lib9p_recv_tentry tentry = xxx_table[ctx->version][typ/2];
+
struct _unmarshal_ctx subctx = {
+ /* input */
.ctx = ctx,
.net_bytes = net_bytes,
+ /* output */
.net_offset = 0,
+ .extra = ret_body + tentry.basesize,
};
-
- enum lib9p_msg_type typ = net_bytes[4];
- *ret_typ = typ;
- struct _lib9p_recv_tentry tentry = xxx_table[ctx->version][typ/2];
- subctx.extra = ret_body + tentry.basesize;
tentry.unmarshal(&subctx, ret_body);
}
@@ -202,7 +206,10 @@ bool _lib9p_marshal(const struct _lib9p_send_tentry xxx_table[LIB9P_VER_NUM][0x8
struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body,
uint8_t *ret_bytes) {
struct _marshal_ctx subctx = {
+ /* input */
.ctx = ctx,
+
+ /* ouptut */
.net_bytes = ret_bytes,
.net_offset = 0,
};
@@ -228,10 +235,12 @@ bool lib9p_Rmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *bo
bool lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes,
uint32_t *ret_net_size, ssize_t *ret_host_size) {
struct _validate_ctx subctx = {
+ /* input */
.ctx = ctx,
.net_size = net_size,
.net_bytes = net_bytes,
+ /* output */
.net_offset = 0,
.host_extra = 0,
};
@@ -248,11 +257,13 @@ bool lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_
uint32_t lib9p_stat_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes,
struct lib9p_stat *ret_obj, void *ret_extra) {
struct _unmarshal_ctx subctx = {
- .ctx = ctx,
- .net_bytes = net_bytes,
- .net_offset = 0,
+ /* input */
+ .ctx = ctx,
+ .net_bytes = net_bytes,
- .extra = ret_extra,
+ /* output */
+ .net_offset = 0,
+ .extra = ret_extra,
};
_lib9p_stat_unmarshal(&subctx, ret_obj);
return subctx.net_offset;
@@ -263,7 +274,10 @@ uint32_t lib9p_stat_marshal(struct lib9p_ctx *ctx, uint32_t max_net_size, struct
struct lib9p_ctx _ctx = *ctx;
_ctx.max_msg_size = max_net_size;
struct _marshal_ctx subctx = {
+ /* input */
.ctx = &_ctx,
+
+ /* output */
.net_bytes = ret_bytes,
.net_offset = 0,
};
diff --git a/lib9p/idl.gen b/lib9p/idl.gen
index 8782771..adb15ce 100755
--- a/lib9p/idl.gen
+++ b/lib9p/idl.gen
@@ -53,13 +53,13 @@ def c_ver_enum(ver: str) -> str:
return f"{idprefix.upper()}VER_{ver.replace('.', '_')}"
-def c_ver_ifdef(versions: set[str]) -> str:
+def c_ver_ifdef(versions: typing.Collection[str]) -> str:
return " || ".join(
f"CONFIG_9P_ENABLE_{v.replace('.', '_')}" for v in sorted(versions)
)
-def c_ver_cond(versions: set[str]) -> str:
+def c_ver_cond(versions: typing.Collection[str]) -> str:
if len(versions) == 1:
v = next(v for v in versions)
return f"is_ver(ctx, {v.replace('.', '_')})"
@@ -84,7 +84,7 @@ def c_typename(typ: idl.Type, parent: idl.StructMember | None = None) -> str:
raise ValueError(f"not a type: {typ.__class__.__name__}")
-def c_expr(expr: idl.Expr) -> str:
+def c_expr(expr: idl.Expr, lookup_sym: typing.Callable[[str], str]) -> str:
ret: list[str] = []
for tok in expr.tokens:
match tok:
@@ -92,14 +92,14 @@ def c_expr(expr: idl.Expr) -> str:
ret.append(tok.op)
case idl.ExprLit():
ret.append(str(tok.val))
- case idl.ExprSym(name="end"):
- ret.append("ctx->net_offset")
case idl.ExprSym(name="s32_max"):
ret.append("INT32_MAX")
case idl.ExprSym(name="s64_max"):
ret.append("INT64_MAX")
case idl.ExprSym():
- ret.append(f"_{tok.name[1:]}_offset")
+ ret.append(lookup_sym(tok.name))
+ case _:
+ assert False
return " ".join(ret)
@@ -411,7 +411,7 @@ def gen_c(versions: set[str], typs: list[idl.Type]) -> str:
ret += f"""
/* strings ********************************************************************/
-const char *_lib9p_table_ver_name[{c_ver_enum('NUM')}] = {{
+const char *_{idprefix}table_ver_name[{c_ver_enum('NUM')}] = {{
"""
for ver in ["unknown", *sorted(versions)]:
if ver in versions:
@@ -573,17 +573,26 @@ LM_ALWAYS_INLINE static bool validate_8(struct _validate_ctx *ctx) { return _val
# Pass 4 - validate ,max= and ,val= constraints
for member in typ.members:
+
+ def lookup_sym(sym: str) -> str:
+ match sym:
+ case "end":
+ return "ctx->net_offset"
+ case _:
+ assert sym.startswith("&")
+ return f"_{sym[1:]}_offset"
+
if member.max:
assert member.static_size
nbits = member.static_size * 8
ret += ifdef_push(2, c_ver_ifdef(member.in_versions))
- ret += f"\t || ({{ uint{nbits}_t max = {c_expr(member.max)}; (((uint{nbits}_t){member.name}) > max) &&\n"
+ ret += f"\t || ({{ uint{nbits}_t max = {c_expr(member.max, lookup_sym)}; (((uint{nbits}_t){member.name}) > max) &&\n"
ret += f'\t lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "{member.name} value is too large (%"PRIu{nbits}" > %"PRIu{nbits}")", {member.name}, max); }})\n'
if member.val:
assert member.static_size
nbits = member.static_size * 8
ret += ifdef_push(2, c_ver_ifdef(member.in_versions))
- ret += f"\t || ({{ uint{nbits}_t exp = {c_expr(member.val)}; (((uint{nbits}_t){member.name}) != exp) &&\n"
+ ret += f"\t || ({{ uint{nbits}_t exp = {c_expr(member.val, lookup_sym)}; (((uint{nbits}_t){member.name}) != exp) &&\n"
ret += f'\t lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "{member.name} value is wrong (actual:%"PRIu{nbits}" != correct:%"PRIu{nbits}")", (uint{nbits}_t){member.name}, exp); }})\n'
ret += ifdef_pop(1)
@@ -775,10 +784,19 @@ LM_ALWAYS_INLINE static bool marshal_8(struct _marshal_ctx *ctx, uint64_t *val)
if member.val:
assert member.static_size
ret += ifdef_push(2, c_ver_ifdef(member.in_versions))
+
+ def lookup_sym(sym: str) -> str:
+ match sym:
+ case "end":
+ return "ctx->net_offset"
+ case _:
+ assert sym.startswith("&")
+ return f"_{sym[1:]}_offset"
+
if member.static_size == 1:
- ret += f"\t || ({{ ctx->net_bytes[_{member.name}_offset] = {c_expr(member.val)}; false; }})\n"
+ ret += f"\t || ({{ ctx->net_bytes[_{member.name}_offset] = {c_expr(member.val, lookup_sym)}; false; }})\n"
else:
- ret += f"\t || ({{ uint{member.static_size*8}le_encode(&ctx->net_bytes[_{member.name}_offset], {c_expr(member.val)}); false; }})\n"
+ ret += f"\t || ({{ uint{member.static_size*8}le_encode(&ctx->net_bytes[_{member.name}_offset], {c_expr(member.val, lookup_sym)}); false; }})\n"
ret += ifdef_pop(1)
ret += "\t ;\n"
@@ -815,10 +833,10 @@ LM_ALWAYS_INLINE static bool marshal_8(struct _marshal_ctx *ctx, uint64_t *val)
LM_FLATTEN bool _{idprefix}stat_validate(struct _validate_ctx *ctx) {{
\treturn validate_stat(ctx);
}}
-LM_FLATTEN void _{idprefix}stat_unmarshal(struct _unmarshal_ctx *ctx, struct lib9p_stat *out) {{
+LM_FLATTEN void _{idprefix}stat_unmarshal(struct _unmarshal_ctx *ctx, struct {idprefix}stat *out) {{
\tunmarshal_stat(ctx, out);
}}
-LM_FLATTEN bool _{idprefix}stat_marshal(struct _marshal_ctx *ctx, struct lib9p_stat *val) {{
+LM_FLATTEN bool _{idprefix}stat_marshal(struct _marshal_ctx *ctx, struct {idprefix}stat *val) {{
\treturn marshal_stat(ctx, val);
}}
"""
diff --git a/lib9p/internal.h b/lib9p/internal.h
index d939d46..a648532 100644
--- a/lib9p/internal.h
+++ b/lib9p/internal.h
@@ -39,10 +39,12 @@ static_assert(CONFIG_9P_MAX_HOSTMSG_SIZE <= SSIZE_MAX);
/* specialized contexts *******************************************************/
struct _validate_ctx {
+ /* input */
struct lib9p_ctx *ctx;
uint32_t net_size;
uint8_t *net_bytes;
+ /* output */
uint32_t net_offset;
/* Increment `host_extra` to pre-allocate space that is
* "extra" beyond sizeof(). */
@@ -51,9 +53,11 @@ struct _validate_ctx {
typedef bool (*_validate_fn_t)(struct _validate_ctx *ctx);
struct _unmarshal_ctx {
+ /* input */
struct lib9p_ctx *ctx;
uint8_t *net_bytes;
+ /* output */
uint32_t net_offset;
/* `extra` points to the beginning of unallocated space. */
void *extra;
@@ -61,8 +65,10 @@ struct _unmarshal_ctx {
typedef void (*_unmarshal_fn_t)(struct _unmarshal_ctx *ctx, void *out);
struct _marshal_ctx {
+ /* input */
struct lib9p_ctx *ctx;
+ /* output */
uint8_t *net_bytes;
uint32_t net_offset;
};
diff --git a/lib9p/map.h b/lib9p/map.h
index b59c83d..ab9564f 100644
--- a/lib9p/map.h
+++ b/lib9p/map.h
@@ -1,6 +1,6 @@
-/* lib9p/map.h - A really dumb map/dict data structur
+/* lib9p/map.h - A really dumb map/dict data structure
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
diff --git a/lib9p/srv.c b/lib9p/srv.c
index 0e58068..9837994 100644
--- a/lib9p/srv.c
+++ b/lib9p/srv.c
@@ -205,12 +205,12 @@ static void respond_error(struct _lib9p_srv_req *req) {
/* read coroutine *************************************************************/
-static bool read_at_least(lo_interface net_stream_conn fd, uint8_t *buf, size_t goal, size_t *done) {
+static bool read_exactly(lo_interface net_stream_conn fd, uint8_t *buf, size_t goal, size_t *done) {
assert(buf);
assert(goal);
assert(done);
while (*done < goal) {
- ssize_t r = LO_CALL(fd, read, &buf[*done], CONFIG_9P_MAX_MSG_SIZE - *done);
+ ssize_t r = LO_CALL(fd, read, &buf[*done], goal - *done);
if (r < 0) {
nonrespond_errorf("read: %s", net_strerror(-r));
return true;
@@ -263,14 +263,14 @@ static void handle_message(struct _lib9p_srv_req *ctx);
nextmsg:
/* Read the message. */
size_t done = 0;
- if (read_at_least(conn.fd, buf, 4, &done))
+ if (read_exactly(conn.fd, buf, 4, &done))
goto close;
size_t goal = uint32le_decode(buf);
if (goal < 7) {
nonrespond_errorf("T-message is impossibly small");
goto close;
}
- if (read_at_least(conn.fd, buf, 7, &done))
+ if (read_exactly(conn.fd, buf, 7, &done))
goto close;
struct _lib9p_srv_req req = {
.parent_sess = &sess,
@@ -292,7 +292,7 @@ static void handle_message(struct _lib9p_srv_req *ctx);
respond_error(&req);
goto nextmsg;
}
- if (read_at_least(conn.fd, buf, goal, &done))
+ if (read_exactly(conn.fd, buf, goal, &done))
goto close;
/* Handle the message... */