// The connection ports. A connection engine reads and writes through `Conn`,
// dials through `Dialer` and runs its reader and its watcher of the peer
// through `Coordination`, so the same engine runs over sockets, TLS, a
// CONNECT tunnel or an in-memory pair. CONTRACT.md (Connections and
// coordination) states what each side may rely on.
///|
/// An owned, full-duplex byte connection.
///
/// One read and one write may run at the same time. `rt.Conn` has no
/// write-half shutdown, because the runtime offers none for sockets or TLS.
pub(open) trait Conn {
/// Reads a nonempty chunk of at most `max_len` bytes, or `None` at EOF.
/// EOF is permanent and ends only the read half: writes may continue.
/// A cancelled read finishes its cleanup before the next read begins.
async fn read(Self, max_len~ : Int32) -> Bytes? raise @http.TransportError
/// Writes all of `bytes`, or raises. A write after `close` raises.
async fn write(Self, Bytes) -> Unit raise @http.TransportError
/// Closes both halves and wakes pending operations. Idempotent.
fn close(Self) -> Unit
}
///|
/// Opens connections and upgrades them to TLS, without naming a runtime or
/// TLS type.
pub(open) trait Dialer {
/// Connects to `host` on `port`.
async fn connect(Self, host~ : String, port~ : Int32) -> &Conn raise @http.TransportError
/// Starts a TLS client session for `host` over `conn`, which may itself be
/// a tunnel. A successful upgrade owns `conn`; after a failed one the
/// caller still owns `conn` and closes it.
async fn start_tls(Self, &Conn, host~ : String) -> &Conn raise @http.TransportError
}
///|
/// A sticky one-shot notification.
pub(open) trait Signal {
/// Waits until `notify` has been called, returning at once if it already
/// was. A cancelled waiter unregisters before it unwinds.
async fn wait(Self) -> Unit noraise
/// Wakes every waiter, now and later. Repeated calls are harmless.
fn notify(Self) -> Unit
}
///|
/// The structured concurrency a connection engine needs.
pub(open) trait Coordination {
/// A new signal on this coordination's scheduler.
fn signal(Self) -> &Signal
/// Runs `primary` and `monitor` as children and returns when both have
/// finished their cleanup. The monitor completing normally lets `primary`
/// continue; the monitor failing cancels `primary` and raises the
/// monitor's error; `primary` finishing (normally or not) cancels the
/// monitor. The first outcome delivered wins. Cancelling the caller
/// cancels both and propagates once both have unwound.
async fn supervise(
Self,
primary~ : async () -> Unit raise @http.TransportError,
monitor~ : async () -> Unit raise @http.TransportError,
) -> Unit raise @http.TransportError
}