parent
d11eb04d12
commit
a6c4e56835
14 changed files with 126 additions and 63 deletions
|
|
@ -4,23 +4,28 @@ This file documents the connection and version negotiation logic.
|
|||
|
||||
## Registry
|
||||
|
||||
The `registry` module provides a multi-version `Registry` used by the host for version negotiation. Accessed through the `mtp` facade (requires the `host` feature):
|
||||
The `registry` module provides a multi-version `Registry` used by the host for
|
||||
version negotiation. Accessed through the `mtp` facade (requires the `host`
|
||||
feature). In this repository, `Registry::builtin()` is generated from
|
||||
[`example/type-maps.yaml`](../example/type-maps.yaml), which currently contains
|
||||
protocol version 3.0 only. Downstream projects can register additional versions
|
||||
in their own YAML configuration.
|
||||
|
||||
```rust
|
||||
use mtp::codec::registry::Registry;
|
||||
use mtp::codec::{Version, registry::Registry};
|
||||
|
||||
let registry = Registry::builtin(); // loads all TypeMaps from config
|
||||
let registry = Registry::builtin(); // loads all TypeMaps from the build config
|
||||
|
||||
// Check if a version is supported
|
||||
assert!(registry.supports(&Version(1, 0)));
|
||||
assert!(registry.supports(&Version(3, 0)));
|
||||
|
||||
// Find highest mutual version for a client
|
||||
let client_versions = &[Version(0, 0), Version(1, 0)];
|
||||
let client_versions = &[Version(2, 0), Version(3, 0)];
|
||||
let negotiated = registry.negotiate(client_versions);
|
||||
assert_eq!(negotiated, Some(Version(1, 0)));
|
||||
assert_eq!(negotiated, Some(Version(3, 0)));
|
||||
|
||||
// Look up a version's TypeMap
|
||||
let tm = registry.get(&Version(2, 0)).unwrap();
|
||||
let tm = registry.get(&Version(3, 0)).unwrap();
|
||||
```
|
||||
|
||||
The `Registry::builtin()` constructor uses the `TypeMap::vX_Y()` methods generated from the config.
|
||||
|
|
@ -54,9 +59,9 @@ let mut host = MTPHost::new(config).await?;
|
|||
while let Some(conn) = host.accept().await? {
|
||||
// conn.version is the negotiated version
|
||||
// conn.codec is a VersionedCodec scoped to that version
|
||||
// conn.sender / conn.receiver for raw CommunicationValue I/O
|
||||
// conn.sender / conn.receive() for application CommunicationValue I/O
|
||||
|
||||
let msg = conn.receiver.receive().await?;
|
||||
let msg = conn.receive().await?;
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -94,29 +99,31 @@ The client's `PROTOCOL_VERSION` constant is set by `protocol_version` in `type-m
|
|||
## Version Negotiation Flow
|
||||
|
||||
```
|
||||
Client (v2.0) Host (v0.0, v1.0, v2.0)
|
||||
Client (v3.0) Host (v3.0)
|
||||
| |
|
||||
| QUIC connect |
|
||||
|----------------------->|
|
||||
| |
|
||||
| CommValue{ Ident. } |
|
||||
| Version -> "2.0" |
|
||||
| Version -> "3.0" |
|
||||
| Id -> 8765 |
|
||||
| (unsigned hello; auth |
|
||||
| challenge follows) |
|
||||
|----------------------->|
|
||||
| | registry.negotiate(&[Version(2,0)])
|
||||
| | -> Some(Version(2,0))
|
||||
| | registry.negotiate(&[Version(3,0)])
|
||||
| | -> Some(Version(3,0))
|
||||
| |
|
||||
| Response | selected v2.0 TypeMap
|
||||
| Response | selected v3.0 TypeMap
|
||||
|<-----------------------|
|
||||
| Status, version |
|
||||
| |
|
||||
| subsequent messages |
|
||||
| use v2.0 TypeMap |
|
||||
| use v3.0 TypeMap |
|
||||
```
|
||||
|
||||
If the client sends an unsupported version (e.g. v3.0 when the host only knows up to v2.0), `negotiate` returns `None` and the connection is closed.
|
||||
If the client sends an unsupported version (for example, v2.0 to the current
|
||||
repository builtin host), `negotiate` returns `None` and the connection is
|
||||
closed.
|
||||
|
||||
## Protocol Ping and Pong
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue