~/bend-docscommunity

wire.bend relies on unsafe/foreign

raw source on the hub · import bend-kit-wire@0.4.6.0/wire.bend as Wire

Byte-exact TCP, UDP, and TLS sockets. Source: https://github.com/paymog/bend-kit/tree/main/wire

1 import
import Base

Effects (foreign code)

effect connect source · line 11 · raw

@host:String -> @port:U32 -> @ms:U32 -> IO(Result<&1, &1, Pair(U32, String), Socket>)

TCP connect to a numeric IPv4 or IPv6 address, with a deadline.

foreign: effs/wire.c, effs/wire.js

effect accept.deadline source · line 19 · raw

@listener:Listener -> @ms:U32 -> IO(Pair(Listener, Result<&1, &1, Pair(U32, String), Socket>))

One monotonic accept budget, ms: 1..2147483647. Every outcome returns the actual listener; timeout leaves it usable. Cooperative scheduling does not preempt arbitrary CPU work or blocking effects.

foreign: effs/wire.c, effs/wire.js

effect recv source · line 25 · raw

@sock:Socket -> @max:U32 -> @ms:U32 -> IO(Pair(Socket, Result<&1, &1, Pair(U32, String), String>))

Octet-String TCP and UDP effects are the slow path: one Char cell per byte.

foreign: effs/wire.c, effs/wire.js

effect send source · line 30 · raw

@sock:Socket -> @data:String -> IO(Pair(Socket, Result<&1, &1, Pair(U32, String), Unit>))

foreign: effs/wire.c, effs/wire.js

effect recv_from source · line 35 · raw

@sock:Socket -> @max:U32 -> @ms:U32 -> IO(Pair(Socket, Result<&1, &1, Pair(U32, String), Pair(String, Pair(U32, String))>))

foreign: effs/wire.c, effs/wire.js

effect send_to source · line 40 · raw

@sock:Socket -> @host:String -> @port:U32 -> @data:String -> IO(Pair(Socket, Result<&1, &1, Pair(U32, String), Unit>))

foreign: effs/wire.c, effs/wire.js

effect tls.connect source · line 47 · raw

@sock:Socket -> @host:String -> @ms:U32 -> IO(Pair(Socket, Result<&1, &1, Pair(U32, String), Unit>))

TLS over a connected TCP socket (OpenSSL 3, loaded at run time; BEND_LIBSSL overrides its path). The certificate chain and host name are always checked.

foreign: effs/wire.c, effs/wire.js

effect tls.connect.cert source · line 54 · raw

@sock:Socket -> @host:String -> @ms:U32 -> @cert_path:String -> @key_path:String -> IO(Pair(Socket, Result<&1, &1, Pair(U32, String), Unit>))

Use a PEM certificate chain and its private key for mutual TLS. A load failure is EINVAL; a handshake or server verification failure is EPROTO.

foreign: effs/wire.c, effs/wire.js

effect tls.connect.alpn source · line 60 · raw

@sock:Socket -> @host:String -> @ms:U32 -> @protos:String -> IO(Pair(Socket, Result<&1, &1, Pair(U32, String), String>))

protos is a comma-separated ALPN list (for example "h2,http/1.1").

foreign: effs/wire.c, effs/wire.js

effect tls.connect.ca source · line 67 · raw

@sock:Socket -> @host:String -> @ms:U32 -> @ca_path:String -> IO(Pair(Socket, Result<&1, &1, Pair(U32, String), Unit>))

Trust the PEM certificates in ca_path for this handshake, instead of the default verify paths. Verification stays on. A load failure is EINVAL.

foreign: effs/wire.c, effs/wire.js

effect tls.connect.alpn.ca source · line 73 · raw

@sock:Socket -> @host:String -> @ms:U32 -> @protos:String -> @ca_path:String -> IO(Pair(Socket, Result<&1, &1, Pair(U32, String), String>))

tls.connect.ca with a comma-separated ALPN list. The result is the selected protocol.

foreign: effs/wire.c, effs/wire.js

effect tls.send source · line 79 · raw

@sock:Socket -> @data:String -> IO(Pair(Socket, Result<&1, &1, Pair(U32, String), Unit>))

The String TLS effects are the slow path: one Char cell per octet.

foreign: effs/wire.c, effs/wire.js

effect tls.recv source · line 85 · raw

@sock:Socket -> @max:U32 -> @ms:U32 -> IO(Pair(Socket, Result<&1, &1, Pair(U32, String), String>))

"" once the peer sends close_notify. A bare EOF is an error.

foreign: effs/wire.c, effs/wire.js

effect tls.close source · line 91 · raw

@sock:Socket -> IO(Unit)

Ends the TLS session and closes the socket.

foreign: effs/wire.c, effs/wire.js

effect recv.words source · line 97 · raw

@sock:Socket -> @max:U32 -> @ms:U32 -> IO(Pair(Socket, Result<&1, &1, Pair(U32, String), Pair(U32, Array<U32>)>))

The .words forms move (len, words): bytes packed four to a U32, laid out as bytes/bytes.bend packs them, so no String cell is made per byte.

foreign: effs/wire.c, effs/wire.js

effect send.words source · line 103 · raw

@sock:Socket -> @len:U32 -> @words:Array<U32> -> IO(Pair(Socket, Result<&1, &1, Pair(U32, String), Unit>))

len past the end of words fails with EINVAL.

foreign: effs/wire.c, effs/wire.js

effect send.words.deadline source · line 112 · raw

@sock:Socket -> @len:U32 -> @words:Array<U32> -> @ms:U32 -> IO(Pair(Socket, Pair(U32, Result<&1, &1, Pair(U32, String), Unit>)))

Total write budget, including packing; ms must be 1..2147483647. Returns socket, bytes accepted locally, and outcome on every path. Consumes words on every path. Timeout/disconnect may leave a sent prefix: close the returned socket, do not replay the whole buffer. Success is not peer receipt.

foreign: effs/wire.c, effs/wire.js

effect recv_from.words source · line 118 · raw

@sock:Socket -> @max:U32 -> @ms:U32 -> IO(Pair(Socket, Result<&1, &1, Pair(U32, String), Pair(String, Pair(U32, Pair(U32, Array<U32>)))>))

UDP keeps the sender address and port beside the packed datagram.

foreign: effs/wire.c, effs/wire.js

effect send_to.words source · line 124 · raw

@sock:Socket -> @host:String -> @port:U32 -> @len:U32 -> @words:Array<U32> -> IO(Pair(Socket, Result<&1, &1, Pair(U32, String), Unit>))

len past the end of words fails with EINVAL.

foreign: effs/wire.c, effs/wire.js

effect tls.recv.words source · line 130 · raw

@sock:Socket -> @max:U32 -> @ms:U32 -> IO(Pair(Socket, Result<&1, &1, Pair(U32, String), Pair(U32, Array<U32>)>))

len 0 once the peer sends close_notify.

foreign: effs/wire.c, effs/wire.js

effect tls.send.words source · line 135 · raw

@sock:Socket -> @len:U32 -> @words:Array<U32> -> IO(Pair(Socket, Result<&1, &1, Pair(U32, String), Unit>))

foreign: effs/wire.c, effs/wire.js