This commit is contained in:
parent
6e5c985719
commit
1b796d0ce7
46 changed files with 1755 additions and 691 deletions
|
|
@ -40,9 +40,10 @@ Both clients exchange the same MTP frames with a host.
|
|||
|
||||
The middle row is shared protocol machinery. The type map determines numeric IDs, the codec serializes values, and transport framing places each serialized frame on a QUIC stream. This is why a type-map change must be compiled into both peers before the new message can be exchanged.
|
||||
|
||||
The bottom row shows the two server entry points. `MTPHost` owns a native QUIC endpoint. `MTPWebServer` owns an HTTP/3 endpoint that also accepts WebTransport MTP sessions. They cannot bind the same IP and port. `mtp-crypto` is an optional cross-cutting layer used by authenticated native connections and browser E2EE;
|
||||
TLS remains the transport security layer in both paths.
|
||||
The bottom row shows the two server entry points. `MTPHost` is a native QUIC endpoint for native MTP clients. `MTPWebServer` is an HTTP/3 server that reuses `HostConfig` and provides the same `accept()`-based MTP session API, adding web routing and WebTransport support for browser clients. Because they rely on different QUIC ALPN protocols (native MTP vs. `h3`), they must bind to different IP/port pairs and should not be enabled as Cargo features in the same binary. Choose `MTPHost` when you only serve native clients; choose `MTPWebServer` when you need HTTP/3 routes or browser-based MTP clients.
|
||||
|
||||
`mtp-host` performs version negotiation and native authentication before returning an `MTPConnection`. `mtp-webserver` routes HTTP/3 requests and WebTransport sessions through its endpoint. It currently accepts only unauthenticated WebTransport MTP sessions.
|
||||
`mtp-crypto` is an optional cross-cutting layer used by authenticated native connections, WebTransport connections, and browser E2EE; TLS remains the transport security layer in both paths.
|
||||
|
||||
The [native client](NATIVE-CLIENT.md), [WASM client](WASM-CLIENT.md), [native host](NATIVE-HOST.md), and [web server](NATIVE-HOST-WEB-SERVER.md) guides cover the public APIs for each boundary.
|
||||
`mtp-host` performs version negotiation and native authentication before returning an `MTPConnection`. `mtp-webserver` routes HTTP/3 requests and WebTransport sessions through its endpoint. WebTransport MTP sessions support the same optional cryptographic authentication as native hosts when the `crypto` feature is enabled.
|
||||
|
||||
The [native client](NATIVE-CLIENT.md), [WASM client](WASM-CLIENT.md), [native host](NATIVE-HOST.md), and [web server](NATIVE-HOST-WEB-SERVER.md) guides cover the public APIs for each boundary. The web server guide should be read as the host API for browser-facing deployments; it accepts the same `HostConfig` and authentication callbacks as the native host.
|
||||
|
|
|
|||
|
|
@ -2,15 +2,17 @@
|
|||
|
||||
Native clients and hosts share the same connection shape after the opening handshake. The client creates the connection; the host receives it from `accept()`.
|
||||
|
||||
| Member | Native client | Native host |
|
||||
| --- | --- | --- |
|
||||
| `version` | Compiled client version accepted by the host | Version selected by the registry |
|
||||
| `sender` | Sends `CommunicationValue` frames | Sends `CommunicationValue` frames |
|
||||
| `receiver` | Receives application frames | Receives application frames |
|
||||
| `description` | Optional label sent during setup | Optional label received from the client |
|
||||
| `client_id` | Confirmed or assigned ID with `crypto` | Authenticated or guest client ID with `crypto` |
|
||||
| `auth_state` | Authentication result with `crypto` | Authentication result with `crypto` |
|
||||
| Member | Native client | Native host | Web host (`WebMTPConnection`) |
|
||||
| --- | --- | --- | --- |
|
||||
| `version` | Compiled client version accepted by the host | Version selected by the registry | Version selected by the registry |
|
||||
| `sender` | Sends `CommunicationValue` frames | Sends `CommunicationValue` frames | Sends `CommunicationValue` frames |
|
||||
| `receiver` | Receives application frames | Receives application frames | Receives application frames |
|
||||
| `description` | Optional label sent during setup | Optional label received from the client | Optional label received from the client |
|
||||
| `client_id` | Confirmed or assigned ID with `crypto` | Authenticated or guest client ID with `crypto` | Authenticated or guest client ID with `crypto` |
|
||||
| `auth_state` | Authentication result with `crypto` | Authentication result with `crypto` | Authentication result with `crypto` |
|
||||
| `request_path` | — | — | WebTransport CONNECT path (e.g. `/mtp`) |
|
||||
|
||||
`WebMTPConnection`, returned by `MTPWebServer::accept()`, exposes the same members as the native host connection plus `request_path`, which contains the HTTP/3 path used for the WebTransport extended CONNECT request.
|
||||
The host connection also exposes a version-scoped `codec` and, for an authenticated client, its `client_public_key`. The native client connection also exposes these methods:
|
||||
|
||||
| Method | Behavior |
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@
|
|||
WebTransport sessions are returned by `accept()` for application messages.
|
||||
`MTPWebServer` and `MTPHost` cannot bind the same IP and port.
|
||||
|
||||
The repository's combined server example registers `/` on `MTPWebServer` and
|
||||
returns `OK` while the process is running. The route is served over HTTP/3 at
|
||||
`https://localhost:8080/` on the same QUIC endpoint as WebTransport MTP sessions.
|
||||
|
||||
## WebServerConfig
|
||||
|
||||
| Builder | Default | Purpose |
|
||||
|
|
@ -63,25 +67,46 @@ let web = WebServerConfig::new()
|
|||
```rust
|
||||
use mtp::{host::HostConfig, webserver::MTPWebServer};
|
||||
|
||||
let host = HostConfig::new(
|
||||
let host_config = HostConfig::new(
|
||||
"0.0.0.0".parse()?,
|
||||
4433,
|
||||
std::fs::read("cert.pem")?,
|
||||
std::fs::read("key.pem")?,
|
||||
);
|
||||
let mut server = MTPWebServer::new(host, web).await?;
|
||||
let mut server = MTPWebServer::new(host_config, web).await?;
|
||||
|
||||
while let Some(connection) = server.accept().await? {
|
||||
// connection: WebMTPConnection
|
||||
while let Ok(message) = connection.receiver.receive().await {
|
||||
while let Ok(message) = connection.receive().await {
|
||||
println!("received MTP message {}", message.get_id());
|
||||
}
|
||||
}
|
||||
```
|
||||
> `MTPWebServer::new` consumes a `HostConfig` (not an `MTPHost` instance). It creates its own QUIC endpoint and does not share a port with a running `MTPHost`.
|
||||
|
||||
`server.accept()` returns `Option<WebMTPConnection>` for each WebTransport session. HTTP/3 routes do not surface through `accept()` because the server dispatches them internally. `WebMTPConnection` retains the negotiated version, codec, request path, description, sender, and receiver used by native MTP connections.
|
||||
|
||||
WebTransport sessions are unauthenticated. With the `crypto` feature enabled, construction rejects any `AuthenticationPolicy` other than `Unauthenticated`. The connection has `AuthState::Unauthenticated` and a random 48-bit client ID when crypto fields are compiled in; `guest_id_generator` is not used by this adapter.
|
||||
### Authentication
|
||||
|
||||
`MTPWebServer` does not impose its own authentication policy. It respects the `AuthenticationPolicy` set on the supplied `HostConfig`:
|
||||
|
||||
| Policy | Behavior |
|
||||
|--------|----------|
|
||||
| `Unauthenticated` (default) | No authentication handshake is performed. The connection has `AuthState::Unauthenticated` and a random 48-bit client ID. `guest_id_generator` is not used by this adapter. |
|
||||
| `AllowAuthentication` | The server accepts the first message. If it is an `Identification` or `Register` message, a full challenge-response handshake is performed. If it is an ordinary opening message, the connection remains unauthenticated. |
|
||||
| `ForceAuthentication` | The server requires a valid `Identification` or `Register` message as the first frame and performs the challenge-response handshake. Any other opening message is rejected. |
|
||||
|
||||
When authentication is required or allowed and the client presents credentials, the server performs the same Ed25519/ML-DSA challenge-response handshake used by native MTP host connections:
|
||||
|
||||
1. The client sends `Identification` (with a client ID) or `Register` (with a public-key bundle).
|
||||
2. The server looks up or accepts the client's public keys, generates a random 128-bit server nonce, and signs a challenge payload with its host keyring.
|
||||
3. The client responds with a proof signed by its own keys.
|
||||
4. The server verifies the proof, assigns the client ID, and sends a final signed response.
|
||||
|
||||
On success, the connection has `AuthState::Authenticated`, the assigned `client_id`, and `client_public_key` populated. On failure, `accept()` returns `AcceptError::AuthenticationFailed` (or `AcceptError::AuthenticationTimedOut` if the handshake exceeds `host_config.auth_timeout`).
|
||||
|
||||
`MTPWebServer::new` returns `CommunicationError` for certificate parsing, certificate loading, and bind failures. It does **not** reject `HostConfig` based on `AuthenticationPolicy`; any policy is accepted at construction time.
|
||||
|
||||
|
||||
## Errors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
The native host is a Rust library (`mtp-host`) that runs a QUIC server, accepts MTP client connections, negotiates protocol versions, and optionally performs a mutual-authentication handshake (login/register) using Ed25519 and ML-DSA-65 signatures.
|
||||
|
||||
> **Note:** `MTPHost` serves native MTP clients over raw QUIC. If you need to serve HTTP/3 routes on the same endpoint, use [`MTPWebServer`](NATIVE-HOST-WEB-SERVER.md) instead. `MTPWebServer` accepts the same `HostConfig` but binds an HTTP/3 endpoint rather than a native QUIC endpoint.
|
||||
|
||||
## Cargo Dependency
|
||||
|
||||
Add the `mtp` umbrella crate with `host`. Add `crypto` for authenticated connections and `pipes` for raw streams. The feature table is in the [README](../README.md).
|
||||
|
|
|
|||
Loading…
Reference in a new issue