silk/tls_connection
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc.
Authenticated TLS 1.3 with one owned partial-byte transport.
When to use
Use authenticateOwned when a caller must retain, move, pool, or explicitly close one
authenticated provider owner. Use withClient when the owner belongs to one lexical scope.
Prepare the trust snapshot independently before transferring the provider to either operation.
Details
Authentication consumes one provider and one already-prepared trust snapshot, samples wall time once, constructs the TLS client, and drives its handshake through exact partial transfers. The earlier of the finite handshake-duration deadline and an optional external absolute deadline bounds all handshake transport work. Ownership is published only after authentication and a final deadline check.
Gotchas
Direct owned I/O is guarded: typed failure or structured cancellation closes the owner and its
provider before an ambiguous buffer can be offered again. OwnedConnection.shutdownWrite
performs TLS grace for the write direction; OwnedConnection.close immediately invalidates
and terminally closes the provider. Scoped close failures are suppressed so they cannot replace
the protected result. Fatal traps remain outside structured finalization guarantees.
Examples
Supply every connection dependency explicitly
This deterministic wiring example uses an empty transport and trust snapshot, so authentication
fails and main returns 1. A real application supplies authenticated peer bytes and selected
trust through the same lexical boundaries.
import silk.allocator { Allocator, OutOfMemoryError }
import silk.effect { Effect }
import silk.https_identity { HttpsIdentity, OriginHost, ReferenceIdentity }
import silk.memory_byte_duplex { MemoryByteDuplex, MemoryReadEvent, MemoryWriteEvent }
import silk.monotonic_clock { MonotonicClock }
import silk.option { Option }
import silk.random { Random }
import silk.result { Result }
import silk.system_clock { Instant, SystemClock }
import silk.tls_client { AlpnConfig, ClientConfig, ClientLimits }
import silk.tls_connection { OwnedConnection, ConnectionOptions, withClient }
import silk.trust_anchor { TrustAnchor }
import silk.trust_snapshot { SnapshotLimits, TrustSnapshot }
import silk.u64
import silk.usize
import silk.vector { Vector }
struct FixedWall {}
impl SystemClock for FixedWall {
effect fn now(self: &mut Self) -> Instant { return SystemClock.make(0, 0) }
effect fn getResolution(self: &mut Self) -> u64 { return u64.toU64(1) }
}
struct FixedMonotonic {}
impl MonotonicClock for FixedMonotonic {
effect fn now(self: &mut Self) -> Instant { return SystemClock.make(0, 0) }
effect fn getResolution(self: &mut Self) -> u64 { return u64.toU64(1) }
effect fn waitUntil(self: &mut Self, when: Instant) -> () { drop when return () }
effect fn waitFor(self: &mut Self, howLong: u64) -> () { drop howLong return () }
}
struct ExampleRandom {}
impl Random for ExampleRandom {
effect fn fillBytes(self: &mut Self, output: &mut [u8]) -> () {
let mut index = usize.ZERO
while index < output.length { output[index] = 1 index = index + usize.ONE }
return ()
}
}
fn reference<'a>(host: &'a [u8]) -> ReferenceIdentity<'a> {
return match move HttpsIdentity.reference(OriginHost<'a>.Dns {bytes: host}) {
Result.Success {value} => value
Result.Failure {error} => { let invalid = 1 / 0 return reference(host) }
}
}
fn emptyTrust() -> TrustSnapshot {
return match move TrustSnapshot.fromAnchors(
Vector.make<TrustAnchor>(),
SnapshotLimits {anchors: 0, encodedBytes: 0},
) {
Result.Success {value} => move value
Result.Failure {error} => { let invalid = 1 / 0 return emptyTrust() }
}
}
effect fn inspect(
connection: &mut OwnedConnection<MemoryByteDuplex>,
) -> i32 {
drop connection
return 0
}
effect fn failed<E>(error: E) -> i32 { drop error return 1 }
effect fn program() -> i32 ! OutOfMemoryError {
let mut allocator = Allocator.systemAllocatorProvider()
let reads = Vector.make<MemoryReadEvent>()
let writes = Vector.make<MemoryWriteEvent>()
let mut transport = run MemoryByteDuplex.make(
move reads,
move writes,
256,
4,
Option.none<i32>(),
) |> Effect.provideMut<Allocator>(&mut allocator)
let trust = emptyTrust()
let mut wall = FixedWall {}
let mut monotonic = FixedMonotonic {}
let mut random = ExampleRandom {}
let host = b"example.com"
let config = ClientConfig {
reference: reference(&host),
alpn: AlpnConfig.defaults(),
limits: ClientLimits.defaults(),
}
let attempt = withClient<i32, never>(
move transport,
&config,
move trust,
ConnectionOptions.defaults(),
inspect,
)
|> Effect.provideMut<SystemClock>(&mut wall)
|> Effect.provideMut<MonotonicClock>(&mut monotonic)
|> Effect.provideMut<Random>(&mut random)
|> Effect.provideMut<Allocator>(&mut allocator)
return run Effect.catchAll(move attempt, failed)
}
pub fn main() -> i32 { return run Effect.catchAll(program(), failed) }Import as OwnedConnection with import silk.tls_connection { OwnedConnection }.
Public declarations: 6.
ConnectionPhase
pub enum ConnectionPhaseThe visible lifecycle of one authenticated connection.
Open
Open = 0Both authenticated directions remain available.
PeerEnded
PeerEnded = 1The peer sent authenticated close_notify; buffered plaintext may remain.
WriteShutdown
WriteShutdown = 2Local close_notify and transport write shutdown completed.
Invalid
Invalid = 3A protocol or transport failure made the lease unusable.
Closed
Closed = 4Terminal close consumed provider authority; later I/O cannot reach the provider.
ConnectionError
pub union ConnectionErrorA scoped connection failure that preserves its originating boundary.
Tls
ConnectionError.Tls { error: TlsError }: ConnectionErrorThe TLS state machine rejected peer input or caller state.
Field error
pub error: TlsErrorThe complete sticky TLS failure.
Io
ConnectionError.Io { error: ByteIoError }: ConnectionErrorThe byte provider rejected a non-handshake operation.
Field error
pub error: ByteIoErrorThe complete byte-I/O failure.
HandshakeTimeout
ConnectionError.HandshakeTimeout: ConnectionErrorThe single absolute handshake deadline was reached.
ConnectionOptions
pub struct ConnectionOptionsBounded policy copied for one owned client authentication.
Field handshakeTimeoutNanoseconds
pub handshakeTimeoutNanoseconds: u64Complete handshake duration on the active monotonic timeline.
Field externalDeadline
pub externalDeadline: silk/option.Option<silk/system_clock.Instant>Optional caller-owned absolute deadline clamped against the handshake duration.
Associated function ConnectionOptions.defaults
pub fn defaults() -> ConnectionOptionsReturns the 30-second handshake timeout without an external deadline.
OwnedConnection
pub struct OwnedConnection<P>One affine authenticated TLS client owning its exact byte provider.
Method OwnedConnection.phase
pub fn phase<P, 'life1>(self: &'life1 OwnedConnection<P>) -> ConnectionPhaseReturns the current directional, invalid, or terminal phase.
Method OwnedConnection.authentication
pub fn authentication<P, 'a>(self: &'a OwnedConnection<P>) -> silk/option.Option<silk/tls_client.Authentication<'a>>Borrows the authenticated session evidence retained by this connection.
Method OwnedConnection.readSome
pub effect<'env> fn readSome<P: 'env, 'connection: 'env, 'life2: 'env, 'env>(self: &'connection mut OwnedConnection<P>, output: &'life2 mut [u8], deadline: silk/option.Option<silk/system_clock.Instant>) -> ReadTransfer ! ConnectionError | OutOfMemoryError ? &mut MonotonicClock | &mut Allocator | &mut Random where &mut P provides &ByteDuplex from &mut ByteDuplex, &mut P provides &ByteDuplex from &mut ByteDuplex | &mut MonotonicClock | &mut Allocator | &mut RandomReads one verified plaintext prefix or clean authenticated peer end.
Details
Mandatory TLS output is sent first. Underlying end without close_notify is truncation.
Method OwnedConnection.writeSome
pub effect<'env> fn writeSome<P: 'env, 'connection: 'env, 'life2: 'env, 'env>(self: &'connection mut OwnedConnection<P>, input: &'life2 [u8], deadline: silk/option.Option<silk/system_clock.Instant>) -> usize ! ConnectionError | OutOfMemoryError ? &mut MonotonicClock | &mut Allocator | &mut Random where &mut P provides &ByteDuplex from &mut ByteDuplex, &mut P provides &ByteDuplex from &mut ByteDuplex | &mut MonotonicClock | &mut Allocator | &mut RandomEncrypts and transmits one positive application prefix.
Method OwnedConnection.flush
pub effect<'env> fn flush<P: 'env, 'connection: 'env, 'env>(self: &'connection mut OwnedConnection<P>, deadline: silk/option.Option<silk/system_clock.Instant>) -> () ! ConnectionError | OutOfMemoryError ? &mut MonotonicClock | &mut Allocator | &mut Random where &mut P provides &ByteDuplex from &mut ByteDuplex, &mut P provides &ByteDuplex from &mut ByteDuplex | &mut MonotonicClock | &mut Allocator | &mut RandomDrains mandatory TLS output and flushes the underlying byte boundary.
Method OwnedConnection.shutdownWrite
pub effect<'env> fn shutdownWrite<P: 'env, 'connection: 'env, 'env>(self: &'connection mut OwnedConnection<P>, deadline: silk/option.Option<silk/system_clock.Instant>) -> () ! ConnectionError | OutOfMemoryError ? &mut MonotonicClock | &mut Allocator | &mut Random where &mut P provides &ByteDuplex from &mut ByteDuplex, &mut P provides &ByteDuplex from &mut ByteDuplex | &mut MonotonicClock | &mut Allocator | &mut RandomSends and flushes TLS close_notify, then closes only the transport write direction.
Method OwnedConnection.close
pub effect<'env> fn close<P: 'env, 'life1: 'env, 'env>(self: &'life1 mut OwnedConnection<P>) -> () ! ConnectionError ? Without<&mut ByteDuplex, &ByteDuplex> where &mut P provides &ByteDuplex from &mut ByteDuplexTerminally closes the exact provider without TLS grace or retry.
Details
The connection becomes Closed before provider dispatch. Repeated close is local and
successful; a first provider close failure remains observable while later I/O stays closed.
authenticateOwned
pub effect<'env> fn authenticateOwned<P: 'env, 'life1: 'env, 'life2: 'env, 'env>(provider: P, config: &'life1 silk/tls_client.ClientConfig<'life2>, trust: TrustSnapshot, options: ConnectionOptions) -> silk/tls_connection.OwnedConnection<P> ! ConnectionError | OutOfMemoryError ? &mut SystemClock | &mut MonotonicClock | &mut Allocator | &mut Random where &mut P provides &ByteDuplex from &mut ByteDuplex, &mut P provides &ByteDuplex from &mut ByteDuplex | &mut MonotonicClock | &mut Allocator | &mut RandomConsumes a provider and prepared trust snapshot and returns one authenticated affine owner.
Details
The provider enters a nonparking guard before time sampling, client construction, allocation, or transport work. Authentication publishes only after the final deadline check; typed failure and structured cancellation close an unpublished provider exactly once.
withClient
pub effect<'env1> fn withClient<'env: 'env1, A, E, ?CallbackRequirements, P: 'env1, 'life5: 'env1, 'life6: 'env1, 'env1>(provider: P, config: &'life5 silk/tls_client.ClientConfig<'life6>, trust: TrustSnapshot, options: ConnectionOptions, callback: for<'call> once fn<'env>(&'call mut silk/tls_connection.OwnedConnection<P>) -> once Effect<'call & 'env; A ! E ? CallbackRequirements>) -> A ! E | ConnectionError | OutOfMemoryError ? CallbackRequirements | &mut SystemClock | &mut MonotonicClock | &mut Allocator | &mut Random where &mut P provides &ByteDuplex from &mut ByteDuplex, &mut P provides &ByteDuplex from &mut ByteDuplex | &mut MonotonicClock | &mut Allocator | &mut Random, CallbackRequirements in Without<CallbackRequirements, &ByteDuplex>Authenticates, lends, and terminally closes the same authoritative owned connection.