A TLS connection over any Io.Reader / Io.Writer pair (a TCP stream's, a pipe's, an Http
Link's). The handshake is a plain blocking call on the calling fiber: it waits through the Io
calls under it, so Io.with_deadline limits it and Io.cancel ends it. After it, the stream is
read and written like any other, through reader_of and writer_of, or directly with read,
write_some and write. The example in the module's docs connects, writes and reads.
One stream belongs to one scheduler thread. One fiber may read while another writes (every call into the TLS library is short and not interrupted by a switch to another fiber of the stream); two fibers reading, or two writing, take turns call by call, so their data interleaves.
A stream is allocated by tls_connect or tls_accept and freed by close, which must be called once and after which
the stream is not used. The fields are the module's own state, not an interface: use the procedures.
Fields
- reader: Io.Reader
- writer: Io.Writer
- ssl: *void
- fiber_context: #Context
- The running fiber's context, saved before every call into the library, so the callbacks the
library makes (which are
#c_call) can run Jai code and park the fiber. - lock: Io.Fiber_Mutex
- Calls into the library take turns. A fiber never waits for the network while it holds this:
the receive callback asks the library to retry and the fiber waits outside, and the send
callback only appends to
out. - out: [..] u8
- What the library has produced and the connection has not taken yet, in order. Appended to
under
lockby the send callback;flushwrites it out underflush_lock, so the bytes of two flushes never interleave. The library is never parked in a send: that is what lets both ends of a connection write a lot at once and still read each other. - flush_lock: Io.Fiber_Mutex
- flusher_running: bool
- A fiber started by
flush_lateris sendingout(it counts as a user of the stream). - io_error: Io.Io_Error
- What the Io call under the running library call returned, when it failed.
- broken: Io.Io_Error
- Set once the connection is unusable (an Io call failed in the middle of a record, a record did not decrypt, the peer cut the connection short): what every later call returns.
- failure: Tls_Error
- The error behind
broken, forlast_error. - can_wait: bool
- The underlying reader says when it is readable: the library is never made to wait for input inside a callback (it returns "want read" and the fiber waits outside), so a fiber waiting for data does not block a writer of the same stream.
- ready: bool
- ahead: [] u8
- Bytes read from the connection and not yet handed to the library. The library asks for one
record at a time (at most 16 KiB), and each ask used to cost a wait and a read on the
connection; reading more at once and serving the library from here costs one pair for several
records. The buffer lives from a read to the moment the library has taken all of it, so a
quiet connection holds none;
ahead_sizeis how much the next read takes (it grows while reads come back full, and starts again at the size of a record after a short one). - ahead_start: s64
- ahead_end: s64
- ahead_size: s64
- established: bool
- peer_closed: bool
- closing: bool
- users: s64
- Calls in progress; the stream is freed after
closewhen the last one has left. - key_log_proc: Tls_Key_Log_Proc
- The client's key log, from its config.
- key_log_data: *void
- peer_name_count: u8
- The server name a client asked for (SNI), on a server stream.
- peer_name_bytes: [255] u8