darkbio_wire/protocol/mod.rs
1// wire-rs: encrypted protocol between Ark and host
2// Copyright 2026 Dark Bio AG. All rights reserved.
3
4//! Bidirectional requests over the transport, with pipelining and explicit sessions.
5//!
6//! A reader receives messages from each connection. Each session also has a writer
7//! that sends queued messages and a deadline worker that times out operations.
8//! Incoming requests and unread responses stay encoded until `recv()` or `wait()`.
9//! Invalid payloads close their original session when decoded.
10//!
11//! Each session limits accepted peer requests and buffered incoming bytes. Set
12//! both with [`Session::set_inbound_limits`] or [`Server::set_inbound_limits`].
13//! Exceeding a limit closes the session. The reader never waits for the application
14//! to make room. These limits are local; no flow control is negotiated with the
15//! peer. The outgoing queue has no capacity limit.
16//!
17//! The application opens a [`crate::transport::Stream`]; this layer constructs and
18//! owns its transport. [`connect`] establishes one client session. [`Server`] owns
19//! a persistent stream and accepts successive server sessions. Each [`Session`]
20//! owns its receive queue and closes when dropped. Its [`Requester`] and
21//! [`Responder`] handles always target that session, even after it closes and
22//! another session connects.
23//! Both sides use the same concrete handle types and [`Message`] enum; the role and
24//! wire envelope direction are internal details. Callers select response types when
25//! waiting on [`Promise<Message>`].
26//!
27//! Requests and replies return promises without waiting for I/O. Their deadlines
28//! include time in the outgoing queue; `wait()` does not restart the timeout.
29//! Transport write timeouts are independent: a request can still reach the peer
30//! after its promise expires. The reader and writer run independently of the
31//! application, but the application must keep receiving and answering requests
32//! while its own requests wait for replies. All waiting is blocking; no async
33//! runtime is required. Every request expects a reply, including notifications.
34//!
35//! Closing a session fails its pending promises and discards queued messages.
36//! Completed promises keep their results. A write already in progress may still
37//! reach the peer.
38
39mod closer;
40mod envelope;
41mod error;
42mod message;
43mod operation;
44mod promise;
45mod requester;
46mod responder;
47mod server;
48mod session;
49mod worker;
50
51#[cfg(any(test, feature = "fuzz"))]
52#[cfg_attr(coverage_nightly, coverage(off))]
53#[doc(hidden)]
54pub mod mock;
55
56pub use closer::Closer;
57pub use error::Error;
58pub use generated::Error as RemoteError;
59pub use generated::*;
60pub use message::Message;
61pub use promise::Promise;
62pub use requester::Requester;
63pub use responder::Responder;
64pub use server::Server;
65pub use session::{Session, connect};
66
67use std::time::Duration;
68
69/// Default timeout for sending an automatic `UNANSWERED` reply. Starts when the
70/// responder is dropped and includes time in the outgoing queue. Configure it
71/// with [`Session::set_abandonment_timeout`] or [`Server::set_abandonment_timeout`].
72/// Transport write timeouts are independent.
73pub const DEFAULT_ABANDONMENT_TIMEOUT: Duration = Duration::from_secs(5);
74
75/// Default limit of 1,024 accepted peer requests per session. A request counts
76/// while queued, held by a responder, or waiting to send its reply. The slot is
77/// freed when the writer takes the reply or the reply is discarded.
78/// Configure it with [`Session::set_inbound_limits`] or
79/// [`Server::set_inbound_limits`]. Zero admits no peer requests.
80pub const DEFAULT_MAX_INBOUND_REQUESTS: usize = 1024;
81
82/// Default limit of 16 MiB for queued requests and unread response promises.
83/// Counts their full encoded envelopes. Taking or dropping an envelope reduces
84/// the byte count.
85/// Decoded application data, outgoing messages and transport buffers are excluded.
86/// Configure it with [`Session::set_inbound_limits`] or
87/// [`Server::set_inbound_limits`]. Zero permits no retained envelope bytes.
88pub const DEFAULT_MAX_INBOUND_BYTES: usize = 16 * 1024 * 1024;
89
90/// Generated protobuf bindings, excluded from checks for handwritten code.
91#[allow(clippy::all)]
92#[allow(rustdoc::broken_intra_doc_links)]
93mod generated {
94 include!(concat!(env!("OUT_DIR"), "/darkbio.wire.rs"));
95}