summaryrefslogtreecommitdiff
path: root/9p/internal.h
blob: 1bc0e92d91ebd63844804f7096f7af11a9136e8d (plain)
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
/* 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 <stdint.h>
#include <stdbool.h>

#include "9p/defs.h"

/* C language *****************************************************************/

#define UNUSED(name) /* name __attribute__ ((unused)) */

/* 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_without_nul(uint8_t *str, size_t len) {
	uint8_t mask;
	uint8_t chlen;
	for (size_t pos = 0; pos < len;) {
		if      ((str[pos] & 0b10000000) == 0b00000000) { mask = 0b01111111; chlen = 1; }
		else if ((str[pos] & 0b11100000) == 0b11000000) { mask = 0b00011111; chlen = 2; }
		else if ((str[pos] & 0b11110000) == 0b11100000) { mask = 0b00001111; chlen = 3; }
		else if ((str[pos] & 0b11111000) == 0b11110000) { mask = 0b00000111; chlen = 4; }
		else return false;
		if (pos + chlen > len || (str[pos] & mask) == 0) return false;
		switch (chlen) {
		case 4: if ((str[pos+3] & 0b11000000) != 0b10000000) return false; /* fallthrough */
		case 3: if ((str[pos+2] & 0b11000000) != 0b10000000) return false; /* fallthrough */
		case 2: if ((str[pos+1] & 0b11000000) != 0b10000000) return false; /* fallthrough */
		}
		pos += chlen;
	}
	return 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_ */