Documenting the protocols, structures and concepts used by Hyperscape.
Striven
2 days ago 7253dbe611fa15af474c72811d6e4289c985c674
04_rendezvous/04_prudp_protocol.md
@@ -0,0 +1,137 @@
# RendezVous: PRUDP Protocol
PRUDP probably stands for **P**rotected **R**eliable **U**ser **D**atagram **P**rotocol, as it is designed for adding reliability, encryption and compression to UDP. To do this, it adds [connections](#connections), [acknowledgements](#acknowledgements), [ordering](#ordering), [fragmentation](#fragmentation), [compression](#compression), [encryption](#encryption) and [checksums](#checksums).
## Packets
### Base Packet
**Every** packet, sent by both the client and the server, has the following base information:
| Name             | Description                                                                                                           | Type                                          |
|------------------|-----------------------------------------------------------------------------------------------------------------------|-----------------------------------------------|
| Source           | The [virtual stream](#connections) that the packet is being sent from.                                                | [`Stream`](#structure-stream)                 |
| Destination      | The [virtual stream](#connections) that the packet is being sent to.                                                  | [`Stream`](#structure-stream)                 |
| Type and Flags   | Type of the packet, and flags indicating how the client should treat this packet.                                     | [`Type and Flags`](#structure-type-and-flags) |
| Session ID       | Unknown.                                                                                                              | `u8`                                          |
| Packet Signature | Unknown.                                                                                                              | `u32`                                         |
| Sequence ID      | A strictly monotonically increasing integer used for [acknowledgements](#acknowledgements) and [ordering](#ordering). | `u16`                                         |
### Packet: `SYN`
This packet establishes a connection with the server.
#### Client->Server Payload
| Name                 | Description | Type  |
|----------------------|-------------|-------|
| Connection Signature | Unknown.    | `u32` |
#### Server->Client Payload
| Name                 | Description | Type  |
|----------------------|-------------|-------|
| Connection Signature | Unknown.    | `u32` |
### Packet: `CONNECT`
This stage is used to execute a Diffie-Hellman key exchange, and then derive a shared secret key.
The key exchange operation is $S = d \times Q$, where $S$ is the resulting key, $d$ is the server's private key, and $Q$ is the client's public key. The resulting `y` co-ordinate of this exchange is discarded.
The shared key, used for `DATA` packet encryption and decryption, is derived using the first `16` bytes of a `SHA1` hash on the Diffie-Hellman exchange result.
The server may also use this stage to affirm the client's [connection signature](#connections).
#### Client->Server Payload
| Name                 | Description                | Type                                                 |
|----------------------|----------------------------|------------------------------------------------------|
| Connection Signature | Unknown.                   | `u32`                                                |
| Public Key           | The client's _public key_. | [`Public Key`](03_structure.md#structure-public-key) |
#### Server->Client Payload
| Name                 | Description                                                                                                                                                                                                                                               | Type                                                 |
|----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------|
| Connection Signature | Unknown.                                                                                                                                                                                                                                                  | `u32`                                                |
| Public Key Signature | The server's _public key_ signed by the server's _certification private key_.                                                                                                                                                                             | [`Buffer`](03_structure.md#structure-buffer)         |
| Public Key           | The server's _public key_.                                                                                                                                                                                                                                | [`Public Key`](03_structure.md#structure-public-key) |
| Tag                  | A HMAC-SHA256 signature on both the [client's key](03_structure.md#structure-public-key) and the [server's key]([client's key](03_structure.md#structure-public-key)) concatenated, signed using the Diffie-Hellman exchange result (NOT the shared key). | [`Buffer`](03_structure.md#structure-buffer)         |
### Packet: `DATA`
The whole data is _first_ fragmented, _then_ compressed, _then_ encrypted.
This means that the data in this packet, if fragmented, should be [decrypted first](#encryption), then [de-compressed](#compression) (if applicable), and then re-assembled.
The **compressed payload** (before encryption) is prefixed with a single byte indicating the compression ratio. `0` means that the remaining data is **not** compressed. The client appears to only ever use `0x02` for this byte, however.
The **fragmented payload** (before compression) is suffixed with the 2-byte **sequence id** of the data packet being sent.
#### Client->Server, Server->Client Payload
| Name        | Description                                                                                                                                                     | Type  |
|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|-------|
| Fragment ID | Used to re-assemble [fragmented](#fragmentation) data packets, starting from `1` (if multiple fragments exist), and ending in `0` to indicate a final fragment. | `u32` |
| ...         | Encrypted and compressed data                                                                                                                                   | `any` |
### Packet: `DISCONNECT`
### Packet: `PING`
## Connections
## Acknowledgements
## Ordering
## Compression
## Encryption
## Fragmentation
## Checksums
## Packet Format
## Structures
### Structure: `Public Key`
An **uncompressed** `SEC1` formatted key, **without** the preceeding compression tag (`0x04`).
### Structure: `Stream`
A packed `u8` containing
| Name | Description                                       | Type                               |
|------|---------------------------------------------------|------------------------------------|
| Port | The [virtual port](#connections) for this stream. | `u4`                               |
| Port | The type of stream that the connection is using.  | [`Stream Type`](#enum-stream-type) |
### Structure: `Type and Flags`
A packed `u8` containing
| Name      | Description                                                                                                                                                                                                          | Type                               |
|-----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------|
| Type      | The type of packet that is being sent.                                                                                                                                                                               | [`Packet Type`](#enum-packet-type) |
| Ack       | This packet is an [acknowledgement](#acknowledgements) packet for a reliable packet sent by the recipient.                                                                                                           | `bool`                             |
| Reliable  | This packet **must** be acknowledged by the recipient, or it will be re-sent.                                                                                                                                        | `bool`                             |
| Need Ack  | The sender is expecting an acknowledgement for this packet.                                                                                                                                                          | `bool`                             |
| Has Size  | The packet contains a `u16` size following the packet header (or, for [`SYN`](#packet-syn) and [`CONNECT`](#packet-connect), after the connection signature, and for [`DATA`](#packet-data), after the fragment ID). | `bool`                             |
| Multi Ack | Unknown, doesn't appear to be supported, but if a packet flagged with `Need Ack` has this flag, the recipient should send an `Ack` with this flag set too.                                                           | `bool`                             |
### Enum: `Stream Type`
A `u4` containing these values:
| Name                  | Value |
|-----------------------|-------|
| `RV Authentication` | `2`   |
| `RV Secure` | `3`   |
| `Sandbox Management` | `4`   |
| `NAT` | `5`   |
| `Session Discovery` | `6`   |
| `Nat Echo` | `7`   |
> [!IMPORTANT]
> Hyperscape appears to exclusively use the `RV Secure` (`3`) type.
### Enum: `Packet Type`
A `u3` containing these values:
| Name                  | Value |
|-----------------------|-------|
| [`SYN`](#packet-syn) | `0`   |
| [`CONNECT`](#packet-connect) | `1`   |
| [`DATA`](#packet-data) | `2`   |
| [`DISCONNECT`](#packet-disconnect) | `3`   |
| [`PING`](#packet-ping) | `4`   |
| [`USER`](#packet-user) | `6`   |