Skip to content
Kavachकवच

Sockets

Also known as: socket tcp udp tls ssl quic connection listen accept datagram certificate mtls timeout port

● Intermediate5 minBefore this: HTTPSpec 14.10

std.net speaks the protocols under HTTP: TCP connections, UDP datagrams, TLS encryption and QUIC.

use std.net

fn echo_once(listener: Listener) ! NetError uses Net {
    const conn = try listener.accept()
    while true {
        const data = (try conn.read()) ?? break
        try conn.write(data)
    }
}

fn main() ! Error {
    const listener = try net.listen("127.0.0.1:0")
    const _server = spawn echo_once(listener)
    const conn = try net.connect(listener.address())
    try conn.write("namaste".bytes())
    const back = (try conn.read()) ?? Bytes([])
    print(back.text() ?? "?")
    conn.close()
}

The program ran and printed:

kavach run echo.kav

namaste
echo.kav: Kavach code, then what running it prints
  • conn.read() gives the bytes that came, or none once the other side has closed: ?? break ends the loop then.
  • While a task waits for the network, the program's other tasks run.
  • Addresses are text, "host:port"; port 0 asks the system for a free one.

Every function

Function or methodGives
net.listen(address) -> Listener ! NetErrorListens for connections at address
listener.address() -> StringThe address it listens at, with the port the system picked
listener.accept() -> Connection ! NetErrorWaits for the next connection
net.connect(address) -> Connection ! NetErrorA connection to address
net.connect_tls(address, protocols: [String] = [], roots: String = "", cert: String = "", key: String = "") -> Connection ! NetErrorA connection encrypted with TLS (1.3, or 1.2 for servers without 1.3). The server's certificate must be valid for the host name in address, checked against root certificates built into Kavach (decision 0021) and the PEM certificates in roots, if any (a company's own certificate authority); there is no way to skip the check. protocols are offered to the server (ALPN), such as ["h2", "http/1.1"]. With cert and key (PEM), the client proves who it is to a server that asks (mutual TLS)
net.listen_tls(address, cert, key, protocols: [String] = [], clients: String = "") -> Listener ! NetErrorListens for TLS connections, proving the server's identity with the certificate chain cert and private key key (PEM text, read with fs.read_text where they are files). key takes a secret (8.7), here and in connect_tls, so a key read with env or kept in a secret field needs no reveal. It chooses the first of protocols a client offers. With clients (PEM certificates), every client must present a certificate signed by one of them (mutual TLS); a client without one is refused while connecting
conn.read() -> Bytes? ! NetErrorWaits for data: the bytes that came (at most 64 KB at a time), or none once the other side has closed
conn.write(data) ! NetErrorSends all of data (Bytes)
conn.protocol() -> String?The protocol the two sides agreed on, from those connect_tls offered and listen_tls takes, or none
conn.peer() -> StringThe other side's address: for a connection a listener accepted, whoever opened it (203.0.113.7:51234)
conn.start_tls(host, protocols: [String] = [], roots: String = "", cert: String = "", key: String = "") -> Connection ! NetErrorTLS begun as a client on a connection that has spoken plain TCP so far, the way PostgreSQL's SSLRequest and SMTP's STARTTLS do it. The server's certificate is checked against host, and the other settings are those of connect_tls. It gives the encrypted connection; conn itself is closed from then on, so nothing is sent in the clear by mistake. key takes a secret, as in connect_tls
conn.accept_tls(cert, key, protocols: [String] = [], clients: String = "") -> Connection ! NetErrorThe server's side of the same: TLS begun on a connection the server accepted, with the settings of listen_tls; key takes a secret
conn.peer_certificate() -> Bytes?The other side's TLS certificate as DER: the server's on a client connection, a client's (mutual TLS) on a server one; none without TLS. For channel binding, such as SCRAM's tls-server-end-point, which hashes it
conn.client_cert() -> ClientCert?With mutual TLS (clients: on listen_tls), the names on the certificate the client showed: ClientCert(common_name:, dns:, uris:), from its subject and its subject-alternative names (a SPIFFE id such as spiffe://shop/orders is a URI); none otherwise (decision 0099)
conn.close()Closes the connection (or stops listening). A connection or listener is also closed when its last holder lets it go (6.1), so one a function opens and doesn't return is closed when the function ends
net.bind(address) -> UdpSocket ! NetErrorA UDP socket at address
sock.send(data, to) ! NetErrorSends data (Bytes) as one datagram to the address to
sock.receive() -> Datagram ! NetErrorWaits for the next datagram: Datagram(data: Bytes, from: String), with the sender's address
sock.address(), sock.close()As for a listener

A failed operation gives a NetError: Refused(address), TimedOut(address) or Failed(address, reason).

Limits and sizes

WhatLimit or sizeSource
Any network wait (not accept or receive)gives up after 30 seconds, with TimedOut; .timeout(d) changes it10-net.md
conn.read()at most 64 KB at a time10-net.md
A UDP datagramat most 64 KB is read10-net.md
An HTTP server's idle connectionclosed after 5 seconds without a request11-http.md

Every limit in Kavach, on one page: Limits and Sizes.

One page for each form

What Kavach does for you

  • A waiting task costs nothing

    A task waiting for the network sleeps on the operating system's event queue, and only the thread that has work wakes up.

    decision 0046