wire.bend
bend-kit-wire@0.4.2.0 · 93 lines · 0 definitions
1# Byte-exact TCP, UDP, and TLS sockets. Source: https://github.com/paymog/bend-kit/tree/main/wire
2import Base
3
4# Socket IO on octets: one Char per byte (0..255). Base's TCP/UDP effects
5# decode UTF-8, which breaks byte counts and binary protocols.
6# ms arguments are deadlines in milliseconds (0: none); a miss is ETIMEDOUT.
7# import ./wire.bend as Wire
8
9# TCP connect to a numeric IPv4 or IPv6 address, with a deadline.
10def connect(host: String, port: U32, ms: U32) ->
11 IO(Result<&1, &1, U32 & String, Socket>):
12 import "./effs/wire.c"
13 import "./effs/wire.js"
14
15def recv(sock: Socket, max: U32, ms: U32) ->
16 IO(Socket & Result<&1, &1, U32 & String, String>):
17 import "./effs/wire.c"
18 import "./effs/wire.js"
19
20def send(sock: Socket, data: String) ->
21 IO(Socket & Result<&1, &1, U32 & String, Unit>):
22 import "./effs/wire.c"
23 import "./effs/wire.js"
24
25def recv_from(sock: Socket, max: U32, ms: U32) ->
26 IO(Socket & Result<&1, &1, U32 & String, String & U32 & String>):
27 import "./effs/wire.c"
28 import "./effs/wire.js"
29
30def send_to(sock: Socket, host: String, port: U32, data: String) ->
31 IO(Socket & Result<&1, &1, U32 & String, Unit>):
32 import "./effs/wire.c"
33 import "./effs/wire.js"
34
35# TLS over a connected TCP socket (OpenSSL 3, loaded at run time; BEND_LIBSSL
36# overrides its path). The certificate chain and host name are always checked.
37def tls.connect(sock: Socket, host: String, ms: U32) ->
38 IO(Socket & Result<&1, &1, U32 & String, Unit>):
39 import "./effs/wire.c"
40 import "./effs/wire.js"
41
42# Use a PEM certificate chain and its private key for mutual TLS.
43# A load failure is EINVAL; a handshake or server verification failure is EPROTO.
44def tls.connect.cert(sock: Socket, host: String, ms: U32, cert_path: String, key_path: String) ->
45 IO(Socket & Result<&1, &1, U32 & String, Unit>):
46 import "./effs/wire.c"
47 import "./effs/wire.js"
48
49# protos is a comma-separated ALPN list (for example "h2,http/1.1").
50def tls.connect.alpn(sock: Socket, host: String, ms: U32, protos: String) ->
51 IO(Socket & Result<&1, &1, U32 & String, String>):
52 import "./effs/wire.c"
53 import "./effs/wire.js"
54
55def tls.send(sock: Socket, data: String) ->
56 IO(Socket & Result<&1, &1, U32 & String, Unit>):
57 import "./effs/wire.c"
58 import "./effs/wire.js"
59
60# "" once the peer sends close_notify. A bare EOF is an error.
61def tls.recv(sock: Socket, max: U32, ms: U32) ->
62 IO(Socket & Result<&1, &1, U32 & String, String>):
63 import "./effs/wire.c"
64 import "./effs/wire.js"
65
66# Ends the TLS session and closes the socket.
67def tls.close(sock: Socket) -> IO(Unit):
68 import "./effs/wire.c"
69 import "./effs/wire.js"
70
71# The .words forms move (len, words): bytes packed four to a U32, laid out as
72# bytes/bytes.bend packs them, so no String cell is made per byte.
73def recv.words(sock: Socket, max: U32, ms: U32) ->
74 IO(Socket & Result<&1, &1, U32 & String, U32 & Array<U32>>):
75 import "./effs/wire.c"
76 import "./effs/wire.js"
77
78# len past the end of words fails with EINVAL.
79def send.words(sock: Socket, len: U32, words: Array<U32>) ->
80 IO(Socket & Result<&1, &1, U32 & String, Unit>):
81 import "./effs/wire.c"
82 import "./effs/wire.js"
83
84# len 0 once the peer sends close_notify.
85def tls.recv.words(sock: Socket, max: U32, ms: U32) ->
86 IO(Socket & Result<&1, &1, U32 & String, U32 & Array<U32>>):
87 import "./effs/wire.c"
88 import "./effs/wire.js"
89
90def tls.send.words(sock: Socket, len: U32, words: Array<U32>) ->
91 IO(Socket & Result<&1, &1, U32 & String, Unit>):
92 import "./effs/wire.c"
93 import "./effs/wire.js"