summaryrefslogtreecommitdiff
path: root/lib9p/9p.c
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-09-27 22:27:01 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-09-27 22:27:01 -0600
commit7ec97df3ee8edfd102fe573eaa61cf4e5c6284cb (patch)
treee696f30da5645cdd3cb09971d9544622e9943bcf /lib9p/9p.c
parentfa357459f88bb8f0170d1a68df66e7d068d59996 (diff)
wip fixes
Diffstat (limited to 'lib9p/9p.c')
-rw-r--r--lib9p/9p.c72
1 files changed, 44 insertions, 28 deletions
diff --git a/lib9p/9p.c b/lib9p/9p.c
index 64b09a6..8d53815 100644
--- a/lib9p/9p.c
+++ b/lib9p/9p.c
@@ -13,12 +13,12 @@
#include "internal.h"
-enum lib9p_version lib9p_ctx_version(lib9p_ctx *ctx) {
+enum lib9p_version lib9p_ctx_version(struct lib9p_ctx *ctx) {
assert(ctx);
return ctx->version;
}
-uint32_t lib9p_ctx_max_msg_size(lib9p_ctx *ctx) {
+uint32_t lib9p_ctx_max_msg_size(struct lib9p_ctx *ctx) {
assert(ctx);
return ctx->max_msg_size;
}
@@ -45,50 +45,66 @@ int lib9p_errorf(struct lib9p_ctx *ctx, uint32_t linux_errno, char const *fmt, .
return -1;
}
-size_t lib9p_unmarshal_size(struct lib9p_ctx *ctx, uint8_t *net_bytes) {
+ssize_t lib9p_unmarshal_size(struct lib9p_ctx *ctx, uint8_t *net_bytes) {
/* Header */
- uint32_t net_len = decode_u32le(net_bytes);
- if (net_len < 7)
+ struct _checksize_ctx subctx = {
+ .ctx = ctx,
+ .net_size = decode_u32le(net_bytes),
+ .net_bytes = net_bytes,
+
+ .net_offset = 7,
+ .host_extra = 0,
+ };
+ if (subctx.net_size < subctx.net_offset)
return lib9p_error(ctx, LINUX_EBADMSG, "message is too short");
uint8_t typ = net_bytes[4];
- uint32_t net_offset = 7;
/* Body */
- if (!versions[ctx->version]->msgs[typ].unmarshal_extrasize)
+ struct _vtable_msg vtable = _lib9p_vtables[ctx->version].msgs[typ];
+ if (!vtable.unmarshal_extrasize)
return lib9p_errorf(ctx, LINUX_EOPNOTSUPP, "unknown message type %"PRIu8, typ);
- size_t host_size = versions[ctx->version]->msgs[typ].unmarshal_basesize;
- if (versions[ctx->version]->msgs[typ].unmarshal_extrasize(net_len, net_bytes, &net_offset, &host_size))
- return lib9p_error(ctx, LINUX_EBADMSG, "message is too short for content");
+ if (vtable.unmarshal_extrasize(&subctx))
+ return -1;
- return host_size;
+ return (ssize_t)(vtable.unmarshal_basesize + subctx.host_extra);
}
-uint8_t lib9p_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, uint16_t *out_tag, void *out_body) {
+void lib9p_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes,
+ enum lib9p_msg_type *ret_typ, uint16_t *ret_tag, void *ret_body) {
/* Header */
- uint8_t typ = net_bytes[4];
- *out_tag = decode_u16le(&net_bytes[5]);
- uint32_t net_offset = 7;
+ struct _unmarshal_ctx subctx = {
+ .ctx = ctx,
+ .net_bytes = net_bytes,
- /* Body */
- void *host_extra = out_body + versions[ctx->version]->msgs[typ].unmarshal_basesize;
- if (versions[ctx->version]->msgs[typ].unmarshal(net_bytes, &net_offset, &host_extra, out_body))
- return lib9p_error(ctx, LINUX_EBADMSG, "message contains invalid UTF-8");
+ .net_offset = 7,
+ };
+ *ret_typ = net_bytes[4];
+ *ret_tag = decode_u16le(&net_bytes[5]);
- return typ;
+ /* Body */
+ struct _vtable_msg vtable = _lib9p_vtables[ctx->version].msgs[*ret_typ];
+ subctx.extra = ret_body + vtable.unmarshal_basesize;
+ vtable.unmarshal(&subctx, ret_body);
}
-uint32_t lib9p_marshal(struct lib9p_ctx *ctx, uint8_t typ, uint16_t msgid, void *body, uint8_t *out_bytes) {
+bool lib9p_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, uint16_t tag, void *body,
+ uint8_t *ret_bytes) {
/* Header */
- out_bytes[4] = typ;
- encode_u16le(msgid, &out_bytes[5]);
- uint32_t net_offset = 7;
+ struct _marshal_ctx subctx = {
+ .ctx = ctx,
+ .net_bytes = ret_bytes,
+ .net_offset = 7,
+ };
+ ret_bytes[4] = typ;
+ encode_u16le(tag, &ret_bytes[5]);
/* Body */
- if (versions[ctx->version]->msgs[typ].marshal(ctx, body, out_bytes, &net_offset))
- return 0;
+ struct _vtable_msg vtable = _lib9p_vtables[ctx->version].msgs[typ];
+ if (vtable.marshal(&subctx, body))
+ return true;
/* Header, again */
- encode_u32le(net_offset, out_bytes);
+ encode_u32le(subctx.net_offset, ret_bytes);
- return net_offset;
+ return false;
}