# 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.