diff options
Diffstat (limited to 'lib9p/internal.h')
-rw-r--r-- | lib9p/internal.h | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/lib9p/internal.h b/lib9p/internal.h new file mode 100644 index 0000000..61977d4 --- /dev/null +++ b/lib9p/internal.h @@ -0,0 +1,139 @@ +/* 9p/internal.h - TODO + * + * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-Licence-Identifier: AGPL-3.0-or-later + */ + +#ifndef _9P_INTERNAL_H_ +#define _9P_INTERNAL_H_ + +#include <assert.h> +#include <stdint.h> +#include <stdbool.h> + +#include "9p/defs.h" + +#define USE_CONFIG_9P +#include "config.h" +static_assert(CONFIG_9P_MAX_ERR_SIZE <= UINT16_MAX); + +/* C language *****************************************************************/ + +#define UNUSED(name) /* name __attribute__ ((unused)) */ + +/* types **********************************************************************/ + +struct p9_ctx { + enum p9_version version; + uint32_t max_msg_size; + uint32_t Rerror_overhead; + + uint32_t err_num; + char err_msg[CONFIG_9P_MAX_ERR_SIZE]; +}; + +static inline enum p9_version p9_ctx_version(p9_ctx *ctx) { + assert(ctx); + return ctx->version; +} + +/* vtables ********************************************************************/ + +typedef bool (*_checksize_fn_t)(uint32_t net_len, uint8_t *net_bytes, uint32_t *mut_net_offset, size_t *mut_host_extra); +typedef bool (*_unmarshal_fn_t)(uint8_t *net_bytes, uint32_t *mut_net_offset, void **mut_host_extra, void *out); +typedef bool (*_marshal_fn_t)(struct p9_ctx *ctx, void *val, uint8_t *out_net_bytes, uint32_t *mut_net_offset); + +struct msg_vtable { + size_t unmarshal_basesize; + _checksize_fn_t unmarshal_extrasize; + _unmarshal_fn_t unmarshal; + _marshal_fn_t marshal; +}; + +struct version { + struct msg_vtable msgs[0xFF]; +}; + +extern struct version version_9P2000; +/*extern struct version version_9P2000u; */ + +/* unmarshal utilities ********************************************************/ + +static inline uint8_t decode_u8le(uint8_t *in) { + return in[0]; +} +static inline uint16_t decode_u16le(uint8_t *in) { + return (((uint16_t)(in[0])) << 0) + | (((uint16_t)(in[1])) << 8) + ; +} +static inline uint32_t decode_u32le(uint8_t *in) { + return (((uint32_t)(in[0])) << 0) + | (((uint32_t)(in[1])) << 8) + | (((uint32_t)(in[2])) << 16) + | (((uint32_t)(in[3])) << 24) + ; +} +static inline uint64_t decode_u64le(uint8_t *in) { + return (((uint64_t)(in[0])) << 0) + | (((uint64_t)(in[1])) << 8) + | (((uint64_t)(in[2])) << 16) + | (((uint64_t)(in[3])) << 24) + | (((uint64_t)(in[4])) << 32) + | (((uint64_t)(in[5])) << 40) + | (((uint64_t)(in[6])) << 48) + | (((uint64_t)(in[7])) << 56) + ; +} + +static inline bool _is_valid_utf8(uint8_t *str, size_t len, bool forbid_nul) { + uint32_t ch; + uint8_t chlen; + assert(str); + for (size_t pos = 0; pos < len;) { + if ((str[pos] & 0b10000000) == 0b00000000) { ch = str[pos] & 0b01111111; chlen = 1; } + else if ((str[pos] & 0b11100000) == 0b11000000) { ch = str[pos] & 0b00011111; chlen = 2; } + else if ((str[pos] & 0b11110000) == 0b11100000) { ch = str[pos] & 0b00001111; chlen = 3; } + else if ((str[pos] & 0b11111000) == 0b11110000) { ch = str[pos] & 0b00000111; chlen = 4; } + else return false; + if ((ch == 0 && (chlen != 1 || forbid_nul)) || pos + chlen > len) return false; + for (uint8_t i = 1; i < chlen; i++) { + if ((str[pos+i] & 0b11000000) != 0b10000000) return false; + ch = (ch << 6) | (str[pos+i] & 0b00111111); + } + if (ch > 0x10FFFF) return false; + pos += chlen; + } + return true; +} + +#define is_valid_utf8(str, len) _is_valid_utf8(str, len, false) +#define is_valid_utf8_without_nul(str, len) _is_valid_utf8(str, len, true) + +/* marshal utilities **********************************************************/ + +static inline void encode_u8le(uint8_t in, uint8_t *out) { + out[0] = in; +} +static inline void encode_u16le(uint16_t in, uint8_t *out) { + out[0] = (uint8_t)((in >> 0) & 0xFF); + out[1] = (uint8_t)((in >> 8) & 0xFF); +} +static inline void encode_u32le(uint32_t in, uint8_t *out) { + out[0] = (uint8_t)((in >> 0) & 0xFF); + out[1] = (uint8_t)((in >> 8) & 0xFF); + out[2] = (uint8_t)((in >> 16) & 0xFF); + out[3] = (uint8_t)((in >> 24) & 0xFF); +} +static inline void encode_u64le(uint64_t in, uint8_t *out) { + out[0] = (uint8_t)((in >> 0) & 0xFF); + out[1] = (uint8_t)((in >> 8) & 0xFF); + out[2] = (uint8_t)((in >> 16) & 0xFF); + out[3] = (uint8_t)((in >> 24) & 0xFF); + out[4] = (uint8_t)((in >> 32) & 0xFF); + out[5] = (uint8_t)((in >> 40) & 0xFF); + out[6] = (uint8_t)((in >> 48) & 0xFF); + out[7] = (uint8_t)((in >> 56) & 0xFF); +} + +#endif /* _9P_INTERNAL_H_ */ |