hanki

tls_stream

stdlib/core/tls_stream.hk: methods on the TlsStream resource type.

A TLS connection is a runtime-managed native resource (HANKI.md §4) as a TcpStream is: the per-actor heap closes one when its last handle goes, close! releases it eagerly, and its single-owner handle moves, never copies, across actors. split! invalidates the full handle and produces independently movable application read and write handles over one shared, scheduler-aware TLS record layer. They are application capabilities rather than descriptor halves: either may service read or write transport traffic.

Open one with tls.connect!; the methods here read, write, reset its deadline, and close. The primitive operations are @intrinsic in sys; this face delegates, and the [net] effect bubbles up through the call.

There are two faces and two error contracts. The inherent methods and the duplex Stream impl answer sys.TlsFailure, preserving whether the fault was the handshake, certificate, socket, or deadline. The directional ReadStream and WriteStream faces retain their common sys.NetError contract and fold a TLS failure into Other. Code that only frames one direction takes one of those fixed faces; duplex-and-close code takes S: Stream and can constrain S.Error to the conversion its caller needs.

There is no hermetic test block here: every method bottoms out in a real TLS connection via an @intrinsic, with no pure result to assert in the stdlib test pack. The directional mapping above is the one pure thing, and it is asserted.

asnet

def _as_net(f: sys.TlsFailure) -> sys.NetError

Render a TLS failure into the trait face's NetError. Other reports the whole rendered failure, host included, and only the ability to match on it.

_as_net(sys.TlsFailure(host="h", kind=sys.TlsCertificate("expired"))).to_string() => "h: certificate rejected: expired"

TlsStream

TlsStream, or tls.TlsStream, is a runtime-managed native resource handle (HANKI.md §4): live native state the per-actor memory manager owns, released when the last handle drops. It is single-owner - never copied, moved across a send - and has no fields of its own, so its methods are its whole surface. A handle is minted by an API that opens one; it is never constructed.

impl TlsStream

read!

def read!(self, max: u32) -> Result<bytes, sys.TlsFailure> [net]

Read once, returning up to max decrypted bytes. An empty bytes is EOF (the peer closed). Err(TlsFailure) on an I/O or protocol error or a closed stream. @no-doctest: reads a real connection; needs a peer, cannot assert in a doctest

write!

def write!(self, data: bytes) -> Result<i64, sys.TlsFailure> [net]

Write once, returning the count written (which may be less than data.length). For the whole buffer, use tls.write_all!. @no-doctest: writes a real connection; needs a peer, cannot assert in a doctest

set_deadline!

def set_deadline!(self, timeout_ms: i32) -> () [net]

Replace this connection's absolute wall-clock deadline. The TLS record layer and its socket share the new budget. @no-doctest: mutates a live TLS resource

version!

def version!(self) -> Result<sys.TlsVersion, sys.TlsFailure> [net]

The protocol version the handshake settled on, sys.V13 or sys.V12. sys.TlsVersion is Ord, ascending, and a policy floor is therefore a comparison: a payload that must not travel over 1.2 checks version >= sys.V13. Err(TlsFailure) once the stream is closed. @no-doctest: reads a real connection; needs a peer, cannot assert in a doctest

close!

def close!(self) -> () [net]

Release the connection now, sending close_notify best-effort so the peer can tell a clean shutdown from a truncation. Idempotent: dropping the last handle also closes a stream, and an explicit close! is eager optimisation. @no-doctest: side-effecting close; no return value to assert

split!

def split!(self) -> Pair<TlsReadHalf, TlsWriteHalf> [net]

Consume this full handle and return independently movable application read/write resources. The original handle accepts no later operation. @no-doctest: needs a live TLS connection

TlsReadHalf

TlsReadHalf, or tls.TlsReadHalf, is a runtime-managed native resource handle (HANKI.md §4): live native state the per-actor memory manager owns, released when the last handle drops. It is single-owner - never copied, moved across a send - and has no fields of its own, so its methods are its whole surface. A handle is minted by an API that opens one; it is never constructed.

impl TlsReadHalf

read!

def read!(self, max: u32) -> Result<bytes, sys.TlsFailure> [net]

Read once, returning up to max decrypted bytes. An empty bytes is EOF. @no-doctest: reads a real TLS connection; needs a peer

close!

def close!(self) -> () [net]

Close the application read direction. The sibling write half remains usable, including for TLS transport reads its record progress requires. @no-doctest: side-effecting close; no return value to assert

TlsWriteHalf

TlsWriteHalf, or tls.TlsWriteHalf, is a runtime-managed native resource handle (HANKI.md §4): live native state the per-actor memory manager owns, released when the last handle drops. It is single-owner - never copied, moved across a send - and has no fields of its own, so its methods are its whole surface. A handle is minted by an API that opens one; it is never constructed.

impl TlsWriteHalf

write!

def write!(self, data: bytes) -> Result<i64, sys.TlsFailure> [net]

Write once, returning the count accepted. @no-doctest: writes a real TLS connection; needs a peer

close!

def close!(self) -> () [net]

Close the application write direction and send close_notify best-effort. The sibling read half remains usable. @no-doctest: side-effecting close; no return value to assert

impl ReadStream<TlsStream>

read!

def read!(self, max: u32) -> Result<bytes, sys.NetError> [net]

See stream.ReadStream.read!. A TlsFailure folds into NetError.Other. @no-doctest: reads a real connection; needs a peer

impl WriteStream<TlsStream>

write!

def write!(self, data: bytes) -> Result<i64, sys.NetError> [net]

See stream.WriteStream.write!. A TlsFailure folds into NetError.Other. @no-doctest: writes a real connection; needs a peer

impl ReadStream<TlsReadHalf>

read!

def read!(self, max: u32) -> Result<bytes, sys.NetError> [net]

See stream.ReadStream.read!. A TlsFailure folds into NetError.Other. @no-doctest: reads a real TLS connection; needs a peer

impl WriteStream<TlsWriteHalf>

write!

def write!(self, data: bytes) -> Result<i64, sys.NetError> [net]

See stream.WriteStream.write!. A TlsFailure folds into NetError.Other. @no-doctest: writes a real TLS connection; needs a peer

impl Stream<TlsStream>

The Stream face preserves TlsFailure through the trait's associated error, while framing code remains generic over the transport.

Each body forwards to the inherent method of the same name above. This is not the self-call it looks like: inherent-wins coherence (HANKI.md §10) resolves self.read! to the inherent impl, never back into this one.

Error

type Error = sys.TlsFailure

read!

def read!(self, max: u32) -> Result<bytes, sys.TlsFailure> [net]

See stream.Stream.read!. @no-doctest: reads a real connection; needs a peer, cannot assert in a doctest

write!

def write!(self, data: bytes) -> Result<i64, sys.TlsFailure> [net]

See stream.Stream.write!. @no-doctest: writes a real connection; needs a peer, cannot assert in a doctest

close!

def close!(self) -> () [net]

See stream.Stream.close!. @no-doctest: side-effecting close; no return value to assert

impl DeadlineStream<TlsStream>

set_deadline!

def set_deadline!(self, timeout_ms: i32) -> () [net]

See stream.DeadlineStream.set_deadline!. @no-doctest: mutates a live TLS resource