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