summaryrefslogtreecommitdiff
path: root/lib9p/idl/0000-README.md
blob: 84cf865853db45584a10f9abceb6c8d75e63567b (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
<!--
  lib9p/idl/0000-README.md - Overview of 9P protocol definitions

  Copyright (C) 2024-2025  Luke T. Shumaker <lukeshu@lukeshu.com>
  SPDX-License-Identifier: AGPL-3.0-or-later
  -->

# 9P protocol definitions

This directory contains several `*.9p` files, each of which describes
a 9P protocol variant.

In the 9P protocol, each message has a type, and message types come
in pairs (except "Rerror"); "T" and "R"; T-messages are
client->server requests, and R-messages are server->client responses
(the client "Transmits" T-messages and "Receives" R-messages).  The
type of a message is represented by a u8 ID; T-messages are even and
R-messages are odd.

9P messages are exchanged over a reliable bidirectional in-order octet
stream.  Messages are made up of the primitives; unsigned
little-endian integers, identified with the following single-character
mnemonics:

 - 1 = u8
 - 2 = u16le
 - 4 = u32le
 - 8 = u16le

Out of these primitives, we can make more complex types:

## User-defined types

### Numeric types

	num NUMNAME = PRIMITIVE_TYPE
		"NAME=VAL"...

Besides just being an alias for a primitive type, a numeric type may
define 0 or more named constants of that type, each wrapped in
"quotes".

### Bitfields

	bitfield BFNAME = PRIMITIVE_TYPE
		"bit NBIT=NAME"...
		"bit NBIT=reserved(NAME)"...
		"bit NBIT=num(NUMNAME)"...
		"alias NAME=VAL"...
		"mask NAME=VAL"...
		"num(NUMNAME) NAME=VAL"...

The same NBIT may not be defined multiple times.  The same NAME may
not be defined multiple times.

 - A `reserved(...)` bit indicates that the bit is named but is not
   allowed to be used.
 - `num(...)` bits embed a numeric/enumerated field within a set of
   bits.  Once several bits have been allocated to a numeric field
   with `bit NBIT=num(NUMNAME)`, constant values for that field may be
   declared with `num(NUMNAME) NAME=VAL`.  For each numeric field, a
   `mask NUMNAME=BITMASK` is automatically declared.
 - A `mask` defines a bitmask that selects several bits.
 - An `alias` defines a convenience alias for a bit or set of bits.

### Structures

	struct STRUCTNAME = "FIELDNAME[FIELDTYPE]..."

Or a special-case for structs that are messages; `msg` has the same
syntax as `struct`, but has restrictions on the STRUCTNAME and the
first 3 fields must all be declared in the same way:

	msg Tname = "size[4,val=end-&size] typ[1,val=TYP] tag[tag] REST..."

Struct fields that have numeric types (either primitives or `num`
types) can add to their type `,val=` and/or `,max=` to specify what
the exact value must be and/or what the maximum (inclusive) value is.
A field that is repeated a variable number of times be wrapped in
parenthesis and prefixed with the fieldname containing that count:
`OTHERFIELDNAME*(FIELDNAME[FIELDTYPE])`.

`,val=` and `,max` take a string of `+`/`-` tokens and values; a value
can be
 - a decimal numeric constant (eg: `107`),
 - `&fieldname` to refer to the offset of a field name in that struct,
 - the special value `end` to refer to the offset of the end of the
   struct,
 - the special value `u{8,16,32,64}_max` to refer to the constant
   value `(1<<{n})-1`, or
 - the special value `s{8,16,32,64}_max` to refer to the constant value
   `(1<<({n}-1))-1`.

## Parser

A parser for this syntax is given in `__init__.py`.  However,
`__init__.py` places the somewhat arbitrary undocumented restrictions
on fields referenced as the count of a repeated field.