mtp/docs/PIPES.md
Alex Emmet f3b6393849
Some checks failed
CI / checks (push) Failing after 4m5s
General Upgrade, NEW: WebServers, Better Docs
2026-07-18 03:47:19 +02:00

81 lines
4 KiB
Markdown

# MTP Pipes
Pipes are unidirectional QUIC streams for raw bytes. The creator sends a `PipeRequest` communication value, the peer accepts or rejects it, and the stream then carries bytes without an MTP frame around every write.
The creator owns the writer. The accepting peer owns the reader. A writer finishes with a stream FIN or aborts with a stream reset. A reader returns EOF after FIN and reports a connection or stream error when the peer closes unexpectedly.
## Opening a Pipe
The creator calls `create_pipe` or the corresponding SDK `createPipe` method with a description. MTP assigns a pipe ID and sends a `PipeRequest` frame. The creator receives a handle, not an active writer, because the peer must decide whether to accept the request.
The request description is application metadata. It does not grant access to the stream, authenticate the creator, or negotiate an application protocol.
Use the authenticated MTP connection and the host's admission policy when a pipe carries sensitive data.
## Accepting or Rejecting a Pipe
The receiving side reads pipe requests through `receive_pipe`, the host dispatcher, or the browser pipe callback. It calls `accept` to obtain a reader or `deny` to reject the request. A rejected request completes the creator's handle with `Rejected` and no raw byte stream becomes available.
With native pipes enabled, do not read the underlying `receiver` directly.
Normal messages and pipe requests share the transport and must pass through the connection facade so a dispatcher does not deliver one event to the wrong consumer.
## Closing a Pipe
The creator closes a successful pipe with `PipeWriter::finish` or the browser writer's `close`; this sends a QUIC FIN and lets the reader observe EOF. Use `abort` when the peer should discard the stream immediately; this resets the stream and the reader receives an error instead of a clean EOF. Dropping the connection closes all active pipes.
The accepting side closes its reader by consuming it or dropping it. A reader does not send an application-level acknowledgement for EOF. If the application needs completion metadata, send an ordinary MTP message before finishing the pipe.
## Pipe Errors
| Error | Meaning |
| --- | --- |
| `Rejected` | The peer denied the request. |
| `HandshakeTimeout` | The peer did not complete the pipe handshake in time. |
| `StreamClosed` | The pipe stream ended unexpectedly. |
| `IoError` | The underlying byte stream returned an I/O error. |
| `ConnectionClosed` | The MTP connection closed while the pipe was active. |
Native applications use the pipe APIs on `MTPConnection`; browser applications use the SDK methods in [WASM Client](WASM-CLIENT.md#pipes). With native pipes enabled, normal messages and pipe requests must be read through the connection facade so the dispatcher can route each event to the correct queue.
## Native File Upload and Processing
The creator streams a file in chunks. The accepting side processes each chunk without buffering the complete file:
```rust
// Client
use tokio::io::AsyncWriteExt;
let handle = conn.create_pipe("file-upload").await?;
if let Some(mut writer) = handle.wait().await? {
let mut file = tokio::fs::File::open("input.bin").await?;
tokio::io::copy(&mut file, &mut writer).await?;
writer.finish().await?;
}
```
```rust
// Host
use tokio::io::AsyncReadExt;
while let Ok(request) = conn.receive_pipe().await {
if request.description() != "file-upload" {
request.deny().await?;
continue;
}
let mut reader = request.accept().await?;
let mut hasher = sha2::Sha256::new();
let mut buffer = [0u8; 64 * 1024];
loop {
let count = reader.read(&mut buffer).await?;
if count == 0 {
break;
}
hasher.update(&buffer[..count]);
process_chunk(&buffer[..count]).await?;
}
let digest = hasher.finalize();
println!("processed upload with digest {digest:x}");
}
```
Send completion metadata as an ordinary MTP message after the reader observes EOF. A stream FIN means the writer finished; it does not authenticate file contents or provide a digest.