Doc update
Some checks failed
CI / rustfmt (push) Failing after 16s
CI / wasm build (push) Successful in 1m17s
CI / clippy (push) Failing after 1m27s
CI / example (push) Successful in 1m29s
CI / test (push) Successful in 1m47s
CI / duplicate code (push) Failing after 30s
CI / web client (push) Failing after 30s
CI / cargo-machete (push) Successful in 1m7s
CI / cargo-deny (push) Failing after 2m20s

This commit is contained in:
Alex Emmet 2026-06-28 04:17:42 +02:00
commit 15cc1d4c5e
3 changed files with 38 additions and 23 deletions

10
.cargo/config.toml Normal file
View file

@ -0,0 +1,10 @@
[env]
MTP_TYPE_MAPS = { value = "example-type-maps.yaml", relative = true }
# web-sys's WebTransport* bindings are behind unstable APIs, gated by this cfg.
# Scoped to the wasm32 target so it applies to the wasm crate however cargo is
# invoked (e.g. `cargo build -p mtp-wasm --target wasm32-unknown-unknown` from
# the workspace root). Cargo only reads .cargo/config.toml from the invocation
# dir and its ancestors, so the wasm crate's own config isn't seen from here.
[target.wasm32-unknown-unknown]
rustflags = ["--cfg=web_sys_unstable_apis"]

View file

@ -24,11 +24,12 @@ let config = ClientConfig::new("https://host.example.com:4433")
.with_client_id(0); .with_client_id(0);
``` ```
| Field | Type | Description | | Field | Type | Description |
|--------------|--------------------|-----------------------------------------------------| |---------------|--------------------|-----------------------------------------------------|
| `url` | `String` | `https://host:port` address of the MTP host | | `url` | `String` | `https://host:port` address of the MTP host |
| `tls` | `ClientTlsConfig` | `SystemRoots` or `PinnedPem(pem_bytes)` | | `tls` | `ClientTlsConfig` | `SystemRoots` or `PinnedPem(pem_bytes)` |
| `client_id` | `u64` | Client identifier (ignored during `auth_register`) | | `client_id` | `u64` | Client identifier (ignored during `auth_register`) |
| `auth_timeout` | `Duration` (crypto) | Authentication handshake timeout (default 30s) |
### TLS Certificate Handling ### TLS Certificate Handling

View file

@ -29,13 +29,15 @@ let config = HostConfig::new(
) )
.with_authentication( .with_authentication(
/* Keyring */, /* Keyring */,
|client_id: u64| -> Option<PublicKeyBundle> { |client_id: u64| {
CLIENT_DB.lock().unwrap().get(&client_id).cloned() let db = CLIENT_DB.clone();
Box::pin(async move { db.lock().unwrap().get(&client_id).cloned() })
}, },
|bundle: PublicKeyBundle| -> u64 { |bundle: PublicKeyBundle| {
let mut db = CLIENT_DB.lock().unwrap();
let id = next_id(); let id = next_id();
CLIENT_DB.lock().unwrap().insert(id, bundle); db.insert(id, bundle);
id Box::pin(async move { id })
}, },
); );
``` ```
@ -48,8 +50,8 @@ let config = HostConfig::new(
| `tls_key` | `Vec<u8>` | PEM-encoded TLS private key | | `tls_key` | `Vec<u8>` | PEM-encoded TLS private key |
| `require_authentication` | `bool` (crypto) | Enable login/register handshake | | `require_authentication` | `bool` (crypto) | Enable login/register handshake |
| `host_keyring` | `Keyring` (crypto) | Host's signing and KEM keys | | `host_keyring` | `Keyring` (crypto) | Host's signing and KEM keys |
| `get_existing_user` | `Fn(u64) -> Option<PublicKeyBundle> + Send + Sync` (crypto) | Lookup callback for login | | `get_existing_user` | `Fn(u64) -> Pin<Box<dyn Future<Output = Option<PublicKeyBundle>> + Send>> + Send + Sync` (crypto) | Async lookup callback for login |
| `complete_register` | `Fn(PublicKeyBundle) -> u64 + Send + Sync` (crypto) | Registration callback, returns new client ID | | `complete_register` | `Fn(PublicKeyBundle) -> Pin<Box<dyn Future<Output = u64> + Send>> + Send + Sync` (crypto) | Async registration callback, returns new client ID |
### TLS ### TLS
@ -262,8 +264,9 @@ verification. Must return `Some(PublicKeyBundle)` if the client ID is known,
or `None` to reject. or `None` to reject.
```rust ```rust
let get_existing_user = |id: u64| -> Option<PublicKeyBundle> { let get_existing_user = |id: u64| {
db.lock().unwrap().get(&id).cloned() let db = db.clone();
Box::pin(async move { db.lock().unwrap().get(&id).cloned() })
}; };
``` ```
@ -274,18 +277,19 @@ assign a client ID. The returned `u64` becomes the client's permanent
identifier. identifier.
```rust ```rust
let complete_register = |bundle: PublicKeyBundle| -> u64 { let complete_register = |bundle: PublicKeyBundle| {
let mut db = db.lock().unwrap(); let db = db.clone();
let id = next_id; let id = next_id.fetch_add(1, Ordering::SeqCst);
next_id += 1; Box::pin(async move {
db.insert(id, bundle); db.lock().unwrap().insert(id, bundle);
id id
})
}; };
``` ```
Both callbacks are called from within `accept()` and must be `Send + Sync`. They are Both callbacks are called from within `accept()` and must be `Send + Sync`. They
invoked synchronously, so avoid long-running operations (or use `spawn_blocking` are `async` (returning `Pin<Box<dyn Future<...>>`) and are `.await`ed by the
if needed, though the callbacks are `Fn`, not `AsyncFn`). host, so they can perform I/O or other async work as needed.
## Host Key Generation ## Host Key Generation