summaryrefslogtreecommitdiff
path: root/lib9p/internal.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p/internal.h')
-rw-r--r--lib9p/internal.h139
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_ */