1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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_ */
|