mt-lang 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/docs/index.html +4 -3
- data/lib/milk_tea/base.rb +1 -1
- data/std/asset_pack.mt +267 -0
- data/std/async/libuv_runtime.mt +539 -0
- data/std/async/mailbox.mt +191 -0
- data/std/async/runtime.mt +87 -0
- data/std/async.mt +87 -0
- data/std/base64.mt +185 -0
- data/std/behavior_tree.mt +396 -0
- data/std/binary.mt +314 -0
- data/std/binary_heap.mt +157 -0
- data/std/bitset.mt +239 -0
- data/std/box2d.mt +535 -0
- data/std/bytes.mt +46 -0
- data/std/c/box2d.mt +1254 -0
- data/std/c/cgltf.mt +647 -0
- data/std/c/cjson.mt +106 -0
- data/std/c/crypto.mt +11 -0
- data/std/c/crypto_support.h +51 -0
- data/std/c/ctype.mt +19 -0
- data/std/c/ctype_bindgen.h +29 -0
- data/std/c/curl.mt +1223 -0
- data/std/c/enet.mt +473 -0
- data/std/c/errno.mt +41 -0
- data/std/c/errno_bindgen.h +53 -0
- data/std/c/flecs.mt +2945 -0
- data/std/c/fs.linux.mt +43 -0
- data/std/c/fs.windows.mt +43 -0
- data/std/c/fs_support.h +954 -0
- data/std/c/gl.mt +2065 -0
- data/std/c/gl_registry_helpers.h +10748 -0
- data/std/c/glfw.mt +499 -0
- data/std/c/libc.mt +167 -0
- data/std/c/libuv.mt +1491 -0
- data/std/c/math.mt +22 -0
- data/std/c/math_bindgen.h +31 -0
- data/std/c/miniaudio.mt +3420 -0
- data/std/c/pcre2.mt +735 -0
- data/std/c/process.mt +58 -0
- data/std/c/process_support.h +1147 -0
- data/std/c/raygui.mt +1602 -0
- data/std/c/raylib.mt +1245 -0
- data/std/c/raymath.mt +163 -0
- data/std/c/rlgl.mt +434 -0
- data/std/c/rpng.mt +60 -0
- data/std/c/rres.mt +187 -0
- data/std/c/sdl3.mt +4132 -0
- data/std/c/sqlite3.mt +951 -0
- data/std/c/stb_image.mt +52 -0
- data/std/c/stb_image_resize2.mt +128 -0
- data/std/c/stb_image_write.mt +19 -0
- data/std/c/stb_rect_pack.mt +38 -0
- data/std/c/stb_truetype.mt +175 -0
- data/std/c/stb_vorbis.mt +31 -0
- data/std/c/stdio.mt +90 -0
- data/std/c/steamworks.h +5769 -0
- data/std/c/steamworks.mt +4771 -0
- data/std/c/string.mt +16 -0
- data/std/c/string_bindgen.h +36 -0
- data/std/c/sync.mt +33 -0
- data/std/c/sync_support.h +219 -0
- data/std/c/terminal.mt +24 -0
- data/std/c/terminal_support.h +408 -0
- data/std/c/time.mt +26 -0
- data/std/c/tls.mt +24 -0
- data/std/c/tls_support.h +626 -0
- data/std/c/tracy.mt +53 -0
- data/std/c/zlib.mt +20 -0
- data/std/c/zlib_support.h +239 -0
- data/std/c/zstd.mt +231 -0
- data/std/cell.mt +60 -0
- data/std/cgltf.mt +115 -0
- data/std/cjson.mt +90 -0
- data/std/cli.mt +768 -0
- data/std/cookie.mt +198 -0
- data/std/counter.mt +160 -0
- data/std/crypto.mt +74 -0
- data/std/cstring.mt +13 -0
- data/std/ctype.mt +52 -0
- data/std/curl/runtime.mt +261 -0
- data/std/curl.mt +38 -0
- data/std/deque.mt +348 -0
- data/std/encoding.mt +93 -0
- data/std/enet.mt +133 -0
- data/std/env.mt +41 -0
- data/std/errno.mt +47 -0
- data/std/flecs.mt +978 -0
- data/std/fmt.mt +271 -0
- data/std/fs.linux.mt +696 -0
- data/std/fs.windows.mt +711 -0
- data/std/fsm.mt +267 -0
- data/std/gl.mt +2062 -0
- data/std/glfw.mt +471 -0
- data/std/goap.mt +342 -0
- data/std/graph.mt +521 -0
- data/std/gzip.mt +77 -0
- data/std/hash.mt +429 -0
- data/std/http/server.mt +810 -0
- data/std/http.mt +1227 -0
- data/std/intern.mt +53 -0
- data/std/jobs.mt +288 -0
- data/std/json.mt +627 -0
- data/std/libc.mt +34 -0
- data/std/libuv.mt +554 -0
- data/std/linear_algebra.mt +243 -0
- data/std/linked_map.mt +372 -0
- data/std/linked_map_view.mt +49 -0
- data/std/linked_set.mt +117 -0
- data/std/log.mt +69 -0
- data/std/map.mt +418 -0
- data/std/math.mt +24 -0
- data/std/mem/arena.mt +137 -0
- data/std/mem/endian.mt +51 -0
- data/std/mem/heap.mt +298 -0
- data/std/mem/pool.mt +164 -0
- data/std/mem/stack.mt +47 -0
- data/std/mem/tracking.mt +119 -0
- data/std/miniaudio.mt +1299 -0
- data/std/multiset.mt +191 -0
- data/std/net/channel.mt +727 -0
- data/std/net/clock.mt +237 -0
- data/std/net/discovery.mt +277 -0
- data/std/net/lobby.mt +813 -0
- data/std/net/manager.mt +539 -0
- data/std/net/mux.mt +839 -0
- data/std/net/nat.mt +122 -0
- data/std/net/packet.mt +219 -0
- data/std/net/punch.mt +162 -0
- data/std/net/rpc.mt +119 -0
- data/std/net/session.mt +1157 -0
- data/std/net/stun.mt +252 -0
- data/std/net/sync.mt +183 -0
- data/std/net/turn.mt +459 -0
- data/std/net.mt +2944 -0
- data/std/oauth2.mt +408 -0
- data/std/option.mt +51 -0
- data/std/ordered_map.mt +497 -0
- data/std/ordered_set.mt +348 -0
- data/std/path.mt +368 -0
- data/std/pcre2/runtime.mt +35 -0
- data/std/pcre2.mt +78 -0
- data/std/priority_queue.mt +55 -0
- data/std/process.mt +837 -0
- data/std/queue.mt +55 -0
- data/std/random.mt +146 -0
- data/std/raygui.mt +99 -0
- data/std/raylib/debug_console.mt +71 -0
- data/std/raylib/easing.mt +388 -0
- data/std/raylib/packed_assets.mt +255 -0
- data/std/raylib/runtime.mt +30 -0
- data/std/raylib/tracy_gpu.mt +37 -0
- data/std/raylib.mt +1510 -0
- data/std/raymath.mt +153 -0
- data/std/result.mt +89 -0
- data/std/rlgl.mt +268 -0
- data/std/rpng.mt +46 -0
- data/std/rres.mt +36 -0
- data/std/sdl3/runtime.mt +54 -0
- data/std/sdl3.mt +1731 -0
- data/std/serialize.mt +68 -0
- data/std/set.mt +124 -0
- data/std/spatial.mt +176 -0
- data/std/sqlite3.mt +151 -0
- data/std/stack.mt +55 -0
- data/std/stb_image.mt +47 -0
- data/std/stb_image_resize2.mt +41 -0
- data/std/stb_image_write.mt +17 -0
- data/std/stb_rect_pack.mt +15 -0
- data/std/stb_truetype.mt +77 -0
- data/std/stb_vorbis.mt +16 -0
- data/std/stdio.mt +88 -0
- data/std/steamworks.mt +1542 -0
- data/std/str.mt +293 -0
- data/std/string.mt +234 -0
- data/std/sync.mt +194 -0
- data/std/tar.mt +704 -0
- data/std/terminal.mt +1002 -0
- data/std/testing.mt +266 -0
- data/std/thread.mt +120 -0
- data/std/time.mt +105 -0
- data/std/tls.mt +616 -0
- data/std/toml.mt +1310 -0
- data/std/tracy.mt +42 -0
- data/std/uri.mt +118 -0
- data/std/url.mt +372 -0
- data/std/vec.mt +433 -0
- data/std/zstd.mt +94 -0
- metadata +187 -2
data/std/net.mt
ADDED
|
@@ -0,0 +1,2944 @@
|
|
|
1
|
+
import std.async as aio
|
|
2
|
+
import std.async.libuv_runtime as aio_backend
|
|
3
|
+
import std.bytes as bytes
|
|
4
|
+
import std.c.libuv as libuv_c
|
|
5
|
+
import std.cstring as cstring
|
|
6
|
+
import std.libuv as libuv
|
|
7
|
+
import std.mem.arena as arena
|
|
8
|
+
import std.mem.heap as heap
|
|
9
|
+
import std.str as text
|
|
10
|
+
import std.string as string
|
|
11
|
+
import std.vec as vec
|
|
12
|
+
|
|
13
|
+
const address_name_capacity: ptr_uint = 128
|
|
14
|
+
|
|
15
|
+
public type NativeSocketStorage = libuv.sockaddr_storage
|
|
16
|
+
public type NativeTcpHandle = libuv.uv_tcp_t
|
|
17
|
+
public type NativeUdpHandle = libuv.uv_udp_t
|
|
18
|
+
|
|
19
|
+
type NativeSockAddr = libuv.sockaddr
|
|
20
|
+
type NativeSockAddrIn = libuv.sockaddr_in
|
|
21
|
+
type NativeSockAddrIn6 = libuv.sockaddr_in6
|
|
22
|
+
type NativeHandle = libuv.uv_handle_t
|
|
23
|
+
type NativeStreamHandle = libuv.uv_stream_t
|
|
24
|
+
type NativeRequest = libuv.uv_req_t
|
|
25
|
+
type NativeGetAddrInfoRequest = libuv.uv_getaddrinfo_t
|
|
26
|
+
type NativeConnectRequest = libuv.uv_connect_t
|
|
27
|
+
type NativeWriteRequest = libuv.uv_write_t
|
|
28
|
+
type NativeShutdownRequest = libuv.uv_shutdown_t
|
|
29
|
+
type NativeUdpSendRequest = libuv.uv_udp_send_t
|
|
30
|
+
type NativeBuffer = libuv.uv_buf_t
|
|
31
|
+
type NativeAddrInfo = libuv.addrinfo
|
|
32
|
+
type NativeOsFd = libuv.uv_os_fd_t
|
|
33
|
+
|
|
34
|
+
public struct TcpStream:
|
|
35
|
+
handle: ptr[NativeTcpHandle]?
|
|
36
|
+
|
|
37
|
+
public struct TcpListener:
|
|
38
|
+
handle: ptr[NativeTcpHandle]?
|
|
39
|
+
|
|
40
|
+
public struct UdpSocket:
|
|
41
|
+
handle: ptr[NativeUdpHandle]?
|
|
42
|
+
|
|
43
|
+
public struct UdpDatagram:
|
|
44
|
+
data: bytes.Bytes
|
|
45
|
+
source: SocketAddress
|
|
46
|
+
|
|
47
|
+
public struct Error:
|
|
48
|
+
code: int
|
|
49
|
+
message: string.String
|
|
50
|
+
|
|
51
|
+
public enum AddressKind: int
|
|
52
|
+
ipv4 = 4
|
|
53
|
+
ipv6 = 6
|
|
54
|
+
|
|
55
|
+
public struct SocketAddress:
|
|
56
|
+
storage: ptr[NativeSocketStorage]?
|
|
57
|
+
len: ptr_uint
|
|
58
|
+
kind: AddressKind
|
|
59
|
+
|
|
60
|
+
struct ResolveState:
|
|
61
|
+
ready: bool
|
|
62
|
+
status_code: int
|
|
63
|
+
result: Result[SocketAddress, Error]
|
|
64
|
+
result_owned: bool
|
|
65
|
+
waiter_frame: ptr[void]?
|
|
66
|
+
waiter: fn(frame: ptr[void]) -> void
|
|
67
|
+
waiter_registered: bool
|
|
68
|
+
req: ptr[NativeGetAddrInfoRequest]?
|
|
69
|
+
storage: arena.Arena
|
|
70
|
+
node: cstr?
|
|
71
|
+
service: cstr?
|
|
72
|
+
released: bool
|
|
73
|
+
|
|
74
|
+
struct ResolveAllState:
|
|
75
|
+
ready: bool
|
|
76
|
+
status_code: int
|
|
77
|
+
result: Result[vec.Vec[SocketAddress], Error]
|
|
78
|
+
result_owned: bool
|
|
79
|
+
waiter_frame: ptr[void]?
|
|
80
|
+
waiter: fn(frame: ptr[void]) -> void
|
|
81
|
+
waiter_registered: bool
|
|
82
|
+
req: ptr[NativeGetAddrInfoRequest]?
|
|
83
|
+
storage: arena.Arena
|
|
84
|
+
node: cstr?
|
|
85
|
+
service: cstr?
|
|
86
|
+
released: bool
|
|
87
|
+
|
|
88
|
+
struct ConnectState:
|
|
89
|
+
ready: bool
|
|
90
|
+
status_code: int
|
|
91
|
+
result: Result[TcpStream, Error]
|
|
92
|
+
result_owned: bool
|
|
93
|
+
waiter_frame: ptr[void]?
|
|
94
|
+
waiter: fn(frame: ptr[void]) -> void
|
|
95
|
+
waiter_registered: bool
|
|
96
|
+
req: ptr[NativeConnectRequest]?
|
|
97
|
+
handle: ptr[NativeTcpHandle]?
|
|
98
|
+
destination: SocketAddress
|
|
99
|
+
destination_owned: bool
|
|
100
|
+
released: bool
|
|
101
|
+
|
|
102
|
+
struct ListenerState:
|
|
103
|
+
handle: ptr[NativeTcpHandle]?
|
|
104
|
+
pending_connections: int
|
|
105
|
+
pending_error_code: int
|
|
106
|
+
accept_state: ptr[AcceptState]?
|
|
107
|
+
|
|
108
|
+
struct AcceptState:
|
|
109
|
+
ready: bool
|
|
110
|
+
status_code: int
|
|
111
|
+
result: Result[TcpStream, Error]
|
|
112
|
+
result_owned: bool
|
|
113
|
+
waiter_frame: ptr[void]?
|
|
114
|
+
waiter: fn(frame: ptr[void]) -> void
|
|
115
|
+
waiter_registered: bool
|
|
116
|
+
listener: ptr[ListenerState]?
|
|
117
|
+
|
|
118
|
+
struct TcpStreamState:
|
|
119
|
+
handle: ptr[NativeTcpHandle]?
|
|
120
|
+
read_state: ptr[ReadState]?
|
|
121
|
+
|
|
122
|
+
struct WriteState:
|
|
123
|
+
ready: bool
|
|
124
|
+
status_code: int
|
|
125
|
+
result: Result[ptr_uint, Error]
|
|
126
|
+
result_owned: bool
|
|
127
|
+
waiter_frame: ptr[void]?
|
|
128
|
+
waiter: fn(frame: ptr[void]) -> void
|
|
129
|
+
waiter_registered: bool
|
|
130
|
+
req: ptr[NativeWriteRequest]?
|
|
131
|
+
buffers: ptr[NativeBuffer]?
|
|
132
|
+
data: bytes.Bytes
|
|
133
|
+
released: bool
|
|
134
|
+
|
|
135
|
+
struct ReadState:
|
|
136
|
+
ready: bool
|
|
137
|
+
status_code: int
|
|
138
|
+
result: Result[bytes.Bytes, Error]
|
|
139
|
+
result_owned: bool
|
|
140
|
+
waiter_frame: ptr[void]?
|
|
141
|
+
waiter: fn(frame: ptr[void]) -> void
|
|
142
|
+
waiter_registered: bool
|
|
143
|
+
stream: ptr[TcpStreamState]?
|
|
144
|
+
max_bytes: ptr_uint
|
|
145
|
+
buffer: own[ubyte]?
|
|
146
|
+
received_bytes: ptr_uint
|
|
147
|
+
exact: bool
|
|
148
|
+
released: bool
|
|
149
|
+
|
|
150
|
+
struct ShutdownState:
|
|
151
|
+
ready: bool
|
|
152
|
+
status_code: int
|
|
153
|
+
result: Result[bool, Error]
|
|
154
|
+
result_owned: bool
|
|
155
|
+
waiter_frame: ptr[void]?
|
|
156
|
+
waiter: fn(frame: ptr[void]) -> void
|
|
157
|
+
waiter_registered: bool
|
|
158
|
+
req: ptr[NativeShutdownRequest]?
|
|
159
|
+
released: bool
|
|
160
|
+
|
|
161
|
+
struct UdpSocketState:
|
|
162
|
+
handle: ptr[NativeUdpHandle]?
|
|
163
|
+
receive_state: ptr[UdpReceiveState]?
|
|
164
|
+
pending_send_count: ptr_uint
|
|
165
|
+
closing: bool
|
|
166
|
+
|
|
167
|
+
struct UdpSendState:
|
|
168
|
+
ready: bool
|
|
169
|
+
status_code: int
|
|
170
|
+
result: Result[ptr_uint, Error]
|
|
171
|
+
result_owned: bool
|
|
172
|
+
waiter_frame: ptr[void]?
|
|
173
|
+
waiter: fn(frame: ptr[void]) -> void
|
|
174
|
+
waiter_registered: bool
|
|
175
|
+
req: ptr[NativeUdpSendRequest]?
|
|
176
|
+
buffers: ptr[NativeBuffer]?
|
|
177
|
+
data: bytes.Bytes
|
|
178
|
+
destination: SocketAddress
|
|
179
|
+
destination_owned: bool
|
|
180
|
+
released: bool
|
|
181
|
+
socket: ptr[UdpSocketState]?
|
|
182
|
+
|
|
183
|
+
struct UdpReceiveState:
|
|
184
|
+
ready: bool
|
|
185
|
+
status_code: int
|
|
186
|
+
result: Result[UdpDatagram, Error]
|
|
187
|
+
result_owned: bool
|
|
188
|
+
waiter_frame: ptr[void]?
|
|
189
|
+
waiter: fn(frame: ptr[void]) -> void
|
|
190
|
+
waiter_registered: bool
|
|
191
|
+
socket: ptr[UdpSocketState]?
|
|
192
|
+
max_bytes: ptr_uint
|
|
193
|
+
released: bool
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
function noop_waiter(frame: ptr[void]) -> void:
|
|
197
|
+
unsafe: frame
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
function resolve_state(frame: ptr[void]) -> ptr[ResolveState]:
|
|
201
|
+
return unsafe: ptr[ResolveState]<-frame
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
function resolve_all_state(frame: ptr[void]) -> ptr[ResolveAllState]:
|
|
205
|
+
return unsafe: ptr[ResolveAllState]<-frame
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
function req_as_base(req: ptr[NativeGetAddrInfoRequest]) -> ptr[NativeRequest]:
|
|
209
|
+
return unsafe: ptr[NativeRequest]<-req
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
function connect_state(frame: ptr[void]) -> ptr[ConnectState]:
|
|
213
|
+
return unsafe: ptr[ConnectState]<-frame
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
function connect_req_as_base(req: ptr[NativeConnectRequest]) -> ptr[NativeRequest]:
|
|
217
|
+
return unsafe: ptr[NativeRequest]<-req
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
function accept_state(frame: ptr[void]) -> ptr[AcceptState]:
|
|
221
|
+
return unsafe: ptr[AcceptState]<-frame
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
function write_state(frame: ptr[void]) -> ptr[WriteState]:
|
|
225
|
+
return unsafe: ptr[WriteState]<-frame
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
function stream_read_state(frame: ptr[void]) -> ptr[ReadState]:
|
|
229
|
+
return unsafe: ptr[ReadState]<-frame
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
function shutdown_state(frame: ptr[void]) -> ptr[ShutdownState]:
|
|
233
|
+
return unsafe: ptr[ShutdownState]<-frame
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
function udp_send_state(frame: ptr[void]) -> ptr[UdpSendState]:
|
|
237
|
+
return unsafe: ptr[UdpSendState]<-frame
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
function udp_receive_state(frame: ptr[void]) -> ptr[UdpReceiveState]:
|
|
241
|
+
return unsafe: ptr[UdpReceiveState]<-frame
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
function write_req_as_base(req: ptr[NativeWriteRequest]) -> ptr[NativeRequest]:
|
|
245
|
+
return unsafe: ptr[NativeRequest]<-req
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
function shutdown_req_as_base(req: ptr[NativeShutdownRequest]) -> ptr[NativeRequest]:
|
|
249
|
+
return unsafe: ptr[NativeRequest]<-req
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
function udp_send_req_as_base(req: ptr[NativeUdpSendRequest]) -> ptr[NativeRequest]:
|
|
253
|
+
return unsafe: ptr[NativeRequest]<-req
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
function sockaddr_storage_as_sockaddr(storage: ptr[NativeSocketStorage]) -> ptr[NativeSockAddr]:
|
|
257
|
+
return unsafe: ptr[NativeSockAddr]<-storage
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
function sockaddr_as_sockaddr_in(address: ptr[NativeSockAddr]) -> ptr[NativeSockAddrIn]:
|
|
261
|
+
return unsafe: ptr[NativeSockAddrIn]<-address
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
function sockaddr_as_sockaddr_in6(address: ptr[NativeSockAddr]) -> ptr[NativeSockAddrIn6]:
|
|
265
|
+
return unsafe: ptr[NativeSockAddrIn6]<-address
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
function tcp_as_handle(handle: ptr[NativeTcpHandle]) -> ptr[NativeHandle]:
|
|
269
|
+
return unsafe: ptr[NativeHandle]<-handle
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
function handle_as_tcp(handle: ptr[NativeHandle]) -> ptr[NativeTcpHandle]:
|
|
273
|
+
return unsafe: ptr[NativeTcpHandle]<-handle
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
function tcp_as_stream(handle: ptr[NativeTcpHandle]) -> ptr[NativeStreamHandle]:
|
|
277
|
+
return unsafe: ptr[NativeStreamHandle]<-handle
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
function stream_as_handle(stream: ptr[NativeStreamHandle]) -> ptr[NativeHandle]:
|
|
281
|
+
return unsafe: ptr[NativeHandle]<-stream
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
function udp_as_handle(handle: ptr[NativeUdpHandle]) -> ptr[NativeHandle]:
|
|
285
|
+
return unsafe: ptr[NativeHandle]<-handle
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
function handle_as_udp(handle: ptr[NativeHandle]) -> ptr[NativeUdpHandle]:
|
|
289
|
+
return unsafe: ptr[NativeUdpHandle]<-handle
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
function alloc_tcp_handle() -> ptr[NativeTcpHandle]:
|
|
293
|
+
let handle_size = libuv.handle_size(libuv.uv_handle_type.UV_TCP)
|
|
294
|
+
return unsafe: ptr[NativeTcpHandle]<-heap.must_alloc_zeroed_bytes(1, handle_size)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
function alloc_connect_request() -> ptr[NativeConnectRequest]:
|
|
298
|
+
let req_size = libuv.req_size(libuv.uv_req_type.UV_CONNECT)
|
|
299
|
+
return unsafe: ptr[NativeConnectRequest]<-heap.must_alloc_zeroed_bytes(1, req_size)
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
function alloc_write_request() -> ptr[NativeWriteRequest]:
|
|
303
|
+
let req_size = libuv.req_size(libuv.uv_req_type.UV_WRITE)
|
|
304
|
+
return unsafe: ptr[NativeWriteRequest]<-heap.must_alloc_zeroed_bytes(1, req_size)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
function alloc_shutdown_request() -> ptr[NativeShutdownRequest]:
|
|
308
|
+
let req_size = libuv.req_size(libuv.uv_req_type.UV_SHUTDOWN)
|
|
309
|
+
return unsafe: ptr[NativeShutdownRequest]<-heap.must_alloc_zeroed_bytes(1, req_size)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
function alloc_udp_handle() -> ptr[NativeUdpHandle]:
|
|
313
|
+
let handle_size = libuv.handle_size(libuv.uv_handle_type.UV_UDP)
|
|
314
|
+
return unsafe: ptr[NativeUdpHandle]<-heap.must_alloc_zeroed_bytes(1, handle_size)
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
function alloc_udp_send_request() -> ptr[NativeUdpSendRequest]:
|
|
318
|
+
let req_size = libuv.req_size(libuv.uv_req_type.UV_UDP_SEND)
|
|
319
|
+
return unsafe: ptr[NativeUdpSendRequest]<-heap.must_alloc_zeroed_bytes(1, req_size)
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
function tcp_close_callback(handle: ptr[NativeHandle]) -> void:
|
|
323
|
+
unsafe: heap.release_bytes(ptr[void]<-handle_as_tcp(handle))
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
function close_tcp_handle(handle: ptr[NativeTcpHandle]) -> void:
|
|
327
|
+
if libuv.is_closing(tcp_as_handle(handle)) != 0:
|
|
328
|
+
return
|
|
329
|
+
|
|
330
|
+
libuv.close(tcp_as_handle(handle), tcp_close_callback)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
function udp_close_callback(handle: ptr[NativeHandle]) -> void:
|
|
334
|
+
unsafe: heap.release_bytes(ptr[void]<-handle_as_udp(handle))
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
function close_raw_udp_handle(handle: ptr[NativeUdpHandle]) -> void:
|
|
338
|
+
if libuv.is_closing(udp_as_handle(handle)) != 0:
|
|
339
|
+
return
|
|
340
|
+
|
|
341
|
+
libuv.close(udp_as_handle(handle), udp_close_callback)
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
function release_uv_buffer(buffer: NativeBuffer) -> void:
|
|
345
|
+
unsafe: heap.release_bytes(ptr[void]<-buffer.base)
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
function attach_tcp_stream(handle: ptr[NativeTcpHandle]) -> TcpStream:
|
|
349
|
+
let state = heap.must_alloc_zeroed[TcpStreamState](1)
|
|
350
|
+
unsafe:
|
|
351
|
+
read(state).handle = handle
|
|
352
|
+
read(state).read_state = null
|
|
353
|
+
libuv.handle_set_data(tcp_as_handle(handle), ptr[void]<-state)
|
|
354
|
+
return TcpStream(handle = handle)
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
function attach_udp_socket(handle: ptr[NativeUdpHandle]) -> UdpSocket:
|
|
358
|
+
let state = heap.must_alloc_zeroed[UdpSocketState](1)
|
|
359
|
+
unsafe:
|
|
360
|
+
read(state).handle = handle
|
|
361
|
+
read(state).receive_state = null
|
|
362
|
+
libuv.handle_set_data(udp_as_handle(handle), ptr[void]<-state)
|
|
363
|
+
return UdpSocket(handle = handle)
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
function duplicate_socket_address(address: SocketAddress) -> Result[SocketAddress, Error]:
|
|
367
|
+
let storage = address.storage else:
|
|
368
|
+
return Result[SocketAddress, Error].failure(error= invalid_address_error("socket address is released"))
|
|
369
|
+
|
|
370
|
+
return socket_address_from_sockaddr(sockaddr_storage_as_sockaddr(storage), address.len)
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
function ipv4_socket_family() -> ushort:
|
|
374
|
+
var raw = zero[libuv.sockaddr_in]
|
|
375
|
+
let status_code = libuv.ip4_addr("0.0.0.0", 0, raw)
|
|
376
|
+
if status_code != 0:
|
|
377
|
+
fatal(c"std.net internal failed to determine AF_INET")
|
|
378
|
+
|
|
379
|
+
return raw.sin_family
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
function ipv6_socket_family() -> ushort:
|
|
383
|
+
var raw = zero[libuv.sockaddr_in6]
|
|
384
|
+
let status_code = libuv.ip6_addr("::", 0, raw)
|
|
385
|
+
if status_code != 0:
|
|
386
|
+
fatal(c"std.net internal failed to determine AF_INET6")
|
|
387
|
+
|
|
388
|
+
return raw.sin6_family
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
function socket_address_from_unknown_sockaddr(address: const_ptr[NativeSockAddr]?) -> Result[SocketAddress, Error]:
|
|
392
|
+
let live_address = address else:
|
|
393
|
+
return Result[SocketAddress, Error].failure(error= invalid_address_error("socket address is missing"))
|
|
394
|
+
|
|
395
|
+
let family = unsafe: read(live_address).sa_family
|
|
396
|
+
if family == ipv4_socket_family():
|
|
397
|
+
return socket_address_from_sockaddr(unsafe: ptr[NativeSockAddr]?<-address, size_of(NativeSockAddrIn))
|
|
398
|
+
|
|
399
|
+
if family == ipv6_socket_family():
|
|
400
|
+
return socket_address_from_sockaddr(unsafe: ptr[NativeSockAddr]?<-address, size_of(NativeSockAddrIn6))
|
|
401
|
+
|
|
402
|
+
return Result[SocketAddress, Error].failure(error= invalid_address_error("unsupported socket address family"))
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
function take_owned_message(message: str) -> string.String:
|
|
406
|
+
return string.String.from_str(message)
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
function libuv_error(code: int) -> Error:
|
|
410
|
+
return Error(code = code, message = take_owned_message(text.cstr_as_str(libuv.strerror(code))))
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
public function net_error(message: str) -> Error:
|
|
414
|
+
return Error(code = -1, message = take_owned_message(message))
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
function invalid_address_error(message: str) -> Error:
|
|
418
|
+
return net_error(message)
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
function socket_address_from_sockaddr(address: ptr[NativeSockAddr]?, length: ptr_uint) -> Result[SocketAddress, Error]:
|
|
422
|
+
let live_address = address else:
|
|
423
|
+
return Result[SocketAddress, Error].failure(error= invalid_address_error("resolver returned null address"))
|
|
424
|
+
|
|
425
|
+
let ipv4_size = size_of(NativeSockAddrIn)
|
|
426
|
+
let ipv6_size = size_of(NativeSockAddrIn6)
|
|
427
|
+
let storage = heap.must_alloc_zeroed[NativeSocketStorage](1)
|
|
428
|
+
|
|
429
|
+
var result = SocketAddress(storage = storage, len = 0, kind = AddressKind.ipv4)
|
|
430
|
+
if length == ipv4_size:
|
|
431
|
+
unsafe:
|
|
432
|
+
let source = ptr[ubyte]<-sockaddr_as_sockaddr_in(live_address)
|
|
433
|
+
let target = ptr[ubyte]<-storage
|
|
434
|
+
heap.copy_bytes(target, source, ipv4_size)
|
|
435
|
+
result.len = ipv4_size
|
|
436
|
+
result.kind = AddressKind.ipv4
|
|
437
|
+
return Result[SocketAddress, Error].success(value= result)
|
|
438
|
+
|
|
439
|
+
if length == ipv6_size:
|
|
440
|
+
unsafe:
|
|
441
|
+
let source = ptr[ubyte]<-sockaddr_as_sockaddr_in6(live_address)
|
|
442
|
+
let target = ptr[ubyte]<-storage
|
|
443
|
+
heap.copy_bytes(target, source, ipv6_size)
|
|
444
|
+
result.len = ipv6_size
|
|
445
|
+
result.kind = AddressKind.ipv6
|
|
446
|
+
return Result[SocketAddress, Error].success(value= result)
|
|
447
|
+
|
|
448
|
+
heap.release(storage)
|
|
449
|
+
return Result[SocketAddress, Error].failure(error= invalid_address_error("unsupported socket address family"))
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
function socket_address_to_string_result(address: SocketAddress) -> Result[string.String, Error]:
|
|
453
|
+
let storage_ptr = address.storage else:
|
|
454
|
+
return Result[string.String, Error].failure(error= invalid_address_error("socket address is released"))
|
|
455
|
+
|
|
456
|
+
var buffer: array[char, address_name_capacity] = zero[array[char, address_name_capacity]]
|
|
457
|
+
if address.kind == AddressKind.ipv4:
|
|
458
|
+
var value = unsafe: read(ptr[NativeSockAddrIn]<-storage_ptr)
|
|
459
|
+
let status_code = libuv.ip4_name(ptr_of(value), ptr_of(buffer[0]), address_name_capacity)
|
|
460
|
+
if status_code != 0:
|
|
461
|
+
return Result[string.String, Error].failure(error= libuv_error(status_code))
|
|
462
|
+
else:
|
|
463
|
+
var value = unsafe: read(ptr[NativeSockAddrIn6]<-storage_ptr)
|
|
464
|
+
let status_code = libuv.ip6_name(ptr_of(value), ptr_of(buffer[0]), address_name_capacity)
|
|
465
|
+
if status_code != 0:
|
|
466
|
+
return Result[string.String, Error].failure(error= libuv_error(status_code))
|
|
467
|
+
|
|
468
|
+
return Result[string.String, Error].success(value= string.String.from_str(text.chars_as_str(ptr_of(buffer[0]))))
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
function tcp_socket_address_from_getsockname(handle: ptr[NativeTcpHandle]?) -> Result[SocketAddress, Error]:
|
|
472
|
+
let live_handle = handle else:
|
|
473
|
+
return Result[SocketAddress, Error].failure(error= net_error("tcp handle is released"))
|
|
474
|
+
|
|
475
|
+
var raw = zero[NativeSocketStorage]
|
|
476
|
+
var name_length = int<-size_of(NativeSocketStorage)
|
|
477
|
+
let status_code = libuv_c.uv_tcp_getsockname(
|
|
478
|
+
live_handle,
|
|
479
|
+
sockaddr_storage_as_sockaddr(unsafe: ptr_of(raw)),
|
|
480
|
+
ptr_of(name_length)
|
|
481
|
+
)
|
|
482
|
+
if status_code != 0:
|
|
483
|
+
return Result[SocketAddress, Error].failure(error= libuv_error(status_code))
|
|
484
|
+
|
|
485
|
+
return socket_address_from_sockaddr(
|
|
486
|
+
sockaddr_storage_as_sockaddr(unsafe: ptr_of(raw)),
|
|
487
|
+
ptr_uint<-name_length
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
function tcp_socket_address_from_getpeername(handle: ptr[NativeTcpHandle]?) -> Result[SocketAddress, Error]:
|
|
492
|
+
let live_handle = handle else:
|
|
493
|
+
return Result[SocketAddress, Error].failure(error= net_error("tcp handle is released"))
|
|
494
|
+
|
|
495
|
+
var raw = zero[NativeSocketStorage]
|
|
496
|
+
var name_length = int<-size_of(NativeSocketStorage)
|
|
497
|
+
let status_code = libuv_c.uv_tcp_getpeername(
|
|
498
|
+
live_handle,
|
|
499
|
+
sockaddr_storage_as_sockaddr(unsafe: ptr_of(raw)),
|
|
500
|
+
ptr_of(name_length)
|
|
501
|
+
)
|
|
502
|
+
if status_code != 0:
|
|
503
|
+
return Result[SocketAddress, Error].failure(error= libuv_error(status_code))
|
|
504
|
+
|
|
505
|
+
return socket_address_from_sockaddr(
|
|
506
|
+
sockaddr_storage_as_sockaddr(unsafe: ptr_of(raw)),
|
|
507
|
+
ptr_uint<-name_length
|
|
508
|
+
)
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
function tcp_socket_fd(handle: ptr[NativeTcpHandle]?) -> Result[int, Error]:
|
|
512
|
+
let live_handle = handle else:
|
|
513
|
+
return Result[int, Error].failure(error= net_error("tcp handle is released"))
|
|
514
|
+
|
|
515
|
+
var fd = zero[NativeOsFd]
|
|
516
|
+
let status_code = libuv.fileno(tcp_as_handle(live_handle), fd)
|
|
517
|
+
if status_code != 0:
|
|
518
|
+
return Result[int, Error].failure(error= libuv_error(status_code))
|
|
519
|
+
|
|
520
|
+
return Result[int, Error].success(value= fd)
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
function udp_socket_address_from_getsockname(handle: ptr[NativeUdpHandle]?) -> Result[SocketAddress, Error]:
|
|
524
|
+
let live_handle = handle else:
|
|
525
|
+
return Result[SocketAddress, Error].failure(error= net_error("udp handle is released"))
|
|
526
|
+
|
|
527
|
+
var raw = zero[NativeSocketStorage]
|
|
528
|
+
var name_length = int<-size_of(NativeSocketStorage)
|
|
529
|
+
let status_code = libuv_c.uv_udp_getsockname(
|
|
530
|
+
live_handle,
|
|
531
|
+
sockaddr_storage_as_sockaddr(unsafe: ptr_of(raw)),
|
|
532
|
+
ptr_of(name_length)
|
|
533
|
+
)
|
|
534
|
+
if status_code != 0:
|
|
535
|
+
return Result[SocketAddress, Error].failure(error= libuv_error(status_code))
|
|
536
|
+
|
|
537
|
+
return socket_address_from_sockaddr(
|
|
538
|
+
sockaddr_storage_as_sockaddr(unsafe: ptr_of(raw)),
|
|
539
|
+
ptr_uint<-name_length
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
function udp_socket_address_from_getpeername(handle: ptr[NativeUdpHandle]?) -> Result[SocketAddress, Error]:
|
|
544
|
+
let live_handle = handle else:
|
|
545
|
+
return Result[SocketAddress, Error].failure(error= net_error("udp handle is released"))
|
|
546
|
+
|
|
547
|
+
var raw = zero[NativeSocketStorage]
|
|
548
|
+
var name_length = int<-size_of(NativeSocketStorage)
|
|
549
|
+
let status_code = libuv_c.uv_udp_getpeername(
|
|
550
|
+
live_handle,
|
|
551
|
+
sockaddr_storage_as_sockaddr(unsafe: ptr_of(raw)),
|
|
552
|
+
ptr_of(name_length)
|
|
553
|
+
)
|
|
554
|
+
if status_code != 0:
|
|
555
|
+
return Result[SocketAddress, Error].failure(error= libuv_error(status_code))
|
|
556
|
+
|
|
557
|
+
return socket_address_from_sockaddr(
|
|
558
|
+
sockaddr_storage_as_sockaddr(unsafe: ptr_of(raw)),
|
|
559
|
+
ptr_uint<-name_length
|
|
560
|
+
)
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
function udp_connect_impl(handle: ptr[NativeUdpHandle]?, destination: SocketAddress) -> Result[bool, Error]:
|
|
564
|
+
let live_handle = handle else:
|
|
565
|
+
return Result[bool, Error].failure(error= net_error("udp socket is released"))
|
|
566
|
+
|
|
567
|
+
if libuv.is_closing(udp_as_handle(live_handle)) != 0:
|
|
568
|
+
return Result[bool, Error].failure(error= net_error("udp socket is closing"))
|
|
569
|
+
|
|
570
|
+
let storage = destination.storage else:
|
|
571
|
+
return Result[bool, Error].failure(error= invalid_address_error("socket address is released"))
|
|
572
|
+
|
|
573
|
+
let status_code = libuv.udp_connect(live_handle, sockaddr_storage_as_sockaddr(storage))
|
|
574
|
+
if status_code != 0:
|
|
575
|
+
return Result[bool, Error].failure(error= libuv_error(status_code))
|
|
576
|
+
|
|
577
|
+
return Result[bool, Error].success(value= true)
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
function resolve_ready(frame: ptr[void]) -> bool:
|
|
581
|
+
return unsafe: read(resolve_state(frame)).ready
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
function resolve_set_waiter(frame: ptr[void], waiter_frame: ptr[void], waiter: fn(frame: ptr[void]) -> void) -> void:
|
|
585
|
+
let state = resolve_state(frame)
|
|
586
|
+
unsafe:
|
|
587
|
+
read(state).waiter_frame = waiter_frame
|
|
588
|
+
read(state).waiter = waiter
|
|
589
|
+
read(state).waiter_registered = true
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
function resolve_release(frame: ptr[void]) -> void:
|
|
593
|
+
let state = resolve_state(frame)
|
|
594
|
+
|
|
595
|
+
unsafe:
|
|
596
|
+
if read(state).released:
|
|
597
|
+
return
|
|
598
|
+
read(state).released = true
|
|
599
|
+
|
|
600
|
+
unsafe:
|
|
601
|
+
if read(state).result_owned:
|
|
602
|
+
let result_value = read(state).result
|
|
603
|
+
match result_value:
|
|
604
|
+
Result.success as payload:
|
|
605
|
+
payload.value.release()
|
|
606
|
+
Result.failure as payload:
|
|
607
|
+
payload.error.release()
|
|
608
|
+
|
|
609
|
+
var storage = read(state).storage
|
|
610
|
+
storage.release()
|
|
611
|
+
|
|
612
|
+
heap.release(state)
|
|
613
|
+
|
|
614
|
+
|
|
615
|
+
function resolve_take_result(frame: ptr[void]) -> Result[SocketAddress, Error]:
|
|
616
|
+
let state = resolve_state(frame)
|
|
617
|
+
let result_value = unsafe: read(state).result
|
|
618
|
+
unsafe: read(state).result_owned = false
|
|
619
|
+
return result_value
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
function resolve_task(state: ptr[ResolveState]) -> Task[Result[SocketAddress, Error]]:
|
|
623
|
+
return unsafe: Task[Result[SocketAddress, Error]](
|
|
624
|
+
frame = ptr[void]<-state,
|
|
625
|
+
ready = resolve_ready,
|
|
626
|
+
set_waiter = resolve_set_waiter,
|
|
627
|
+
release = resolve_release,
|
|
628
|
+
take_result = resolve_take_result
|
|
629
|
+
)
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
function release_socket_addresses(values: ref[vec.Vec[SocketAddress]]) -> void:
|
|
633
|
+
var index: ptr_uint = 0
|
|
634
|
+
while index < values.len:
|
|
635
|
+
let current = values.get(index) else:
|
|
636
|
+
fatal(c"std.net release_socket_addresses missing value")
|
|
637
|
+
|
|
638
|
+
var address = unsafe: read(current)
|
|
639
|
+
address.release()
|
|
640
|
+
index += 1
|
|
641
|
+
|
|
642
|
+
values.release()
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
function resolve_all_ready(frame: ptr[void]) -> bool:
|
|
646
|
+
return unsafe: read(resolve_all_state(frame)).ready
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
function resolve_all_set_waiter(
|
|
650
|
+
frame: ptr[void],
|
|
651
|
+
waiter_frame: ptr[void],
|
|
652
|
+
waiter: fn(frame: ptr[void]) -> void
|
|
653
|
+
) -> void:
|
|
654
|
+
let state = resolve_all_state(frame)
|
|
655
|
+
unsafe:
|
|
656
|
+
read(state).waiter_frame = waiter_frame
|
|
657
|
+
read(state).waiter = waiter
|
|
658
|
+
read(state).waiter_registered = true
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
function resolve_all_release(frame: ptr[void]) -> void:
|
|
662
|
+
let state = resolve_all_state(frame)
|
|
663
|
+
|
|
664
|
+
unsafe:
|
|
665
|
+
if read(state).released:
|
|
666
|
+
return
|
|
667
|
+
read(state).released = true
|
|
668
|
+
|
|
669
|
+
unsafe:
|
|
670
|
+
if read(state).result_owned:
|
|
671
|
+
let result_value = read(state).result
|
|
672
|
+
match result_value:
|
|
673
|
+
Result.success as payload:
|
|
674
|
+
var addresses = payload.value
|
|
675
|
+
release_socket_addresses(ref_of(addresses))
|
|
676
|
+
Result.failure as payload:
|
|
677
|
+
payload.error.release()
|
|
678
|
+
|
|
679
|
+
var storage = read(state).storage
|
|
680
|
+
storage.release()
|
|
681
|
+
|
|
682
|
+
heap.release(state)
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
function resolve_all_take_result(frame: ptr[void]) -> Result[vec.Vec[SocketAddress], Error]:
|
|
686
|
+
let state = resolve_all_state(frame)
|
|
687
|
+
let result_value = unsafe: read(state).result
|
|
688
|
+
unsafe: read(state).result_owned = false
|
|
689
|
+
return result_value
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
function resolve_all_task(state: ptr[ResolveAllState]) -> Task[Result[vec.Vec[SocketAddress], Error]]:
|
|
693
|
+
return unsafe: Task[Result[vec.Vec[SocketAddress], Error]](
|
|
694
|
+
frame = ptr[void]<-state,
|
|
695
|
+
ready = resolve_all_ready,
|
|
696
|
+
set_waiter = resolve_all_set_waiter,
|
|
697
|
+
release = resolve_all_release,
|
|
698
|
+
take_result = resolve_all_take_result
|
|
699
|
+
)
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
function connect_ready(frame: ptr[void]) -> bool:
|
|
703
|
+
return unsafe: read(connect_state(frame)).ready
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
function connect_set_waiter(frame: ptr[void], waiter_frame: ptr[void], waiter: fn(frame: ptr[void]) -> void) -> void:
|
|
707
|
+
let state = connect_state(frame)
|
|
708
|
+
unsafe:
|
|
709
|
+
if read(state).ready:
|
|
710
|
+
waiter(waiter_frame)
|
|
711
|
+
return
|
|
712
|
+
|
|
713
|
+
read(state).waiter_frame = waiter_frame
|
|
714
|
+
read(state).waiter = waiter
|
|
715
|
+
read(state).waiter_registered = true
|
|
716
|
+
|
|
717
|
+
|
|
718
|
+
function connect_cleanup_and_release(state: ptr[ConnectState]) -> void:
|
|
719
|
+
unsafe:
|
|
720
|
+
if read(state).req != null[ptr[NativeConnectRequest]]:
|
|
721
|
+
heap.release_bytes(ptr[void]<-read(state).req)
|
|
722
|
+
read(state).req = null
|
|
723
|
+
|
|
724
|
+
if read(state).destination_owned:
|
|
725
|
+
var destination = read(state).destination
|
|
726
|
+
destination.release()
|
|
727
|
+
read(state).destination_owned = false
|
|
728
|
+
|
|
729
|
+
if read(state).result_owned:
|
|
730
|
+
let result_value = read(state).result
|
|
731
|
+
match result_value:
|
|
732
|
+
Result.success as payload:
|
|
733
|
+
payload.value.release()
|
|
734
|
+
Result.failure as payload:
|
|
735
|
+
payload.error.release()
|
|
736
|
+
read(state).result_owned = false
|
|
737
|
+
|
|
738
|
+
if read(state).handle != null[ptr[NativeTcpHandle]]:
|
|
739
|
+
close_tcp_handle(unsafe: ptr[NativeTcpHandle]<-read(state).handle)
|
|
740
|
+
read(state).handle = null
|
|
741
|
+
|
|
742
|
+
heap.release(state)
|
|
743
|
+
|
|
744
|
+
|
|
745
|
+
function connect_release(frame: ptr[void]) -> void:
|
|
746
|
+
let state = connect_state(frame)
|
|
747
|
+
if unsafe: read(state).ready:
|
|
748
|
+
connect_cleanup_and_release(state)
|
|
749
|
+
return
|
|
750
|
+
|
|
751
|
+
unsafe: read(state).released = true
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
function connect_take_result(frame: ptr[void]) -> Result[TcpStream, Error]:
|
|
755
|
+
let state = connect_state(frame)
|
|
756
|
+
let result_value = unsafe: read(state).result
|
|
757
|
+
unsafe: read(state).result_owned = false
|
|
758
|
+
return result_value
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
function connect_task(state: ptr[ConnectState]) -> Task[Result[TcpStream, Error]]:
|
|
762
|
+
return unsafe: Task[Result[TcpStream, Error]](
|
|
763
|
+
frame = ptr[void]<-state,
|
|
764
|
+
ready = connect_ready,
|
|
765
|
+
set_waiter = connect_set_waiter,
|
|
766
|
+
release = connect_release,
|
|
767
|
+
take_result = connect_take_result
|
|
768
|
+
)
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
function finish_connect(state: ptr[ConnectState], result_value: Result[TcpStream, Error], status_code: int) -> void:
|
|
772
|
+
var waiter: fn(frame: ptr[void]) -> void = noop_waiter
|
|
773
|
+
var waiter_frame: ptr[void]? = null
|
|
774
|
+
var notify = false
|
|
775
|
+
|
|
776
|
+
unsafe:
|
|
777
|
+
read(state).result = result_value
|
|
778
|
+
read(state).result_owned = true
|
|
779
|
+
read(state).status_code = status_code
|
|
780
|
+
read(state).ready = true
|
|
781
|
+
if read(state).waiter_registered:
|
|
782
|
+
waiter = read(state).waiter
|
|
783
|
+
waiter_frame = read(state).waiter_frame
|
|
784
|
+
read(state).waiter_registered = false
|
|
785
|
+
notify = true
|
|
786
|
+
|
|
787
|
+
if notify and waiter_frame != null[ptr[void]]:
|
|
788
|
+
waiter(unsafe: waiter_frame)
|
|
789
|
+
return
|
|
790
|
+
|
|
791
|
+
if unsafe: read(state).released:
|
|
792
|
+
connect_cleanup_and_release(state)
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
function connect_callback(req: ptr[NativeConnectRequest], status_code: int) -> void:
|
|
796
|
+
let state_raw = libuv.req_get_data(connect_req_as_base(req)) else:
|
|
797
|
+
unsafe: heap.release_bytes(ptr[void]<-req)
|
|
798
|
+
return
|
|
799
|
+
|
|
800
|
+
let state = unsafe: ptr[ConnectState]<-state_raw
|
|
801
|
+
unsafe:
|
|
802
|
+
heap.release_bytes(ptr[void]<-req)
|
|
803
|
+
read(state).req = null
|
|
804
|
+
|
|
805
|
+
if status_code != 0:
|
|
806
|
+
let handle = unsafe: read(state).handle
|
|
807
|
+
if handle != null[ptr[NativeTcpHandle]]:
|
|
808
|
+
close_tcp_handle(unsafe: handle)
|
|
809
|
+
unsafe: read(state).handle = null
|
|
810
|
+
|
|
811
|
+
finish_connect(state, Result[TcpStream, Error].failure(error= libuv_error(status_code)), status_code)
|
|
812
|
+
return
|
|
813
|
+
|
|
814
|
+
let handle = unsafe: read(state).handle else:
|
|
815
|
+
finish_connect(
|
|
816
|
+
state,
|
|
817
|
+
Result[TcpStream, Error].failure(error= net_error("tcp connect completed without a handle")),
|
|
818
|
+
-1
|
|
819
|
+
)
|
|
820
|
+
return
|
|
821
|
+
|
|
822
|
+
unsafe: read(state).handle = null
|
|
823
|
+
finish_connect(state, Result[TcpStream, Error].success(value= attach_tcp_stream(handle)), 0)
|
|
824
|
+
|
|
825
|
+
|
|
826
|
+
function accept_ready(frame: ptr[void]) -> bool:
|
|
827
|
+
return unsafe: read(accept_state(frame)).ready
|
|
828
|
+
|
|
829
|
+
|
|
830
|
+
function accept_set_waiter(frame: ptr[void], waiter_frame: ptr[void], waiter: fn(frame: ptr[void]) -> void) -> void:
|
|
831
|
+
let state = accept_state(frame)
|
|
832
|
+
unsafe:
|
|
833
|
+
if read(state).ready:
|
|
834
|
+
waiter(waiter_frame)
|
|
835
|
+
return
|
|
836
|
+
|
|
837
|
+
read(state).waiter_frame = waiter_frame
|
|
838
|
+
read(state).waiter = waiter
|
|
839
|
+
read(state).waiter_registered = true
|
|
840
|
+
|
|
841
|
+
|
|
842
|
+
function accept_cleanup_and_release(state: ptr[AcceptState]) -> void:
|
|
843
|
+
unsafe:
|
|
844
|
+
if read(state).result_owned:
|
|
845
|
+
let result_value = read(state).result
|
|
846
|
+
match result_value:
|
|
847
|
+
Result.success as payload:
|
|
848
|
+
payload.value.release()
|
|
849
|
+
Result.failure as payload:
|
|
850
|
+
payload.error.release()
|
|
851
|
+
read(state).result_owned = false
|
|
852
|
+
|
|
853
|
+
heap.release(state)
|
|
854
|
+
|
|
855
|
+
|
|
856
|
+
function accept_release(frame: ptr[void]) -> void:
|
|
857
|
+
let state = accept_state(frame)
|
|
858
|
+
if unsafe: read(state).ready:
|
|
859
|
+
accept_cleanup_and_release(state)
|
|
860
|
+
return
|
|
861
|
+
|
|
862
|
+
let listener = unsafe: read(state).listener
|
|
863
|
+
if listener != null[ptr[ListenerState]]:
|
|
864
|
+
let live_listener = unsafe: listener
|
|
865
|
+
if unsafe: read(live_listener).accept_state == state:
|
|
866
|
+
unsafe: read(live_listener).accept_state = null
|
|
867
|
+
|
|
868
|
+
unsafe: read(state).listener = null
|
|
869
|
+
heap.release(state)
|
|
870
|
+
|
|
871
|
+
|
|
872
|
+
function accept_take_result(frame: ptr[void]) -> Result[TcpStream, Error]:
|
|
873
|
+
let state = accept_state(frame)
|
|
874
|
+
let result_value = unsafe: read(state).result
|
|
875
|
+
unsafe: read(state).result_owned = false
|
|
876
|
+
return result_value
|
|
877
|
+
|
|
878
|
+
|
|
879
|
+
function accept_task(state: ptr[AcceptState]) -> Task[Result[TcpStream, Error]]:
|
|
880
|
+
return unsafe: Task[Result[TcpStream, Error]](
|
|
881
|
+
frame = ptr[void]<-state,
|
|
882
|
+
ready = accept_ready,
|
|
883
|
+
set_waiter = accept_set_waiter,
|
|
884
|
+
release = accept_release,
|
|
885
|
+
take_result = accept_take_result
|
|
886
|
+
)
|
|
887
|
+
|
|
888
|
+
|
|
889
|
+
function finish_accept(state: ptr[AcceptState], result_value: Result[TcpStream, Error], status_code: int) -> void:
|
|
890
|
+
var waiter: fn(frame: ptr[void]) -> void = noop_waiter
|
|
891
|
+
var waiter_frame: ptr[void]? = null
|
|
892
|
+
var notify = false
|
|
893
|
+
|
|
894
|
+
unsafe:
|
|
895
|
+
read(state).result = result_value
|
|
896
|
+
read(state).result_owned = true
|
|
897
|
+
read(state).status_code = status_code
|
|
898
|
+
read(state).ready = true
|
|
899
|
+
read(state).listener = null
|
|
900
|
+
if read(state).waiter_registered:
|
|
901
|
+
waiter = read(state).waiter
|
|
902
|
+
waiter_frame = read(state).waiter_frame
|
|
903
|
+
read(state).waiter_registered = false
|
|
904
|
+
notify = true
|
|
905
|
+
|
|
906
|
+
if notify and waiter_frame != null[ptr[void]]:
|
|
907
|
+
waiter(unsafe: waiter_frame)
|
|
908
|
+
|
|
909
|
+
|
|
910
|
+
function listener_close_callback(handle: ptr[NativeHandle]) -> void:
|
|
911
|
+
let state_raw = libuv.handle_get_data(handle) else:
|
|
912
|
+
unsafe: heap.release_bytes(ptr[void]<-handle_as_tcp(handle))
|
|
913
|
+
return
|
|
914
|
+
|
|
915
|
+
let listener = unsafe: ptr[ListenerState]<-state_raw
|
|
916
|
+
let pending_accept = unsafe: read(listener).accept_state
|
|
917
|
+
if pending_accept != null[ptr[AcceptState]]:
|
|
918
|
+
unsafe: read(listener).accept_state = null
|
|
919
|
+
finish_accept(
|
|
920
|
+
unsafe: pending_accept,
|
|
921
|
+
Result[TcpStream, Error].failure(error= net_error("listener closed")),
|
|
922
|
+
-1
|
|
923
|
+
)
|
|
924
|
+
|
|
925
|
+
unsafe:
|
|
926
|
+
heap.release_bytes(ptr[void]<-handle_as_tcp(handle))
|
|
927
|
+
read(listener).handle = null
|
|
928
|
+
heap.release(listener)
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
function perform_listener_accept(listener: ptr[ListenerState], state: ptr[AcceptState]) -> void:
|
|
932
|
+
let server_handle = unsafe: read(listener).handle else:
|
|
933
|
+
finish_accept(state, Result[TcpStream, Error].failure(error= net_error("listener is released")), -1)
|
|
934
|
+
return
|
|
935
|
+
|
|
936
|
+
let client_handle = alloc_tcp_handle()
|
|
937
|
+
let init_status = libuv.tcp_init(libuv.handle_get_loop(tcp_as_handle(server_handle)), client_handle)
|
|
938
|
+
if init_status != 0:
|
|
939
|
+
unsafe: heap.release_bytes(ptr[void]<-client_handle)
|
|
940
|
+
finish_accept(state, Result[TcpStream, Error].failure(error= libuv_error(init_status)), init_status)
|
|
941
|
+
return
|
|
942
|
+
|
|
943
|
+
let accept_status = libuv.accept(tcp_as_stream(server_handle), tcp_as_stream(client_handle))
|
|
944
|
+
if accept_status != 0:
|
|
945
|
+
close_tcp_handle(client_handle)
|
|
946
|
+
finish_accept(state, Result[TcpStream, Error].failure(error= libuv_error(accept_status)), accept_status)
|
|
947
|
+
return
|
|
948
|
+
|
|
949
|
+
finish_accept(state, Result[TcpStream, Error].success(value= attach_tcp_stream(client_handle)), 0)
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
function listener_connection_callback(server: ptr[NativeStreamHandle], status_code: int) -> void:
|
|
953
|
+
let state_raw = libuv.handle_get_data(stream_as_handle(server)) else:
|
|
954
|
+
return
|
|
955
|
+
|
|
956
|
+
let listener = unsafe: ptr[ListenerState]<-state_raw
|
|
957
|
+
let pending_accept = unsafe: read(listener).accept_state
|
|
958
|
+
if status_code != 0:
|
|
959
|
+
if pending_accept != null[ptr[AcceptState]]:
|
|
960
|
+
unsafe: read(listener).accept_state = null
|
|
961
|
+
finish_accept(
|
|
962
|
+
unsafe: pending_accept,
|
|
963
|
+
Result[TcpStream, Error].failure(error= libuv_error(status_code)),
|
|
964
|
+
status_code
|
|
965
|
+
)
|
|
966
|
+
else:
|
|
967
|
+
unsafe: read(listener).pending_error_code = status_code
|
|
968
|
+
return
|
|
969
|
+
|
|
970
|
+
if pending_accept != null[ptr[AcceptState]]:
|
|
971
|
+
unsafe: read(listener).accept_state = null
|
|
972
|
+
perform_listener_accept(listener, unsafe: pending_accept)
|
|
973
|
+
return
|
|
974
|
+
|
|
975
|
+
unsafe: read(listener).pending_connections += 1
|
|
976
|
+
|
|
977
|
+
|
|
978
|
+
function accept_impl(handle: ptr[NativeTcpHandle]?) -> Task[Result[TcpStream, Error]]:
|
|
979
|
+
let state = heap.must_alloc_zeroed[AcceptState](1)
|
|
980
|
+
unsafe:
|
|
981
|
+
read(state).ready = false
|
|
982
|
+
read(state).status_code = 0
|
|
983
|
+
read(state).result = Result[TcpStream, Error].success(value= zero[TcpStream])
|
|
984
|
+
read(state).result_owned = false
|
|
985
|
+
read(state).waiter_frame = null
|
|
986
|
+
read(state).waiter = noop_waiter
|
|
987
|
+
read(state).waiter_registered = false
|
|
988
|
+
read(state).listener = null
|
|
989
|
+
|
|
990
|
+
let live_handle = handle else:
|
|
991
|
+
finish_accept(state, Result[TcpStream, Error].failure(error= net_error("listener is released")), -1)
|
|
992
|
+
return accept_task(state)
|
|
993
|
+
|
|
994
|
+
if libuv.is_closing(tcp_as_handle(live_handle)) != 0:
|
|
995
|
+
finish_accept(state, Result[TcpStream, Error].failure(error= net_error("listener is closing")), -1)
|
|
996
|
+
return accept_task(state)
|
|
997
|
+
|
|
998
|
+
let state_raw = libuv.handle_get_data(tcp_as_handle(live_handle)) else:
|
|
999
|
+
finish_accept(state, Result[TcpStream, Error].failure(error= net_error("listener state is unavailable")), -1)
|
|
1000
|
+
return accept_task(state)
|
|
1001
|
+
|
|
1002
|
+
let listener = unsafe: ptr[ListenerState]<-state_raw
|
|
1003
|
+
unsafe: read(state).listener = listener
|
|
1004
|
+
|
|
1005
|
+
let pending_error_code = unsafe: read(listener).pending_error_code
|
|
1006
|
+
if pending_error_code != 0:
|
|
1007
|
+
unsafe:
|
|
1008
|
+
read(listener).pending_error_code = 0
|
|
1009
|
+
read(state).listener = null
|
|
1010
|
+
finish_accept(
|
|
1011
|
+
state,
|
|
1012
|
+
Result[TcpStream, Error].failure(error= libuv_error(pending_error_code)),
|
|
1013
|
+
pending_error_code
|
|
1014
|
+
)
|
|
1015
|
+
return accept_task(state)
|
|
1016
|
+
|
|
1017
|
+
if unsafe: read(listener).accept_state != null[ptr[AcceptState]]:
|
|
1018
|
+
unsafe: read(state).listener = null
|
|
1019
|
+
finish_accept(
|
|
1020
|
+
state,
|
|
1021
|
+
Result[TcpStream, Error].failure(error= net_error("listener already has a pending accept")),
|
|
1022
|
+
-1
|
|
1023
|
+
)
|
|
1024
|
+
return accept_task(state)
|
|
1025
|
+
|
|
1026
|
+
if unsafe: read(listener).pending_connections > 0:
|
|
1027
|
+
unsafe: read(listener).pending_connections -= 1
|
|
1028
|
+
perform_listener_accept(listener, state)
|
|
1029
|
+
return accept_task(state)
|
|
1030
|
+
|
|
1031
|
+
unsafe: read(listener).accept_state = state
|
|
1032
|
+
return accept_task(state)
|
|
1033
|
+
|
|
1034
|
+
|
|
1035
|
+
function tcp_stream_close_callback(handle: ptr[NativeHandle]) -> void:
|
|
1036
|
+
let state_raw = libuv.handle_get_data(handle) else:
|
|
1037
|
+
unsafe: heap.release_bytes(ptr[void]<-handle_as_tcp(handle))
|
|
1038
|
+
return
|
|
1039
|
+
|
|
1040
|
+
let stream = unsafe: ptr[TcpStreamState]<-state_raw
|
|
1041
|
+
let pending_read = unsafe: read(stream).read_state
|
|
1042
|
+
if pending_read != null[ptr[ReadState]]:
|
|
1043
|
+
unsafe:
|
|
1044
|
+
read(stream).read_state = null
|
|
1045
|
+
read(pending_read).stream = null
|
|
1046
|
+
finish_stream_read(
|
|
1047
|
+
unsafe: pending_read,
|
|
1048
|
+
Result[bytes.Bytes, Error].failure(error= net_error("tcp stream closed")),
|
|
1049
|
+
-1
|
|
1050
|
+
)
|
|
1051
|
+
|
|
1052
|
+
unsafe:
|
|
1053
|
+
heap.release_bytes(ptr[void]<-handle_as_tcp(handle))
|
|
1054
|
+
read(stream).handle = null
|
|
1055
|
+
heap.release(stream)
|
|
1056
|
+
|
|
1057
|
+
|
|
1058
|
+
function close_tcp_stream_handle(handle: ptr[NativeTcpHandle]) -> void:
|
|
1059
|
+
if libuv.is_closing(tcp_as_handle(handle)) != 0:
|
|
1060
|
+
return
|
|
1061
|
+
|
|
1062
|
+
let state_raw = libuv.handle_get_data(tcp_as_handle(handle))
|
|
1063
|
+
if state_raw == null[ptr[void]]:
|
|
1064
|
+
close_tcp_handle(handle)
|
|
1065
|
+
return
|
|
1066
|
+
|
|
1067
|
+
libuv.close(tcp_as_handle(handle), tcp_stream_close_callback)
|
|
1068
|
+
|
|
1069
|
+
|
|
1070
|
+
function write_ready(frame: ptr[void]) -> bool:
|
|
1071
|
+
return unsafe: read(write_state(frame)).ready
|
|
1072
|
+
|
|
1073
|
+
|
|
1074
|
+
function write_set_waiter(frame: ptr[void], waiter_frame: ptr[void], waiter: fn(frame: ptr[void]) -> void) -> void:
|
|
1075
|
+
let state = write_state(frame)
|
|
1076
|
+
unsafe:
|
|
1077
|
+
if read(state).ready:
|
|
1078
|
+
waiter(waiter_frame)
|
|
1079
|
+
return
|
|
1080
|
+
|
|
1081
|
+
read(state).waiter_frame = waiter_frame
|
|
1082
|
+
read(state).waiter = waiter
|
|
1083
|
+
read(state).waiter_registered = true
|
|
1084
|
+
|
|
1085
|
+
|
|
1086
|
+
function write_cleanup_and_release(state: ptr[WriteState]) -> void:
|
|
1087
|
+
unsafe:
|
|
1088
|
+
if read(state).req != null[ptr[NativeWriteRequest]]:
|
|
1089
|
+
heap.release_bytes(ptr[void]<-read(state).req)
|
|
1090
|
+
read(state).req = null
|
|
1091
|
+
|
|
1092
|
+
if read(state).buffers != null[ptr[NativeBuffer]]:
|
|
1093
|
+
heap.release(read(state).buffers)
|
|
1094
|
+
read(state).buffers = null
|
|
1095
|
+
|
|
1096
|
+
var stored_data = read(state).data
|
|
1097
|
+
stored_data.release()
|
|
1098
|
+
read(state).data = bytes.Bytes.empty()
|
|
1099
|
+
|
|
1100
|
+
if read(state).result_owned:
|
|
1101
|
+
let result_value = read(state).result
|
|
1102
|
+
match result_value:
|
|
1103
|
+
Result.success as ok_payload:
|
|
1104
|
+
ok_payload.value
|
|
1105
|
+
Result.failure as error_payload:
|
|
1106
|
+
error_payload.error.release()
|
|
1107
|
+
read(state).result_owned = false
|
|
1108
|
+
|
|
1109
|
+
heap.release(state)
|
|
1110
|
+
|
|
1111
|
+
|
|
1112
|
+
function write_release(frame: ptr[void]) -> void:
|
|
1113
|
+
let state = write_state(frame)
|
|
1114
|
+
if unsafe: read(state).ready:
|
|
1115
|
+
write_cleanup_and_release(state)
|
|
1116
|
+
return
|
|
1117
|
+
|
|
1118
|
+
unsafe: read(state).released = true
|
|
1119
|
+
|
|
1120
|
+
|
|
1121
|
+
function write_take_result(frame: ptr[void]) -> Result[ptr_uint, Error]:
|
|
1122
|
+
let state = write_state(frame)
|
|
1123
|
+
let result_value = unsafe: read(state).result
|
|
1124
|
+
unsafe: read(state).result_owned = false
|
|
1125
|
+
return result_value
|
|
1126
|
+
|
|
1127
|
+
|
|
1128
|
+
function write_task(state: ptr[WriteState]) -> Task[Result[ptr_uint, Error]]:
|
|
1129
|
+
return unsafe: Task[Result[ptr_uint, Error]](
|
|
1130
|
+
frame = ptr[void]<-state,
|
|
1131
|
+
ready = write_ready,
|
|
1132
|
+
set_waiter = write_set_waiter,
|
|
1133
|
+
release = write_release,
|
|
1134
|
+
take_result = write_take_result
|
|
1135
|
+
)
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
function finish_write(
|
|
1139
|
+
state: ptr[WriteState],
|
|
1140
|
+
result_value: Result[ptr_uint, Error],
|
|
1141
|
+
status_code: int,
|
|
1142
|
+
owns_error: bool
|
|
1143
|
+
) -> void:
|
|
1144
|
+
var waiter: fn(frame: ptr[void]) -> void = noop_waiter
|
|
1145
|
+
var waiter_frame: ptr[void]? = null
|
|
1146
|
+
var notify = false
|
|
1147
|
+
|
|
1148
|
+
unsafe:
|
|
1149
|
+
read(state).result = result_value
|
|
1150
|
+
read(state).result_owned = owns_error
|
|
1151
|
+
read(state).status_code = status_code
|
|
1152
|
+
read(state).ready = true
|
|
1153
|
+
if read(state).waiter_registered:
|
|
1154
|
+
waiter = read(state).waiter
|
|
1155
|
+
waiter_frame = read(state).waiter_frame
|
|
1156
|
+
read(state).waiter_registered = false
|
|
1157
|
+
notify = true
|
|
1158
|
+
|
|
1159
|
+
if notify and waiter_frame != null[ptr[void]]:
|
|
1160
|
+
waiter(unsafe: waiter_frame)
|
|
1161
|
+
return
|
|
1162
|
+
|
|
1163
|
+
if unsafe: read(state).released:
|
|
1164
|
+
write_cleanup_and_release(state)
|
|
1165
|
+
|
|
1166
|
+
|
|
1167
|
+
function write_callback(req: ptr[NativeWriteRequest], status_code: int) -> void:
|
|
1168
|
+
let state_raw = libuv.req_get_data(write_req_as_base(req)) else:
|
|
1169
|
+
unsafe: heap.release_bytes(ptr[void]<-req)
|
|
1170
|
+
return
|
|
1171
|
+
|
|
1172
|
+
let state = unsafe: ptr[WriteState]<-state_raw
|
|
1173
|
+
let written = unsafe: read(state).data.len
|
|
1174
|
+
unsafe:
|
|
1175
|
+
heap.release_bytes(ptr[void]<-req)
|
|
1176
|
+
read(state).req = null
|
|
1177
|
+
|
|
1178
|
+
if read(state).buffers != null[ptr[NativeBuffer]]:
|
|
1179
|
+
heap.release(read(state).buffers)
|
|
1180
|
+
read(state).buffers = null
|
|
1181
|
+
|
|
1182
|
+
var payload = read(state).data
|
|
1183
|
+
payload.release()
|
|
1184
|
+
read(state).data = bytes.Bytes.empty()
|
|
1185
|
+
|
|
1186
|
+
if status_code != 0:
|
|
1187
|
+
finish_write(state, Result[ptr_uint, Error].failure(error= libuv_error(status_code)), status_code, true)
|
|
1188
|
+
return
|
|
1189
|
+
|
|
1190
|
+
finish_write(state, Result[ptr_uint, Error].success(value= written), 0, false)
|
|
1191
|
+
|
|
1192
|
+
|
|
1193
|
+
function write_on_impl(handle: ptr[NativeTcpHandle]?, content: span[ubyte]) -> Task[Result[ptr_uint, Error]]:
|
|
1194
|
+
let state = heap.must_alloc_zeroed[WriteState](1)
|
|
1195
|
+
unsafe:
|
|
1196
|
+
read(state).ready = false
|
|
1197
|
+
read(state).status_code = 0
|
|
1198
|
+
read(state).result = Result[ptr_uint, Error].success(value= 0)
|
|
1199
|
+
read(state).result_owned = false
|
|
1200
|
+
read(state).waiter_frame = null
|
|
1201
|
+
read(state).waiter = noop_waiter
|
|
1202
|
+
read(state).waiter_registered = false
|
|
1203
|
+
read(state).req = null
|
|
1204
|
+
read(state).buffers = null
|
|
1205
|
+
read(state).data = bytes.Bytes.empty()
|
|
1206
|
+
read(state).released = false
|
|
1207
|
+
|
|
1208
|
+
let live_handle = handle else:
|
|
1209
|
+
finish_write(state, Result[ptr_uint, Error].failure(error= net_error("tcp stream is released")), -1, true)
|
|
1210
|
+
return write_task(state)
|
|
1211
|
+
|
|
1212
|
+
if libuv.is_closing(tcp_as_handle(live_handle)) != 0:
|
|
1213
|
+
finish_write(state, Result[ptr_uint, Error].failure(error= net_error("tcp stream is closing")), -1, true)
|
|
1214
|
+
return write_task(state)
|
|
1215
|
+
|
|
1216
|
+
if content.len == 0:
|
|
1217
|
+
finish_write(state, Result[ptr_uint, Error].success(value= 0), 0, false)
|
|
1218
|
+
return write_task(state)
|
|
1219
|
+
|
|
1220
|
+
let copied = bytes.Bytes.copy(content)
|
|
1221
|
+
let copied_data = copied.data else:
|
|
1222
|
+
finish_write(state, Result[ptr_uint, Error].failure(error= net_error("tcp write missing storage")), -1, true)
|
|
1223
|
+
return write_task(state)
|
|
1224
|
+
|
|
1225
|
+
let req = alloc_write_request()
|
|
1226
|
+
let buffers = heap.must_alloc_zeroed[NativeBuffer](1)
|
|
1227
|
+
unsafe:
|
|
1228
|
+
read(state).req = req
|
|
1229
|
+
read(state).buffers = buffers
|
|
1230
|
+
read(state).data = copied
|
|
1231
|
+
read(buffers) = libuv.buf_init(ptr[char]<-copied_data, uint<-copied.len)
|
|
1232
|
+
libuv.req_set_data(write_req_as_base(req), ptr[void]<-state)
|
|
1233
|
+
|
|
1234
|
+
let queue_status = libuv.write(req, tcp_as_stream(live_handle), buffers, 1, write_callback)
|
|
1235
|
+
if queue_status != 0:
|
|
1236
|
+
unsafe:
|
|
1237
|
+
heap.release_bytes(ptr[void]<-req)
|
|
1238
|
+
read(state).req = null
|
|
1239
|
+
heap.release(buffers)
|
|
1240
|
+
read(state).buffers = null
|
|
1241
|
+
var payload = read(state).data
|
|
1242
|
+
payload.release()
|
|
1243
|
+
read(state).data = bytes.Bytes.empty()
|
|
1244
|
+
finish_write(state, Result[ptr_uint, Error].failure(error= libuv_error(queue_status)), queue_status, true)
|
|
1245
|
+
return write_task(state)
|
|
1246
|
+
|
|
1247
|
+
return write_task(state)
|
|
1248
|
+
|
|
1249
|
+
|
|
1250
|
+
function stream_read_ready(frame: ptr[void]) -> bool:
|
|
1251
|
+
return unsafe: read(stream_read_state(frame)).ready
|
|
1252
|
+
|
|
1253
|
+
|
|
1254
|
+
function stream_read_set_waiter(
|
|
1255
|
+
frame: ptr[void],
|
|
1256
|
+
waiter_frame: ptr[void],
|
|
1257
|
+
waiter: fn(frame: ptr[void]) -> void
|
|
1258
|
+
) -> void:
|
|
1259
|
+
let state = stream_read_state(frame)
|
|
1260
|
+
unsafe:
|
|
1261
|
+
if read(state).ready:
|
|
1262
|
+
waiter(waiter_frame)
|
|
1263
|
+
return
|
|
1264
|
+
|
|
1265
|
+
read(state).waiter_frame = waiter_frame
|
|
1266
|
+
read(state).waiter = waiter
|
|
1267
|
+
read(state).waiter_registered = true
|
|
1268
|
+
|
|
1269
|
+
|
|
1270
|
+
function stream_read_reset_buffer(state: ptr[ReadState]) -> void:
|
|
1271
|
+
let buffer = unsafe: read(state).buffer
|
|
1272
|
+
if buffer != null:
|
|
1273
|
+
heap.release(buffer)
|
|
1274
|
+
|
|
1275
|
+
unsafe:
|
|
1276
|
+
read(state).buffer = null
|
|
1277
|
+
read(state).received_bytes = 0
|
|
1278
|
+
|
|
1279
|
+
|
|
1280
|
+
function stream_read_take_payload(state: ptr[ReadState]) -> bytes.Bytes:
|
|
1281
|
+
let received_bytes = unsafe: read(state).received_bytes
|
|
1282
|
+
if received_bytes == 0:
|
|
1283
|
+
stream_read_reset_buffer(state)
|
|
1284
|
+
return bytes.Bytes.empty()
|
|
1285
|
+
|
|
1286
|
+
let buffer = unsafe: read(state).buffer else:
|
|
1287
|
+
fatal(c"std.net tcp read buffer missing storage")
|
|
1288
|
+
|
|
1289
|
+
unsafe:
|
|
1290
|
+
read(state).buffer = null
|
|
1291
|
+
read(state).received_bytes = 0
|
|
1292
|
+
return bytes.Bytes(data = buffer, len = received_bytes)
|
|
1293
|
+
|
|
1294
|
+
|
|
1295
|
+
function stop_stream_read(
|
|
1296
|
+
stream: ptr[TcpStreamState],
|
|
1297
|
+
state: ptr[ReadState],
|
|
1298
|
+
stream_handle: ptr[NativeStreamHandle]
|
|
1299
|
+
) -> void:
|
|
1300
|
+
unsafe:
|
|
1301
|
+
if read(stream).read_state == state:
|
|
1302
|
+
read(stream).read_state = null
|
|
1303
|
+
read(state).stream = null
|
|
1304
|
+
|
|
1305
|
+
libuv.read_stop(stream_handle)
|
|
1306
|
+
|
|
1307
|
+
|
|
1308
|
+
function stream_read_cleanup_and_release(state: ptr[ReadState]) -> void:
|
|
1309
|
+
unsafe:
|
|
1310
|
+
if read(state).buffer != null:
|
|
1311
|
+
heap.release(read(state).buffer)
|
|
1312
|
+
read(state).buffer = null
|
|
1313
|
+
read(state).received_bytes = 0
|
|
1314
|
+
|
|
1315
|
+
if read(state).result_owned:
|
|
1316
|
+
let result_value = read(state).result
|
|
1317
|
+
match result_value:
|
|
1318
|
+
Result.success as payload:
|
|
1319
|
+
payload.value.release()
|
|
1320
|
+
Result.failure as payload:
|
|
1321
|
+
payload.error.release()
|
|
1322
|
+
read(state).result_owned = false
|
|
1323
|
+
|
|
1324
|
+
heap.release(state)
|
|
1325
|
+
|
|
1326
|
+
|
|
1327
|
+
function stream_read_release(frame: ptr[void]) -> void:
|
|
1328
|
+
let state = stream_read_state(frame)
|
|
1329
|
+
if unsafe: read(state).ready:
|
|
1330
|
+
stream_read_cleanup_and_release(state)
|
|
1331
|
+
return
|
|
1332
|
+
|
|
1333
|
+
unsafe: read(state).released = true
|
|
1334
|
+
|
|
1335
|
+
let stream = unsafe: read(state).stream
|
|
1336
|
+
if stream != null[ptr[TcpStreamState]]:
|
|
1337
|
+
let live_stream = unsafe: stream
|
|
1338
|
+
let handle = unsafe: read(live_stream).handle
|
|
1339
|
+
unsafe:
|
|
1340
|
+
if read(live_stream).read_state == state:
|
|
1341
|
+
read(live_stream).read_state = null
|
|
1342
|
+
read(state).stream = null
|
|
1343
|
+
|
|
1344
|
+
if handle != null[ptr[NativeTcpHandle]]:
|
|
1345
|
+
libuv.read_stop(tcp_as_stream(unsafe: handle))
|
|
1346
|
+
|
|
1347
|
+
finish_stream_read(state, Result[bytes.Bytes, Error].failure(error= net_error("tcp read released")), -1)
|
|
1348
|
+
|
|
1349
|
+
|
|
1350
|
+
function stream_read_take_result(frame: ptr[void]) -> Result[bytes.Bytes, Error]:
|
|
1351
|
+
let state = stream_read_state(frame)
|
|
1352
|
+
let result_value = unsafe: read(state).result
|
|
1353
|
+
unsafe: read(state).result_owned = false
|
|
1354
|
+
return result_value
|
|
1355
|
+
|
|
1356
|
+
|
|
1357
|
+
function stream_read_task(state: ptr[ReadState]) -> Task[Result[bytes.Bytes, Error]]:
|
|
1358
|
+
return unsafe: Task[Result[bytes.Bytes, Error]](
|
|
1359
|
+
frame = ptr[void]<-state,
|
|
1360
|
+
ready = stream_read_ready,
|
|
1361
|
+
set_waiter = stream_read_set_waiter,
|
|
1362
|
+
release = stream_read_release,
|
|
1363
|
+
take_result = stream_read_take_result
|
|
1364
|
+
)
|
|
1365
|
+
|
|
1366
|
+
|
|
1367
|
+
function finish_stream_read(state: ptr[ReadState], result_value: Result[bytes.Bytes, Error], status_code: int) -> void:
|
|
1368
|
+
var waiter: fn(frame: ptr[void]) -> void = noop_waiter
|
|
1369
|
+
var waiter_frame: ptr[void]? = null
|
|
1370
|
+
var notify = false
|
|
1371
|
+
|
|
1372
|
+
unsafe:
|
|
1373
|
+
read(state).result = result_value
|
|
1374
|
+
read(state).result_owned = true
|
|
1375
|
+
read(state).status_code = status_code
|
|
1376
|
+
read(state).ready = true
|
|
1377
|
+
if read(state).waiter_registered:
|
|
1378
|
+
waiter = read(state).waiter
|
|
1379
|
+
waiter_frame = read(state).waiter_frame
|
|
1380
|
+
read(state).waiter_registered = false
|
|
1381
|
+
notify = true
|
|
1382
|
+
|
|
1383
|
+
if notify and waiter_frame != null[ptr[void]]:
|
|
1384
|
+
waiter(unsafe: waiter_frame)
|
|
1385
|
+
return
|
|
1386
|
+
|
|
1387
|
+
if unsafe: read(state).released:
|
|
1388
|
+
stream_read_cleanup_and_release(state)
|
|
1389
|
+
|
|
1390
|
+
|
|
1391
|
+
function stream_read_alloc_callback(
|
|
1392
|
+
handle: ptr[NativeHandle],
|
|
1393
|
+
suggested_size: ptr_uint,
|
|
1394
|
+
buf: ptr[NativeBuffer]
|
|
1395
|
+
) -> void:
|
|
1396
|
+
let state_raw = libuv.handle_get_data(handle) else:
|
|
1397
|
+
let storage = unsafe: ptr[char]<-heap.must_alloc_zeroed_bytes(1, 1)
|
|
1398
|
+
unsafe: read(buf) = libuv.buf_init(storage, 0)
|
|
1399
|
+
return
|
|
1400
|
+
|
|
1401
|
+
let stream = unsafe: ptr[TcpStreamState]<-state_raw
|
|
1402
|
+
let pending_read = unsafe: read(stream).read_state
|
|
1403
|
+
if pending_read == null[ptr[ReadState]]:
|
|
1404
|
+
let storage = unsafe: ptr[char]<-heap.must_alloc_zeroed_bytes(1, 1)
|
|
1405
|
+
unsafe: read(buf) = libuv.buf_init(storage, 0)
|
|
1406
|
+
return
|
|
1407
|
+
|
|
1408
|
+
let state = unsafe: pending_read
|
|
1409
|
+
var capacity = suggested_size
|
|
1410
|
+
let remaining = unsafe: read(state).max_bytes - read(state).received_bytes
|
|
1411
|
+
if remaining < capacity:
|
|
1412
|
+
capacity = remaining
|
|
1413
|
+
|
|
1414
|
+
if capacity == 0:
|
|
1415
|
+
capacity = 1
|
|
1416
|
+
|
|
1417
|
+
let storage = unsafe: ptr[char]<-heap.must_alloc_zeroed_bytes(1, capacity)
|
|
1418
|
+
unsafe: read(buf) = libuv.buf_init(storage, uint<-capacity)
|
|
1419
|
+
|
|
1420
|
+
|
|
1421
|
+
function stream_read_callback(
|
|
1422
|
+
stream_handle: ptr[NativeStreamHandle],
|
|
1423
|
+
nread: ptr_int,
|
|
1424
|
+
buf: const_ptr[NativeBuffer]
|
|
1425
|
+
) -> void:
|
|
1426
|
+
let raw_buffer = unsafe: read(buf)
|
|
1427
|
+
|
|
1428
|
+
let state_raw = libuv.handle_get_data(stream_as_handle(stream_handle)) else:
|
|
1429
|
+
release_uv_buffer(raw_buffer)
|
|
1430
|
+
return
|
|
1431
|
+
|
|
1432
|
+
let stream = unsafe: ptr[TcpStreamState]<-state_raw
|
|
1433
|
+
let pending_read = unsafe: read(stream).read_state
|
|
1434
|
+
if pending_read == null[ptr[ReadState]]:
|
|
1435
|
+
release_uv_buffer(raw_buffer)
|
|
1436
|
+
return
|
|
1437
|
+
|
|
1438
|
+
let state = unsafe: pending_read
|
|
1439
|
+
if nread == 0:
|
|
1440
|
+
release_uv_buffer(raw_buffer)
|
|
1441
|
+
return
|
|
1442
|
+
|
|
1443
|
+
if nread < 0:
|
|
1444
|
+
release_uv_buffer(raw_buffer)
|
|
1445
|
+
stop_stream_read(stream, state, stream_handle)
|
|
1446
|
+
if nread == ptr_int<-libuv._EOF:
|
|
1447
|
+
let exact = unsafe: read(state).exact
|
|
1448
|
+
let total_received = unsafe: read(state).received_bytes
|
|
1449
|
+
let max_bytes = unsafe: read(state).max_bytes
|
|
1450
|
+
if exact and total_received < max_bytes:
|
|
1451
|
+
stream_read_reset_buffer(state)
|
|
1452
|
+
finish_stream_read(
|
|
1453
|
+
state,
|
|
1454
|
+
Result[
|
|
1455
|
+
bytes.Bytes,
|
|
1456
|
+
Error
|
|
1457
|
+
].failure(error= net_error("tcp stream ended before requested bytes were read")),
|
|
1458
|
+
int<-nread
|
|
1459
|
+
)
|
|
1460
|
+
return
|
|
1461
|
+
|
|
1462
|
+
finish_stream_read(state, Result[bytes.Bytes, Error].success(value= stream_read_take_payload(state)), 0)
|
|
1463
|
+
return
|
|
1464
|
+
|
|
1465
|
+
stream_read_reset_buffer(state)
|
|
1466
|
+
finish_stream_read(state, Result[bytes.Bytes, Error].failure(error= libuv_error(int<-nread)), int<-nread)
|
|
1467
|
+
return
|
|
1468
|
+
|
|
1469
|
+
let destination = unsafe: read(state).buffer else:
|
|
1470
|
+
release_uv_buffer(raw_buffer)
|
|
1471
|
+
stop_stream_read(stream, state, stream_handle)
|
|
1472
|
+
finish_stream_read(
|
|
1473
|
+
state,
|
|
1474
|
+
Result[bytes.Bytes, Error].failure(error= net_error("tcp read buffer missing storage")),
|
|
1475
|
+
-1
|
|
1476
|
+
)
|
|
1477
|
+
return
|
|
1478
|
+
|
|
1479
|
+
let chunk_len = ptr_uint<-nread
|
|
1480
|
+
let received_bytes = unsafe: read(state).received_bytes
|
|
1481
|
+
unsafe:
|
|
1482
|
+
heap.copy_bytes(destination + received_bytes, ptr[ubyte]<-raw_buffer.base, chunk_len)
|
|
1483
|
+
read(state).received_bytes = received_bytes + chunk_len
|
|
1484
|
+
|
|
1485
|
+
release_uv_buffer(raw_buffer)
|
|
1486
|
+
|
|
1487
|
+
let exact = unsafe: read(state).exact
|
|
1488
|
+
let total_received = unsafe: read(state).received_bytes
|
|
1489
|
+
let max_bytes = unsafe: read(state).max_bytes
|
|
1490
|
+
if (not exact) or total_received == max_bytes:
|
|
1491
|
+
stop_stream_read(stream, state, stream_handle)
|
|
1492
|
+
finish_stream_read(state, Result[bytes.Bytes, Error].success(value= stream_read_take_payload(state)), 0)
|
|
1493
|
+
|
|
1494
|
+
|
|
1495
|
+
function read_impl(handle: ptr[NativeTcpHandle]?, max_bytes: ptr_uint, exact: bool) -> Task[Result[bytes.Bytes, Error]]:
|
|
1496
|
+
let state = heap.must_alloc_zeroed[ReadState](1)
|
|
1497
|
+
unsafe:
|
|
1498
|
+
read(state).ready = false
|
|
1499
|
+
read(state).status_code = 0
|
|
1500
|
+
read(state).result = Result[bytes.Bytes, Error].success(value= bytes.Bytes.empty())
|
|
1501
|
+
read(state).result_owned = false
|
|
1502
|
+
read(state).waiter_frame = null
|
|
1503
|
+
read(state).waiter = noop_waiter
|
|
1504
|
+
read(state).waiter_registered = false
|
|
1505
|
+
read(state).stream = null
|
|
1506
|
+
read(state).max_bytes = max_bytes
|
|
1507
|
+
read(state).buffer = null
|
|
1508
|
+
read(state).received_bytes = 0
|
|
1509
|
+
read(state).exact = exact
|
|
1510
|
+
read(state).released = false
|
|
1511
|
+
|
|
1512
|
+
if max_bytes == 0:
|
|
1513
|
+
finish_stream_read(
|
|
1514
|
+
state,
|
|
1515
|
+
Result[bytes.Bytes, Error].failure(error= net_error("tcp read requires max_bytes > 0")),
|
|
1516
|
+
-1
|
|
1517
|
+
)
|
|
1518
|
+
return stream_read_task(state)
|
|
1519
|
+
|
|
1520
|
+
let live_handle = handle else:
|
|
1521
|
+
finish_stream_read(state, Result[bytes.Bytes, Error].failure(error= net_error("tcp stream is released")), -1)
|
|
1522
|
+
return stream_read_task(state)
|
|
1523
|
+
|
|
1524
|
+
if libuv.is_closing(tcp_as_handle(live_handle)) != 0:
|
|
1525
|
+
finish_stream_read(state, Result[bytes.Bytes, Error].failure(error= net_error("tcp stream is closing")), -1)
|
|
1526
|
+
return stream_read_task(state)
|
|
1527
|
+
|
|
1528
|
+
let stream_raw = libuv.handle_get_data(tcp_as_handle(live_handle)) else:
|
|
1529
|
+
finish_stream_read(
|
|
1530
|
+
state,
|
|
1531
|
+
Result[bytes.Bytes, Error].failure(error= net_error("tcp stream state is unavailable")),
|
|
1532
|
+
-1
|
|
1533
|
+
)
|
|
1534
|
+
return stream_read_task(state)
|
|
1535
|
+
|
|
1536
|
+
let stream = unsafe: ptr[TcpStreamState]<-stream_raw
|
|
1537
|
+
if unsafe: read(stream).read_state != null[ptr[ReadState]]:
|
|
1538
|
+
finish_stream_read(
|
|
1539
|
+
state,
|
|
1540
|
+
Result[bytes.Bytes, Error].failure(error= net_error("tcp stream already has a pending read")),
|
|
1541
|
+
-1
|
|
1542
|
+
)
|
|
1543
|
+
return stream_read_task(state)
|
|
1544
|
+
|
|
1545
|
+
let buffer = heap.must_alloc[ubyte](max_bytes)
|
|
1546
|
+
unsafe:
|
|
1547
|
+
read(state).buffer = buffer
|
|
1548
|
+
read(state).stream = stream
|
|
1549
|
+
read(stream).read_state = state
|
|
1550
|
+
|
|
1551
|
+
let start_status = libuv.read_start(tcp_as_stream(live_handle), stream_read_alloc_callback, stream_read_callback)
|
|
1552
|
+
if start_status != 0:
|
|
1553
|
+
unsafe:
|
|
1554
|
+
read(stream).read_state = null
|
|
1555
|
+
read(state).stream = null
|
|
1556
|
+
finish_stream_read(state, Result[bytes.Bytes, Error].failure(error= libuv_error(start_status)), start_status)
|
|
1557
|
+
return stream_read_task(state)
|
|
1558
|
+
|
|
1559
|
+
return stream_read_task(state)
|
|
1560
|
+
|
|
1561
|
+
|
|
1562
|
+
function read_once_impl(handle: ptr[NativeTcpHandle]?, max_bytes: ptr_uint) -> Task[Result[bytes.Bytes, Error]]:
|
|
1563
|
+
return read_impl(handle, max_bytes, false)
|
|
1564
|
+
|
|
1565
|
+
|
|
1566
|
+
function read_exactly_impl(handle: ptr[NativeTcpHandle]?, byte_count: ptr_uint) -> Task[Result[bytes.Bytes, Error]]:
|
|
1567
|
+
return read_impl(handle, byte_count, true)
|
|
1568
|
+
|
|
1569
|
+
|
|
1570
|
+
function shutdown_ready(frame: ptr[void]) -> bool:
|
|
1571
|
+
return unsafe: read(shutdown_state(frame)).ready
|
|
1572
|
+
|
|
1573
|
+
|
|
1574
|
+
function shutdown_set_waiter(frame: ptr[void], waiter_frame: ptr[void], waiter: fn(frame: ptr[void]) -> void) -> void:
|
|
1575
|
+
let state = shutdown_state(frame)
|
|
1576
|
+
unsafe:
|
|
1577
|
+
if read(state).ready:
|
|
1578
|
+
waiter(waiter_frame)
|
|
1579
|
+
return
|
|
1580
|
+
|
|
1581
|
+
read(state).waiter_frame = waiter_frame
|
|
1582
|
+
read(state).waiter = waiter
|
|
1583
|
+
read(state).waiter_registered = true
|
|
1584
|
+
|
|
1585
|
+
|
|
1586
|
+
function shutdown_cleanup_and_release(state: ptr[ShutdownState]) -> void:
|
|
1587
|
+
unsafe:
|
|
1588
|
+
if read(state).req != null[ptr[NativeShutdownRequest]]:
|
|
1589
|
+
heap.release_bytes(ptr[void]<-read(state).req)
|
|
1590
|
+
read(state).req = null
|
|
1591
|
+
|
|
1592
|
+
if read(state).result_owned:
|
|
1593
|
+
let result_value = read(state).result
|
|
1594
|
+
match result_value:
|
|
1595
|
+
Result.success as payload:
|
|
1596
|
+
payload.value
|
|
1597
|
+
Result.failure as payload:
|
|
1598
|
+
payload.error.release()
|
|
1599
|
+
read(state).result_owned = false
|
|
1600
|
+
|
|
1601
|
+
heap.release(state)
|
|
1602
|
+
|
|
1603
|
+
|
|
1604
|
+
function shutdown_release(frame: ptr[void]) -> void:
|
|
1605
|
+
let state = shutdown_state(frame)
|
|
1606
|
+
if unsafe: read(state).ready:
|
|
1607
|
+
shutdown_cleanup_and_release(state)
|
|
1608
|
+
return
|
|
1609
|
+
|
|
1610
|
+
unsafe: read(state).released = true
|
|
1611
|
+
|
|
1612
|
+
|
|
1613
|
+
function shutdown_take_result(frame: ptr[void]) -> Result[bool, Error]:
|
|
1614
|
+
let state = shutdown_state(frame)
|
|
1615
|
+
let result_value = unsafe: read(state).result
|
|
1616
|
+
unsafe: read(state).result_owned = false
|
|
1617
|
+
return result_value
|
|
1618
|
+
|
|
1619
|
+
|
|
1620
|
+
function shutdown_task(state: ptr[ShutdownState]) -> Task[Result[bool, Error]]:
|
|
1621
|
+
return unsafe: Task[Result[bool, Error]](
|
|
1622
|
+
frame = ptr[void]<-state,
|
|
1623
|
+
ready = shutdown_ready,
|
|
1624
|
+
set_waiter = shutdown_set_waiter,
|
|
1625
|
+
release = shutdown_release,
|
|
1626
|
+
take_result = shutdown_take_result
|
|
1627
|
+
)
|
|
1628
|
+
|
|
1629
|
+
|
|
1630
|
+
function finish_shutdown(
|
|
1631
|
+
state: ptr[ShutdownState],
|
|
1632
|
+
result_value: Result[bool, Error],
|
|
1633
|
+
status_code: int,
|
|
1634
|
+
owns_error: bool
|
|
1635
|
+
) -> void:
|
|
1636
|
+
var waiter: fn(frame: ptr[void]) -> void = noop_waiter
|
|
1637
|
+
var waiter_frame: ptr[void]? = null
|
|
1638
|
+
var notify = false
|
|
1639
|
+
|
|
1640
|
+
unsafe:
|
|
1641
|
+
read(state).result = result_value
|
|
1642
|
+
read(state).result_owned = owns_error
|
|
1643
|
+
read(state).status_code = status_code
|
|
1644
|
+
read(state).ready = true
|
|
1645
|
+
if read(state).waiter_registered:
|
|
1646
|
+
waiter = read(state).waiter
|
|
1647
|
+
waiter_frame = read(state).waiter_frame
|
|
1648
|
+
read(state).waiter_registered = false
|
|
1649
|
+
notify = true
|
|
1650
|
+
|
|
1651
|
+
if notify and waiter_frame != null[ptr[void]]:
|
|
1652
|
+
waiter(unsafe: waiter_frame)
|
|
1653
|
+
return
|
|
1654
|
+
|
|
1655
|
+
if unsafe: read(state).released:
|
|
1656
|
+
shutdown_cleanup_and_release(state)
|
|
1657
|
+
|
|
1658
|
+
|
|
1659
|
+
function shutdown_callback(req: ptr[NativeShutdownRequest], status_code: int) -> void:
|
|
1660
|
+
let state_raw = libuv.req_get_data(shutdown_req_as_base(req)) else:
|
|
1661
|
+
unsafe: heap.release_bytes(ptr[void]<-req)
|
|
1662
|
+
return
|
|
1663
|
+
|
|
1664
|
+
let state = unsafe: ptr[ShutdownState]<-state_raw
|
|
1665
|
+
unsafe:
|
|
1666
|
+
heap.release_bytes(ptr[void]<-req)
|
|
1667
|
+
read(state).req = null
|
|
1668
|
+
|
|
1669
|
+
if status_code != 0:
|
|
1670
|
+
finish_shutdown(state, Result[bool, Error].failure(error= libuv_error(status_code)), status_code, true)
|
|
1671
|
+
return
|
|
1672
|
+
|
|
1673
|
+
finish_shutdown(state, Result[bool, Error].success(value= true), 0, false)
|
|
1674
|
+
|
|
1675
|
+
|
|
1676
|
+
function shutdown_impl(handle: ptr[NativeTcpHandle]?) -> Task[Result[bool, Error]]:
|
|
1677
|
+
let state = heap.must_alloc_zeroed[ShutdownState](1)
|
|
1678
|
+
unsafe:
|
|
1679
|
+
read(state).ready = false
|
|
1680
|
+
read(state).status_code = 0
|
|
1681
|
+
read(state).result = Result[bool, Error].success(value= false)
|
|
1682
|
+
read(state).result_owned = false
|
|
1683
|
+
read(state).waiter_frame = null
|
|
1684
|
+
read(state).waiter = noop_waiter
|
|
1685
|
+
read(state).waiter_registered = false
|
|
1686
|
+
read(state).req = null
|
|
1687
|
+
read(state).released = false
|
|
1688
|
+
|
|
1689
|
+
let live_handle = handle else:
|
|
1690
|
+
finish_shutdown(state, Result[bool, Error].failure(error= net_error("tcp stream is released")), -1, true)
|
|
1691
|
+
return shutdown_task(state)
|
|
1692
|
+
|
|
1693
|
+
if libuv.is_closing(tcp_as_handle(live_handle)) != 0:
|
|
1694
|
+
finish_shutdown(state, Result[bool, Error].failure(error= net_error("tcp stream is closing")), -1, true)
|
|
1695
|
+
return shutdown_task(state)
|
|
1696
|
+
|
|
1697
|
+
let req = alloc_shutdown_request()
|
|
1698
|
+
unsafe:
|
|
1699
|
+
read(state).req = req
|
|
1700
|
+
libuv.req_set_data(shutdown_req_as_base(req), ptr[void]<-state)
|
|
1701
|
+
|
|
1702
|
+
let queue_status = libuv.shutdown(req, tcp_as_stream(live_handle), shutdown_callback)
|
|
1703
|
+
if queue_status != 0:
|
|
1704
|
+
unsafe:
|
|
1705
|
+
heap.release_bytes(ptr[void]<-req)
|
|
1706
|
+
read(state).req = null
|
|
1707
|
+
finish_shutdown(state, Result[bool, Error].failure(error= libuv_error(queue_status)), queue_status, true)
|
|
1708
|
+
return shutdown_task(state)
|
|
1709
|
+
|
|
1710
|
+
return shutdown_task(state)
|
|
1711
|
+
|
|
1712
|
+
|
|
1713
|
+
function udp_socket_close_callback(handle: ptr[NativeHandle]) -> void:
|
|
1714
|
+
let state_raw = libuv.handle_get_data(handle) else:
|
|
1715
|
+
unsafe: heap.release_bytes(ptr[void]<-handle_as_udp(handle))
|
|
1716
|
+
return
|
|
1717
|
+
|
|
1718
|
+
let socket = unsafe: ptr[UdpSocketState]<-state_raw
|
|
1719
|
+
let pending_receive = unsafe: read(socket).receive_state
|
|
1720
|
+
if pending_receive != null[ptr[UdpReceiveState]]:
|
|
1721
|
+
unsafe:
|
|
1722
|
+
read(socket).receive_state = null
|
|
1723
|
+
read(pending_receive).socket = null
|
|
1724
|
+
finish_udp_receive(
|
|
1725
|
+
unsafe: pending_receive,
|
|
1726
|
+
Result[UdpDatagram, Error].failure(error= net_error("udp socket closed")),
|
|
1727
|
+
-1
|
|
1728
|
+
)
|
|
1729
|
+
|
|
1730
|
+
unsafe:
|
|
1731
|
+
heap.release_bytes(ptr[void]<-handle_as_udp(handle))
|
|
1732
|
+
read(socket).handle = null
|
|
1733
|
+
heap.release(socket)
|
|
1734
|
+
|
|
1735
|
+
|
|
1736
|
+
function close_udp_socket_handle(handle: ptr[NativeUdpHandle]) -> void:
|
|
1737
|
+
if libuv.is_closing(udp_as_handle(handle)) != 0:
|
|
1738
|
+
return
|
|
1739
|
+
|
|
1740
|
+
let state_raw = libuv.handle_get_data(udp_as_handle(handle))
|
|
1741
|
+
if state_raw == null[ptr[void]]:
|
|
1742
|
+
close_raw_udp_handle(handle)
|
|
1743
|
+
return
|
|
1744
|
+
|
|
1745
|
+
libuv.close(udp_as_handle(handle), udp_socket_close_callback)
|
|
1746
|
+
|
|
1747
|
+
|
|
1748
|
+
function udp_send_ready(frame: ptr[void]) -> bool:
|
|
1749
|
+
return unsafe: read(udp_send_state(frame)).ready
|
|
1750
|
+
|
|
1751
|
+
|
|
1752
|
+
function udp_send_set_waiter(frame: ptr[void], waiter_frame: ptr[void], waiter: fn(frame: ptr[void]) -> void) -> void:
|
|
1753
|
+
let state = udp_send_state(frame)
|
|
1754
|
+
unsafe:
|
|
1755
|
+
if read(state).ready:
|
|
1756
|
+
waiter(waiter_frame)
|
|
1757
|
+
return
|
|
1758
|
+
|
|
1759
|
+
read(state).waiter_frame = waiter_frame
|
|
1760
|
+
read(state).waiter = waiter
|
|
1761
|
+
read(state).waiter_registered = true
|
|
1762
|
+
|
|
1763
|
+
|
|
1764
|
+
function udp_send_cleanup_and_release(state: ptr[UdpSendState]) -> void:
|
|
1765
|
+
unsafe:
|
|
1766
|
+
if read(state).req != null[ptr[NativeUdpSendRequest]]:
|
|
1767
|
+
heap.release_bytes(ptr[void]<-read(state).req)
|
|
1768
|
+
read(state).req = null
|
|
1769
|
+
|
|
1770
|
+
if read(state).buffers != null[ptr[NativeBuffer]]:
|
|
1771
|
+
heap.release(read(state).buffers)
|
|
1772
|
+
read(state).buffers = null
|
|
1773
|
+
|
|
1774
|
+
var stored_data = read(state).data
|
|
1775
|
+
stored_data.release()
|
|
1776
|
+
read(state).data = bytes.Bytes.empty()
|
|
1777
|
+
|
|
1778
|
+
if read(state).destination_owned:
|
|
1779
|
+
var destination = read(state).destination
|
|
1780
|
+
destination.release()
|
|
1781
|
+
read(state).destination_owned = false
|
|
1782
|
+
|
|
1783
|
+
if read(state).result_owned:
|
|
1784
|
+
let result_value = read(state).result
|
|
1785
|
+
match result_value:
|
|
1786
|
+
Result.success as ok_payload:
|
|
1787
|
+
ok_payload.value
|
|
1788
|
+
Result.failure as error_payload:
|
|
1789
|
+
error_payload.error.release()
|
|
1790
|
+
read(state).result_owned = false
|
|
1791
|
+
|
|
1792
|
+
heap.release(state)
|
|
1793
|
+
|
|
1794
|
+
|
|
1795
|
+
function udp_send_release(frame: ptr[void]) -> void:
|
|
1796
|
+
let state = udp_send_state(frame)
|
|
1797
|
+
if unsafe: read(state).ready:
|
|
1798
|
+
udp_send_cleanup_and_release(state)
|
|
1799
|
+
return
|
|
1800
|
+
|
|
1801
|
+
unsafe: read(state).released = true
|
|
1802
|
+
|
|
1803
|
+
|
|
1804
|
+
function udp_send_take_result(frame: ptr[void]) -> Result[ptr_uint, Error]:
|
|
1805
|
+
let state = udp_send_state(frame)
|
|
1806
|
+
let result_value = unsafe: read(state).result
|
|
1807
|
+
unsafe: read(state).result_owned = false
|
|
1808
|
+
return result_value
|
|
1809
|
+
|
|
1810
|
+
|
|
1811
|
+
function udp_send_task(state: ptr[UdpSendState]) -> Task[Result[ptr_uint, Error]]:
|
|
1812
|
+
return unsafe: Task[Result[ptr_uint, Error]](
|
|
1813
|
+
frame = ptr[void]<-state,
|
|
1814
|
+
ready = udp_send_ready,
|
|
1815
|
+
set_waiter = udp_send_set_waiter,
|
|
1816
|
+
release = udp_send_release,
|
|
1817
|
+
take_result = udp_send_take_result
|
|
1818
|
+
)
|
|
1819
|
+
|
|
1820
|
+
|
|
1821
|
+
function finish_udp_send(
|
|
1822
|
+
state: ptr[UdpSendState],
|
|
1823
|
+
result_value: Result[ptr_uint, Error],
|
|
1824
|
+
status_code: int,
|
|
1825
|
+
owns_error: bool
|
|
1826
|
+
) -> void:
|
|
1827
|
+
var waiter: fn(frame: ptr[void]) -> void = noop_waiter
|
|
1828
|
+
var waiter_frame: ptr[void]? = null
|
|
1829
|
+
var notify = false
|
|
1830
|
+
|
|
1831
|
+
unsafe:
|
|
1832
|
+
read(state).result = result_value
|
|
1833
|
+
read(state).result_owned = owns_error
|
|
1834
|
+
read(state).status_code = status_code
|
|
1835
|
+
read(state).ready = true
|
|
1836
|
+
if read(state).waiter_registered:
|
|
1837
|
+
waiter = read(state).waiter
|
|
1838
|
+
waiter_frame = read(state).waiter_frame
|
|
1839
|
+
read(state).waiter_registered = false
|
|
1840
|
+
notify = true
|
|
1841
|
+
|
|
1842
|
+
unsafe:
|
|
1843
|
+
let socket = read(state).socket
|
|
1844
|
+
if socket != null[ptr[UdpSocketState]]:
|
|
1845
|
+
read(state).socket = null
|
|
1846
|
+
read(socket).pending_send_count -= 1
|
|
1847
|
+
if read(socket).closing and read(socket).pending_send_count == 0:
|
|
1848
|
+
let h = read(socket).handle
|
|
1849
|
+
if h != null[ptr[NativeUdpHandle]]:
|
|
1850
|
+
close_udp_socket_handle(h)
|
|
1851
|
+
|
|
1852
|
+
if notify and waiter_frame != null[ptr[void]]:
|
|
1853
|
+
waiter(unsafe: waiter_frame)
|
|
1854
|
+
return
|
|
1855
|
+
|
|
1856
|
+
if unsafe: read(state).released:
|
|
1857
|
+
udp_send_cleanup_and_release(state)
|
|
1858
|
+
|
|
1859
|
+
|
|
1860
|
+
function udp_send_callback(req: ptr[NativeUdpSendRequest], status_code: int) -> void:
|
|
1861
|
+
let state_raw = libuv.req_get_data(udp_send_req_as_base(req)) else:
|
|
1862
|
+
unsafe: heap.release_bytes(ptr[void]<-req)
|
|
1863
|
+
return
|
|
1864
|
+
|
|
1865
|
+
let state = unsafe: ptr[UdpSendState]<-state_raw
|
|
1866
|
+
let sent = unsafe: read(state).data.len
|
|
1867
|
+
unsafe:
|
|
1868
|
+
heap.release_bytes(ptr[void]<-req)
|
|
1869
|
+
read(state).req = null
|
|
1870
|
+
|
|
1871
|
+
if read(state).buffers != null[ptr[NativeBuffer]]:
|
|
1872
|
+
heap.release(read(state).buffers)
|
|
1873
|
+
read(state).buffers = null
|
|
1874
|
+
|
|
1875
|
+
var payload = read(state).data
|
|
1876
|
+
payload.release()
|
|
1877
|
+
read(state).data = bytes.Bytes.empty()
|
|
1878
|
+
|
|
1879
|
+
if read(state).destination_owned:
|
|
1880
|
+
var destination = read(state).destination
|
|
1881
|
+
destination.release()
|
|
1882
|
+
read(state).destination_owned = false
|
|
1883
|
+
|
|
1884
|
+
if status_code != 0:
|
|
1885
|
+
finish_udp_send(state, Result[ptr_uint, Error].failure(error= libuv_error(status_code)), status_code, true)
|
|
1886
|
+
return
|
|
1887
|
+
|
|
1888
|
+
finish_udp_send(state, Result[ptr_uint, Error].success(value= sent), 0, false)
|
|
1889
|
+
|
|
1890
|
+
|
|
1891
|
+
function udp_send_impl(
|
|
1892
|
+
handle: ptr[NativeUdpHandle]?,
|
|
1893
|
+
content: span[ubyte],
|
|
1894
|
+
destination: SocketAddress,
|
|
1895
|
+
use_destination: bool
|
|
1896
|
+
) -> Task[Result[ptr_uint, Error]]:
|
|
1897
|
+
let state = heap.must_alloc_zeroed[UdpSendState](1)
|
|
1898
|
+
unsafe:
|
|
1899
|
+
read(state).ready = false
|
|
1900
|
+
read(state).status_code = 0
|
|
1901
|
+
read(state).result = Result[ptr_uint, Error].success(value= 0)
|
|
1902
|
+
read(state).result_owned = false
|
|
1903
|
+
read(state).waiter_frame = null
|
|
1904
|
+
read(state).waiter = noop_waiter
|
|
1905
|
+
read(state).waiter_registered = false
|
|
1906
|
+
read(state).req = null
|
|
1907
|
+
read(state).buffers = null
|
|
1908
|
+
read(state).data = bytes.Bytes.empty()
|
|
1909
|
+
read(state).destination = zero[SocketAddress]
|
|
1910
|
+
read(state).destination_owned = false
|
|
1911
|
+
read(state).released = false
|
|
1912
|
+
read(state).socket = null
|
|
1913
|
+
|
|
1914
|
+
let live_handle = handle else:
|
|
1915
|
+
finish_udp_send(state, Result[ptr_uint, Error].failure(error= net_error("udp socket is released")), -1, true)
|
|
1916
|
+
return udp_send_task(state)
|
|
1917
|
+
|
|
1918
|
+
if libuv.is_closing(udp_as_handle(live_handle)) != 0:
|
|
1919
|
+
finish_udp_send(state, Result[ptr_uint, Error].failure(error= net_error("udp socket is closing")), -1, true)
|
|
1920
|
+
return udp_send_task(state)
|
|
1921
|
+
|
|
1922
|
+
if content.len == 0:
|
|
1923
|
+
finish_udp_send(state, Result[ptr_uint, Error].success(value= 0), 0, false)
|
|
1924
|
+
return udp_send_task(state)
|
|
1925
|
+
|
|
1926
|
+
if use_destination:
|
|
1927
|
+
match duplicate_socket_address(destination):
|
|
1928
|
+
Result.failure as payload:
|
|
1929
|
+
let error = payload.error
|
|
1930
|
+
finish_udp_send(state, Result[ptr_uint, Error].failure(error= error), error.code, true)
|
|
1931
|
+
return udp_send_task(state)
|
|
1932
|
+
Result.success as payload:
|
|
1933
|
+
unsafe:
|
|
1934
|
+
read(state).destination = payload.value
|
|
1935
|
+
read(state).destination_owned = true
|
|
1936
|
+
|
|
1937
|
+
let copied = bytes.Bytes.copy(content)
|
|
1938
|
+
let copied_data = copied.data else:
|
|
1939
|
+
finish_udp_send(state, Result[ptr_uint, Error].failure(error= net_error("udp send missing storage")), -1, true)
|
|
1940
|
+
return udp_send_task(state)
|
|
1941
|
+
|
|
1942
|
+
var remote_address: const_ptr[NativeSockAddr]? = null[const_ptr[NativeSockAddr]]
|
|
1943
|
+
if use_destination:
|
|
1944
|
+
let destination_storage = unsafe: read(state).destination.storage else:
|
|
1945
|
+
var payload = copied
|
|
1946
|
+
payload.release()
|
|
1947
|
+
finish_udp_send(
|
|
1948
|
+
state,
|
|
1949
|
+
Result[ptr_uint, Error].failure(error= invalid_address_error("socket address is released")),
|
|
1950
|
+
-1,
|
|
1951
|
+
true
|
|
1952
|
+
)
|
|
1953
|
+
return udp_send_task(state)
|
|
1954
|
+
|
|
1955
|
+
remote_address = sockaddr_storage_as_sockaddr(destination_storage)
|
|
1956
|
+
|
|
1957
|
+
let req = alloc_udp_send_request()
|
|
1958
|
+
let buffers = heap.must_alloc_zeroed[NativeBuffer](1)
|
|
1959
|
+
unsafe:
|
|
1960
|
+
read(state).req = req
|
|
1961
|
+
read(state).buffers = buffers
|
|
1962
|
+
read(state).data = copied
|
|
1963
|
+
read(buffers) = libuv.buf_init(ptr[char]<-copied_data, uint<-copied.len)
|
|
1964
|
+
libuv.req_set_data(udp_send_req_as_base(req), ptr[void]<-state)
|
|
1965
|
+
|
|
1966
|
+
let socket_raw = libuv.handle_get_data(udp_as_handle(live_handle))
|
|
1967
|
+
if socket_raw == null[ptr[void]]:
|
|
1968
|
+
unsafe:
|
|
1969
|
+
heap.release_bytes(ptr[void]<-req)
|
|
1970
|
+
read(state).req = null
|
|
1971
|
+
heap.release(buffers)
|
|
1972
|
+
read(state).buffers = null
|
|
1973
|
+
var payload = read(state).data
|
|
1974
|
+
payload.release()
|
|
1975
|
+
read(state).data = bytes.Bytes.empty()
|
|
1976
|
+
if read(state).destination_owned:
|
|
1977
|
+
var target = read(state).destination
|
|
1978
|
+
target.release()
|
|
1979
|
+
read(state).destination_owned = false
|
|
1980
|
+
finish_udp_send(state, Result[ptr_uint, Error].failure(error= net_error("udp socket state is missing")), -1, true)
|
|
1981
|
+
return udp_send_task(state)
|
|
1982
|
+
|
|
1983
|
+
let socket_state = unsafe: ptr[UdpSocketState]<-socket_raw
|
|
1984
|
+
if unsafe: read(socket_state).closing:
|
|
1985
|
+
unsafe:
|
|
1986
|
+
heap.release_bytes(ptr[void]<-req)
|
|
1987
|
+
read(state).req = null
|
|
1988
|
+
heap.release(buffers)
|
|
1989
|
+
read(state).buffers = null
|
|
1990
|
+
var payload = read(state).data
|
|
1991
|
+
payload.release()
|
|
1992
|
+
read(state).data = bytes.Bytes.empty()
|
|
1993
|
+
if read(state).destination_owned:
|
|
1994
|
+
var target = read(state).destination
|
|
1995
|
+
target.release()
|
|
1996
|
+
read(state).destination_owned = false
|
|
1997
|
+
finish_udp_send(state, Result[ptr_uint, Error].failure(error= net_error("udp socket is closing")), -1, true)
|
|
1998
|
+
return udp_send_task(state)
|
|
1999
|
+
|
|
2000
|
+
unsafe:
|
|
2001
|
+
read(socket_state).pending_send_count += 1
|
|
2002
|
+
read(state).socket = socket_state
|
|
2003
|
+
|
|
2004
|
+
let queue_status = libuv.udp_send(req, live_handle, buffers, 1, remote_address, udp_send_callback)
|
|
2005
|
+
if queue_status != 0:
|
|
2006
|
+
unsafe:
|
|
2007
|
+
let sock = read(state).socket
|
|
2008
|
+
if sock != null[ptr[UdpSocketState]]:
|
|
2009
|
+
read(state).socket = null
|
|
2010
|
+
read(sock).pending_send_count -= 1
|
|
2011
|
+
if read(sock).closing and read(sock).pending_send_count == 0:
|
|
2012
|
+
let h = read(sock).handle
|
|
2013
|
+
if h != null[ptr[NativeUdpHandle]]:
|
|
2014
|
+
close_udp_socket_handle(h)
|
|
2015
|
+
|
|
2016
|
+
heap.release_bytes(ptr[void]<-req)
|
|
2017
|
+
read(state).req = null
|
|
2018
|
+
heap.release(buffers)
|
|
2019
|
+
read(state).buffers = null
|
|
2020
|
+
var payload = read(state).data
|
|
2021
|
+
payload.release()
|
|
2022
|
+
read(state).data = bytes.Bytes.empty()
|
|
2023
|
+
if read(state).destination_owned:
|
|
2024
|
+
var target = read(state).destination
|
|
2025
|
+
target.release()
|
|
2026
|
+
read(state).destination_owned = false
|
|
2027
|
+
finish_udp_send(state, Result[ptr_uint, Error].failure(error= libuv_error(queue_status)), queue_status, true)
|
|
2028
|
+
return udp_send_task(state)
|
|
2029
|
+
|
|
2030
|
+
return udp_send_task(state)
|
|
2031
|
+
|
|
2032
|
+
|
|
2033
|
+
function udp_send_to_impl(
|
|
2034
|
+
handle: ptr[NativeUdpHandle]?,
|
|
2035
|
+
content: span[ubyte],
|
|
2036
|
+
destination: SocketAddress
|
|
2037
|
+
) -> Task[Result[ptr_uint, Error]]:
|
|
2038
|
+
return udp_send_impl(handle, content, destination, true)
|
|
2039
|
+
|
|
2040
|
+
|
|
2041
|
+
function udp_send_connected_impl(handle: ptr[NativeUdpHandle]?, content: span[ubyte]) -> Task[Result[ptr_uint, Error]]:
|
|
2042
|
+
return udp_send_impl(handle, content, zero[SocketAddress], false)
|
|
2043
|
+
|
|
2044
|
+
|
|
2045
|
+
function udp_receive_ready(frame: ptr[void]) -> bool:
|
|
2046
|
+
return unsafe: read(udp_receive_state(frame)).ready
|
|
2047
|
+
|
|
2048
|
+
|
|
2049
|
+
function udp_receive_set_waiter(
|
|
2050
|
+
frame: ptr[void],
|
|
2051
|
+
waiter_frame: ptr[void],
|
|
2052
|
+
waiter: fn(frame: ptr[void]) -> void
|
|
2053
|
+
) -> void:
|
|
2054
|
+
let state = udp_receive_state(frame)
|
|
2055
|
+
unsafe:
|
|
2056
|
+
if read(state).ready:
|
|
2057
|
+
waiter(waiter_frame)
|
|
2058
|
+
return
|
|
2059
|
+
|
|
2060
|
+
read(state).waiter_frame = waiter_frame
|
|
2061
|
+
read(state).waiter = waiter
|
|
2062
|
+
read(state).waiter_registered = true
|
|
2063
|
+
|
|
2064
|
+
|
|
2065
|
+
function udp_receive_cleanup_and_release(state: ptr[UdpReceiveState]) -> void:
|
|
2066
|
+
unsafe:
|
|
2067
|
+
if read(state).result_owned:
|
|
2068
|
+
let result_value = read(state).result
|
|
2069
|
+
match result_value:
|
|
2070
|
+
Result.success as payload:
|
|
2071
|
+
var datagram = payload.value
|
|
2072
|
+
datagram.data.release()
|
|
2073
|
+
datagram.source.release()
|
|
2074
|
+
Result.failure as payload:
|
|
2075
|
+
payload.error.release()
|
|
2076
|
+
read(state).result_owned = false
|
|
2077
|
+
|
|
2078
|
+
heap.release(state)
|
|
2079
|
+
|
|
2080
|
+
|
|
2081
|
+
function udp_receive_release(frame: ptr[void]) -> void:
|
|
2082
|
+
let state = udp_receive_state(frame)
|
|
2083
|
+
if unsafe: read(state).ready:
|
|
2084
|
+
let socket = unsafe: read(state).socket
|
|
2085
|
+
if socket != null[ptr[UdpSocketState]]:
|
|
2086
|
+
let live_socket = unsafe: socket
|
|
2087
|
+
if unsafe: read(live_socket).receive_state == state:
|
|
2088
|
+
unsafe: read(live_socket).receive_state = null
|
|
2089
|
+
udp_receive_cleanup_and_release(state)
|
|
2090
|
+
return
|
|
2091
|
+
|
|
2092
|
+
unsafe: read(state).released = true
|
|
2093
|
+
|
|
2094
|
+
let socket = unsafe: read(state).socket
|
|
2095
|
+
if socket != null[ptr[UdpSocketState]]:
|
|
2096
|
+
let live_socket = unsafe: socket
|
|
2097
|
+
let handle = unsafe: read(live_socket).handle
|
|
2098
|
+
unsafe:
|
|
2099
|
+
if read(live_socket).receive_state == state:
|
|
2100
|
+
read(live_socket).receive_state = null
|
|
2101
|
+
read(state).socket = null
|
|
2102
|
+
|
|
2103
|
+
if handle != null[ptr[NativeUdpHandle]]:
|
|
2104
|
+
libuv.udp_recv_stop(unsafe: handle)
|
|
2105
|
+
|
|
2106
|
+
finish_udp_receive(state, Result[UdpDatagram, Error].failure(error= net_error("udp receive released")), -1)
|
|
2107
|
+
|
|
2108
|
+
|
|
2109
|
+
function udp_receive_take_result(frame: ptr[void]) -> Result[UdpDatagram, Error]:
|
|
2110
|
+
let state = udp_receive_state(frame)
|
|
2111
|
+
let result_value = unsafe: read(state).result
|
|
2112
|
+
unsafe: read(state).result_owned = false
|
|
2113
|
+
return result_value
|
|
2114
|
+
|
|
2115
|
+
|
|
2116
|
+
function udp_receive_task(state: ptr[UdpReceiveState]) -> Task[Result[UdpDatagram, Error]]:
|
|
2117
|
+
return unsafe: Task[Result[UdpDatagram, Error]](
|
|
2118
|
+
frame = ptr[void]<-state,
|
|
2119
|
+
ready = udp_receive_ready,
|
|
2120
|
+
set_waiter = udp_receive_set_waiter,
|
|
2121
|
+
release = udp_receive_release,
|
|
2122
|
+
take_result = udp_receive_take_result
|
|
2123
|
+
)
|
|
2124
|
+
|
|
2125
|
+
|
|
2126
|
+
function finish_udp_receive(
|
|
2127
|
+
state: ptr[UdpReceiveState],
|
|
2128
|
+
result_value: Result[UdpDatagram, Error],
|
|
2129
|
+
status_code: int
|
|
2130
|
+
) -> void:
|
|
2131
|
+
var waiter: fn(frame: ptr[void]) -> void = noop_waiter
|
|
2132
|
+
var waiter_frame: ptr[void]? = null
|
|
2133
|
+
var notify = false
|
|
2134
|
+
|
|
2135
|
+
unsafe:
|
|
2136
|
+
read(state).result = result_value
|
|
2137
|
+
read(state).result_owned = true
|
|
2138
|
+
read(state).status_code = status_code
|
|
2139
|
+
read(state).ready = true
|
|
2140
|
+
if read(state).waiter_registered:
|
|
2141
|
+
waiter = read(state).waiter
|
|
2142
|
+
waiter_frame = read(state).waiter_frame
|
|
2143
|
+
read(state).waiter_registered = false
|
|
2144
|
+
notify = true
|
|
2145
|
+
|
|
2146
|
+
if notify and waiter_frame != null[ptr[void]]:
|
|
2147
|
+
waiter(unsafe: waiter_frame)
|
|
2148
|
+
return
|
|
2149
|
+
|
|
2150
|
+
if unsafe: read(state).released:
|
|
2151
|
+
udp_receive_cleanup_and_release(state)
|
|
2152
|
+
|
|
2153
|
+
|
|
2154
|
+
function udp_receive_alloc_callback(
|
|
2155
|
+
handle: ptr[NativeHandle],
|
|
2156
|
+
suggested_size: ptr_uint,
|
|
2157
|
+
buf: ptr[NativeBuffer]
|
|
2158
|
+
) -> void:
|
|
2159
|
+
let state_raw = libuv.handle_get_data(handle) else:
|
|
2160
|
+
let storage = unsafe: ptr[char]<-heap.must_alloc_zeroed_bytes(1, 1)
|
|
2161
|
+
unsafe: read(buf) = libuv.buf_init(storage, 0)
|
|
2162
|
+
return
|
|
2163
|
+
|
|
2164
|
+
let socket = unsafe: ptr[UdpSocketState]<-state_raw
|
|
2165
|
+
let pending_receive = unsafe: read(socket).receive_state
|
|
2166
|
+
if pending_receive == null[ptr[UdpReceiveState]]:
|
|
2167
|
+
let storage = unsafe: ptr[char]<-heap.must_alloc_zeroed_bytes(1, 1)
|
|
2168
|
+
unsafe: read(buf) = libuv.buf_init(storage, 0)
|
|
2169
|
+
return
|
|
2170
|
+
|
|
2171
|
+
let state = unsafe: pending_receive
|
|
2172
|
+
var capacity = suggested_size
|
|
2173
|
+
let max_bytes = unsafe: read(state).max_bytes
|
|
2174
|
+
if max_bytes < capacity:
|
|
2175
|
+
capacity = max_bytes
|
|
2176
|
+
|
|
2177
|
+
if capacity == 0:
|
|
2178
|
+
capacity = 1
|
|
2179
|
+
|
|
2180
|
+
let storage = unsafe: ptr[char]<-heap.must_alloc_zeroed_bytes(1, capacity)
|
|
2181
|
+
unsafe: read(buf) = libuv.buf_init(storage, uint<-capacity)
|
|
2182
|
+
|
|
2183
|
+
|
|
2184
|
+
function udp_receive_callback(
|
|
2185
|
+
handle: ptr[NativeUdpHandle],
|
|
2186
|
+
nread: ptr_int,
|
|
2187
|
+
buf: const_ptr[NativeBuffer],
|
|
2188
|
+
addr: const_ptr[NativeSockAddr],
|
|
2189
|
+
flags_: uint
|
|
2190
|
+
) -> void:
|
|
2191
|
+
let raw_buffer = unsafe: read(buf)
|
|
2192
|
+
|
|
2193
|
+
let state_raw = libuv.handle_get_data(udp_as_handle(handle)) else:
|
|
2194
|
+
release_uv_buffer(raw_buffer)
|
|
2195
|
+
return
|
|
2196
|
+
|
|
2197
|
+
let socket = unsafe: ptr[UdpSocketState]<-state_raw
|
|
2198
|
+
let pending_receive = unsafe: read(socket).receive_state
|
|
2199
|
+
if pending_receive == null[ptr[UdpReceiveState]]:
|
|
2200
|
+
release_uv_buffer(raw_buffer)
|
|
2201
|
+
return
|
|
2202
|
+
|
|
2203
|
+
let state = unsafe: pending_receive
|
|
2204
|
+
if nread == 0:
|
|
2205
|
+
release_uv_buffer(raw_buffer)
|
|
2206
|
+
return
|
|
2207
|
+
|
|
2208
|
+
unsafe:
|
|
2209
|
+
read(socket).receive_state = null
|
|
2210
|
+
read(state).socket = null
|
|
2211
|
+
|
|
2212
|
+
libuv.udp_recv_stop(handle)
|
|
2213
|
+
|
|
2214
|
+
if nread < 0:
|
|
2215
|
+
release_uv_buffer(raw_buffer)
|
|
2216
|
+
finish_udp_receive(state, Result[UdpDatagram, Error].failure(error= libuv_error(int<-nread)), int<-nread)
|
|
2217
|
+
return
|
|
2218
|
+
|
|
2219
|
+
if (flags_ & uint<-libuv.uv_udp_flags.UV_UDP_PARTIAL) != 0:
|
|
2220
|
+
release_uv_buffer(raw_buffer)
|
|
2221
|
+
finish_udp_receive(state, Result[UdpDatagram, Error].failure(error= net_error("udp datagram truncated")), -1)
|
|
2222
|
+
return
|
|
2223
|
+
|
|
2224
|
+
let source_result = socket_address_from_unknown_sockaddr(addr)
|
|
2225
|
+
var payload = bytes.Bytes.copy(unsafe: span[ubyte](data = ptr[ubyte]<-raw_buffer.base, len = ptr_uint<-nread))
|
|
2226
|
+
release_uv_buffer(raw_buffer)
|
|
2227
|
+
|
|
2228
|
+
match source_result:
|
|
2229
|
+
Result.failure as payload_error:
|
|
2230
|
+
let error = payload_error.error
|
|
2231
|
+
payload.release()
|
|
2232
|
+
finish_udp_receive(state, Result[UdpDatagram, Error].failure(error= error), error.code)
|
|
2233
|
+
return
|
|
2234
|
+
Result.success as payload_source:
|
|
2235
|
+
finish_udp_receive(
|
|
2236
|
+
state,
|
|
2237
|
+
Result[UdpDatagram, Error].success(value= UdpDatagram(data = payload, source = payload_source.value)),
|
|
2238
|
+
0
|
|
2239
|
+
)
|
|
2240
|
+
return
|
|
2241
|
+
|
|
2242
|
+
|
|
2243
|
+
function recv_from_impl(handle: ptr[NativeUdpHandle]?, max_bytes: ptr_uint) -> Task[Result[UdpDatagram, Error]]:
|
|
2244
|
+
let state = heap.must_alloc_zeroed[UdpReceiveState](1)
|
|
2245
|
+
unsafe:
|
|
2246
|
+
read(state).ready = false
|
|
2247
|
+
read(state).status_code = 0
|
|
2248
|
+
read(state).result = Result[UdpDatagram, Error].success(value= zero[UdpDatagram])
|
|
2249
|
+
read(state).result_owned = false
|
|
2250
|
+
read(state).waiter_frame = null
|
|
2251
|
+
read(state).waiter = noop_waiter
|
|
2252
|
+
read(state).waiter_registered = false
|
|
2253
|
+
read(state).socket = null
|
|
2254
|
+
read(state).max_bytes = max_bytes
|
|
2255
|
+
read(state).released = false
|
|
2256
|
+
|
|
2257
|
+
if max_bytes == 0:
|
|
2258
|
+
finish_udp_receive(
|
|
2259
|
+
state,
|
|
2260
|
+
Result[UdpDatagram, Error].failure(error= net_error("udp receive requires max_bytes > 0")),
|
|
2261
|
+
-1
|
|
2262
|
+
)
|
|
2263
|
+
return udp_receive_task(state)
|
|
2264
|
+
|
|
2265
|
+
let live_handle = handle else:
|
|
2266
|
+
finish_udp_receive(state, Result[UdpDatagram, Error].failure(error= net_error("udp socket is released")), -1)
|
|
2267
|
+
return udp_receive_task(state)
|
|
2268
|
+
|
|
2269
|
+
if libuv.is_closing(udp_as_handle(live_handle)) != 0:
|
|
2270
|
+
finish_udp_receive(state, Result[UdpDatagram, Error].failure(error= net_error("udp socket is closing")), -1)
|
|
2271
|
+
return udp_receive_task(state)
|
|
2272
|
+
|
|
2273
|
+
let socket_raw = libuv.handle_get_data(udp_as_handle(live_handle)) else:
|
|
2274
|
+
finish_udp_receive(
|
|
2275
|
+
state,
|
|
2276
|
+
Result[UdpDatagram, Error].failure(error= net_error("udp socket state is unavailable")),
|
|
2277
|
+
-1
|
|
2278
|
+
)
|
|
2279
|
+
return udp_receive_task(state)
|
|
2280
|
+
|
|
2281
|
+
let socket = unsafe: ptr[UdpSocketState]<-socket_raw
|
|
2282
|
+
if unsafe: read(socket).receive_state != null[ptr[UdpReceiveState]]:
|
|
2283
|
+
finish_udp_receive(
|
|
2284
|
+
state,
|
|
2285
|
+
Result[UdpDatagram, Error].failure(error= net_error("udp socket already has a pending receive")),
|
|
2286
|
+
-1
|
|
2287
|
+
)
|
|
2288
|
+
return udp_receive_task(state)
|
|
2289
|
+
|
|
2290
|
+
unsafe:
|
|
2291
|
+
read(state).socket = socket
|
|
2292
|
+
read(socket).receive_state = state
|
|
2293
|
+
|
|
2294
|
+
let start_status = libuv.udp_recv_start(live_handle, udp_receive_alloc_callback, udp_receive_callback)
|
|
2295
|
+
if start_status != 0:
|
|
2296
|
+
unsafe:
|
|
2297
|
+
read(socket).receive_state = null
|
|
2298
|
+
read(state).socket = null
|
|
2299
|
+
finish_udp_receive(state, Result[UdpDatagram, Error].failure(error= libuv_error(start_status)), start_status)
|
|
2300
|
+
return udp_receive_task(state)
|
|
2301
|
+
|
|
2302
|
+
return udp_receive_task(state)
|
|
2303
|
+
|
|
2304
|
+
|
|
2305
|
+
async function recv_impl(handle: ptr[NativeUdpHandle]?, max_bytes: ptr_uint) -> Result[bytes.Bytes, Error]:
|
|
2306
|
+
let received = await recv_from_impl(handle, max_bytes)
|
|
2307
|
+
match received:
|
|
2308
|
+
Result.failure as payload:
|
|
2309
|
+
return Result[bytes.Bytes, Error].failure(error= payload.error)
|
|
2310
|
+
Result.success as payload:
|
|
2311
|
+
var datagram = payload.value
|
|
2312
|
+
let data = datagram.data
|
|
2313
|
+
datagram.data = bytes.Bytes.empty()
|
|
2314
|
+
datagram.source.release()
|
|
2315
|
+
return Result[bytes.Bytes, Error].success(value= data)
|
|
2316
|
+
|
|
2317
|
+
|
|
2318
|
+
function udp_bind_on_impl(runtime: aio.Runtime, address: SocketAddress) -> Result[UdpSocket, Error]:
|
|
2319
|
+
let storage = address.storage else:
|
|
2320
|
+
return Result[UdpSocket, Error].failure(error= invalid_address_error("socket address is released"))
|
|
2321
|
+
|
|
2322
|
+
let handle = alloc_udp_handle()
|
|
2323
|
+
let init_status = libuv.udp_init(aio_backend.runtime_loop(runtime), handle)
|
|
2324
|
+
if init_status != 0:
|
|
2325
|
+
unsafe: heap.release_bytes(ptr[void]<-handle)
|
|
2326
|
+
return Result[UdpSocket, Error].failure(error= libuv_error(init_status))
|
|
2327
|
+
|
|
2328
|
+
let bind_status = libuv.udp_bind(handle, sockaddr_storage_as_sockaddr(storage), 0)
|
|
2329
|
+
if bind_status != 0:
|
|
2330
|
+
close_raw_udp_handle(handle)
|
|
2331
|
+
return Result[UdpSocket, Error].failure(error= libuv_error(bind_status))
|
|
2332
|
+
|
|
2333
|
+
return Result[UdpSocket, Error].success(value= attach_udp_socket(handle))
|
|
2334
|
+
|
|
2335
|
+
|
|
2336
|
+
function finish_resolve(state: ptr[ResolveState], result_value: Result[SocketAddress, Error], status_code: int) -> void:
|
|
2337
|
+
var waiter: fn(frame: ptr[void]) -> void = noop_waiter
|
|
2338
|
+
var waiter_frame: ptr[void]? = null
|
|
2339
|
+
var notify = false
|
|
2340
|
+
|
|
2341
|
+
unsafe:
|
|
2342
|
+
read(state).result = result_value
|
|
2343
|
+
read(state).result_owned = true
|
|
2344
|
+
read(state).status_code = status_code
|
|
2345
|
+
read(state).ready = true
|
|
2346
|
+
if read(state).waiter_registered:
|
|
2347
|
+
waiter = read(state).waiter
|
|
2348
|
+
waiter_frame = read(state).waiter_frame
|
|
2349
|
+
read(state).waiter_registered = false
|
|
2350
|
+
notify = true
|
|
2351
|
+
|
|
2352
|
+
if notify and waiter_frame != null[ptr[void]]:
|
|
2353
|
+
waiter(unsafe: waiter_frame)
|
|
2354
|
+
|
|
2355
|
+
|
|
2356
|
+
function finish_resolve_all(
|
|
2357
|
+
state: ptr[ResolveAllState],
|
|
2358
|
+
result_value: Result[vec.Vec[SocketAddress], Error],
|
|
2359
|
+
status_code: int
|
|
2360
|
+
) -> void:
|
|
2361
|
+
var waiter: fn(frame: ptr[void]) -> void = noop_waiter
|
|
2362
|
+
var waiter_frame: ptr[void]? = null
|
|
2363
|
+
var notify = false
|
|
2364
|
+
|
|
2365
|
+
unsafe:
|
|
2366
|
+
read(state).result = result_value
|
|
2367
|
+
read(state).result_owned = true
|
|
2368
|
+
read(state).status_code = status_code
|
|
2369
|
+
read(state).ready = true
|
|
2370
|
+
if read(state).waiter_registered:
|
|
2371
|
+
waiter = read(state).waiter
|
|
2372
|
+
waiter_frame = read(state).waiter_frame
|
|
2373
|
+
read(state).waiter_registered = false
|
|
2374
|
+
notify = true
|
|
2375
|
+
|
|
2376
|
+
if notify and waiter_frame != null[ptr[void]]:
|
|
2377
|
+
waiter(unsafe: waiter_frame)
|
|
2378
|
+
|
|
2379
|
+
|
|
2380
|
+
function resolve_callback(
|
|
2381
|
+
req: ptr[NativeGetAddrInfoRequest],
|
|
2382
|
+
status_code: int,
|
|
2383
|
+
result_ptr: ptr[NativeAddrInfo]
|
|
2384
|
+
) -> void:
|
|
2385
|
+
let maybe_result = unsafe: ptr[NativeAddrInfo]?<-result_ptr
|
|
2386
|
+
|
|
2387
|
+
let state_raw = libuv.req_get_data(req_as_base(req)) else:
|
|
2388
|
+
if maybe_result != null[ptr[NativeAddrInfo]]:
|
|
2389
|
+
libuv.freeaddrinfo(result_ptr)
|
|
2390
|
+
return
|
|
2391
|
+
|
|
2392
|
+
let state = unsafe: ptr[ResolveState]<-state_raw
|
|
2393
|
+
unsafe: read(state).req = null
|
|
2394
|
+
|
|
2395
|
+
if status_code != 0:
|
|
2396
|
+
if maybe_result != null[ptr[NativeAddrInfo]]:
|
|
2397
|
+
libuv.freeaddrinfo(result_ptr)
|
|
2398
|
+
finish_resolve(state, Result[SocketAddress, Error].failure(error= libuv_error(status_code)), status_code)
|
|
2399
|
+
return
|
|
2400
|
+
|
|
2401
|
+
if maybe_result == null[ptr[NativeAddrInfo]]:
|
|
2402
|
+
finish_resolve(
|
|
2403
|
+
state,
|
|
2404
|
+
Result[SocketAddress, Error].failure(error= invalid_address_error("resolver returned no addresses")),
|
|
2405
|
+
-1
|
|
2406
|
+
)
|
|
2407
|
+
return
|
|
2408
|
+
|
|
2409
|
+
let ai = unsafe: read(result_ptr)
|
|
2410
|
+
let address_result = socket_address_from_sockaddr(ai.ai_addr, ptr_uint<-ai.ai_addrlen)
|
|
2411
|
+
libuv.freeaddrinfo(result_ptr)
|
|
2412
|
+
finish_resolve(state, address_result, 0)
|
|
2413
|
+
|
|
2414
|
+
|
|
2415
|
+
function resolve_all_callback(
|
|
2416
|
+
req: ptr[NativeGetAddrInfoRequest],
|
|
2417
|
+
status_code: int,
|
|
2418
|
+
result_ptr: ptr[NativeAddrInfo]
|
|
2419
|
+
) -> void:
|
|
2420
|
+
let maybe_result = unsafe: ptr[NativeAddrInfo]?<-result_ptr
|
|
2421
|
+
|
|
2422
|
+
let state_raw = libuv.req_get_data(req_as_base(req)) else:
|
|
2423
|
+
if maybe_result != null[ptr[NativeAddrInfo]]:
|
|
2424
|
+
libuv.freeaddrinfo(result_ptr)
|
|
2425
|
+
return
|
|
2426
|
+
|
|
2427
|
+
let state = unsafe: ptr[ResolveAllState]<-state_raw
|
|
2428
|
+
unsafe: read(state).req = null
|
|
2429
|
+
|
|
2430
|
+
if status_code != 0:
|
|
2431
|
+
if maybe_result != null[ptr[NativeAddrInfo]]:
|
|
2432
|
+
libuv.freeaddrinfo(result_ptr)
|
|
2433
|
+
finish_resolve_all(
|
|
2434
|
+
state,
|
|
2435
|
+
Result[vec.Vec[SocketAddress], Error].failure(error= libuv_error(status_code)),
|
|
2436
|
+
status_code
|
|
2437
|
+
)
|
|
2438
|
+
return
|
|
2439
|
+
|
|
2440
|
+
if maybe_result == null[ptr[NativeAddrInfo]]:
|
|
2441
|
+
finish_resolve_all(
|
|
2442
|
+
state,
|
|
2443
|
+
Result[
|
|
2444
|
+
vec.Vec[SocketAddress],
|
|
2445
|
+
Error
|
|
2446
|
+
].failure(error= invalid_address_error("resolver returned no addresses")),
|
|
2447
|
+
-1
|
|
2448
|
+
)
|
|
2449
|
+
return
|
|
2450
|
+
|
|
2451
|
+
var addresses = vec.Vec[SocketAddress].create()
|
|
2452
|
+
var current: ptr[NativeAddrInfo]? = maybe_result
|
|
2453
|
+
while true:
|
|
2454
|
+
if current == null:
|
|
2455
|
+
break
|
|
2456
|
+
|
|
2457
|
+
let live_current = unsafe: current
|
|
2458
|
+
let ai = unsafe: read(live_current)
|
|
2459
|
+
let address_result = socket_address_from_sockaddr(ai.ai_addr, ptr_uint<-ai.ai_addrlen)
|
|
2460
|
+
match address_result:
|
|
2461
|
+
Result.failure as payload:
|
|
2462
|
+
libuv.freeaddrinfo(result_ptr)
|
|
2463
|
+
release_socket_addresses(ref_of(addresses))
|
|
2464
|
+
finish_resolve_all(state, Result[vec.Vec[SocketAddress], Error].failure(error= payload.error), -1)
|
|
2465
|
+
return
|
|
2466
|
+
Result.success as payload:
|
|
2467
|
+
addresses.push(payload.value)
|
|
2468
|
+
|
|
2469
|
+
current = ai.ai_next
|
|
2470
|
+
|
|
2471
|
+
libuv.freeaddrinfo(result_ptr)
|
|
2472
|
+
|
|
2473
|
+
if addresses.len == 0:
|
|
2474
|
+
addresses.release()
|
|
2475
|
+
finish_resolve_all(
|
|
2476
|
+
state,
|
|
2477
|
+
Result[
|
|
2478
|
+
vec.Vec[SocketAddress],
|
|
2479
|
+
Error
|
|
2480
|
+
].failure(error= invalid_address_error("resolver returned no addresses")),
|
|
2481
|
+
-1
|
|
2482
|
+
)
|
|
2483
|
+
return
|
|
2484
|
+
|
|
2485
|
+
finish_resolve_all(state, Result[vec.Vec[SocketAddress], Error].success(value= addresses), 0)
|
|
2486
|
+
|
|
2487
|
+
|
|
2488
|
+
function resolve_on_impl(runtime: aio.Runtime, node: str, service: str) -> Task[Result[SocketAddress, Error]]:
|
|
2489
|
+
let loop = aio_backend.runtime_loop(runtime)
|
|
2490
|
+
let state = heap.must_alloc_zeroed[ResolveState](1)
|
|
2491
|
+
|
|
2492
|
+
let req_size = libuv.req_size(libuv.uv_req_type.UV_GETADDRINFO)
|
|
2493
|
+
let req = unsafe: ptr[NativeGetAddrInfoRequest]<-heap.must_alloc_zeroed_bytes(1, req_size)
|
|
2494
|
+
var storage = arena.create(node.len + service.len + 2)
|
|
2495
|
+
let node_cstr = storage.to_cstr(node)
|
|
2496
|
+
let service_cstr = storage.to_cstr(service)
|
|
2497
|
+
|
|
2498
|
+
unsafe:
|
|
2499
|
+
read(state).ready = false
|
|
2500
|
+
read(state).status_code = 0
|
|
2501
|
+
read(state).result = Result[SocketAddress, Error].success(value= zero[SocketAddress])
|
|
2502
|
+
read(state).result_owned = false
|
|
2503
|
+
read(state).waiter_frame = null
|
|
2504
|
+
read(state).waiter = noop_waiter
|
|
2505
|
+
read(state).waiter_registered = false
|
|
2506
|
+
read(state).req = req
|
|
2507
|
+
read(state).storage = storage
|
|
2508
|
+
read(state).node = node_cstr
|
|
2509
|
+
read(state).service = service_cstr
|
|
2510
|
+
read(state).released = false
|
|
2511
|
+
libuv.req_set_data(req_as_base(req), ptr[void]<-state)
|
|
2512
|
+
|
|
2513
|
+
let queue_status = libuv.getaddrinfo(
|
|
2514
|
+
loop,
|
|
2515
|
+
req,
|
|
2516
|
+
resolve_callback,
|
|
2517
|
+
unsafe: read(state).node,
|
|
2518
|
+
unsafe: read(state).service,
|
|
2519
|
+
null[const_ptr[NativeAddrInfo]]
|
|
2520
|
+
)
|
|
2521
|
+
if queue_status != 0:
|
|
2522
|
+
unsafe:
|
|
2523
|
+
heap.release(req)
|
|
2524
|
+
read(state).req = null
|
|
2525
|
+
finish_resolve(state, Result[SocketAddress, Error].failure(error= libuv_error(queue_status)), queue_status)
|
|
2526
|
+
|
|
2527
|
+
return resolve_task(state)
|
|
2528
|
+
|
|
2529
|
+
|
|
2530
|
+
function resolve_all_on_impl(
|
|
2531
|
+
runtime: aio.Runtime,
|
|
2532
|
+
node: str,
|
|
2533
|
+
service: str
|
|
2534
|
+
) -> Task[Result[vec.Vec[SocketAddress], Error]]:
|
|
2535
|
+
let loop = aio_backend.runtime_loop(runtime)
|
|
2536
|
+
let state = heap.must_alloc_zeroed[ResolveAllState](1)
|
|
2537
|
+
|
|
2538
|
+
let req_size = libuv.req_size(libuv.uv_req_type.UV_GETADDRINFO)
|
|
2539
|
+
let req = unsafe: ptr[NativeGetAddrInfoRequest]<-heap.must_alloc_zeroed_bytes(1, req_size)
|
|
2540
|
+
var storage = arena.create(node.len + service.len + 2)
|
|
2541
|
+
let node_cstr = storage.to_cstr(node)
|
|
2542
|
+
let service_cstr = storage.to_cstr(service)
|
|
2543
|
+
|
|
2544
|
+
unsafe:
|
|
2545
|
+
read(state).ready = false
|
|
2546
|
+
read(state).status_code = 0
|
|
2547
|
+
read(state).result = Result[vec.Vec[SocketAddress], Error].success(value= vec.Vec[SocketAddress].create())
|
|
2548
|
+
read(state).result_owned = false
|
|
2549
|
+
read(state).waiter_frame = null
|
|
2550
|
+
read(state).waiter = noop_waiter
|
|
2551
|
+
read(state).waiter_registered = false
|
|
2552
|
+
read(state).req = req
|
|
2553
|
+
read(state).storage = storage
|
|
2554
|
+
read(state).node = node_cstr
|
|
2555
|
+
read(state).service = service_cstr
|
|
2556
|
+
read(state).released = false
|
|
2557
|
+
libuv.req_set_data(req_as_base(req), ptr[void]<-state)
|
|
2558
|
+
|
|
2559
|
+
let queue_status = libuv.getaddrinfo(
|
|
2560
|
+
loop,
|
|
2561
|
+
req,
|
|
2562
|
+
resolve_all_callback,
|
|
2563
|
+
unsafe: read(state).node,
|
|
2564
|
+
unsafe: read(state).service,
|
|
2565
|
+
null[const_ptr[NativeAddrInfo]]
|
|
2566
|
+
)
|
|
2567
|
+
if queue_status != 0:
|
|
2568
|
+
unsafe:
|
|
2569
|
+
heap.release(req)
|
|
2570
|
+
read(state).req = null
|
|
2571
|
+
finish_resolve_all(
|
|
2572
|
+
state,
|
|
2573
|
+
Result[vec.Vec[SocketAddress], Error].failure(error= libuv_error(queue_status)),
|
|
2574
|
+
queue_status
|
|
2575
|
+
)
|
|
2576
|
+
|
|
2577
|
+
return resolve_all_task(state)
|
|
2578
|
+
|
|
2579
|
+
|
|
2580
|
+
function connect_on_impl(runtime: aio.Runtime, address: SocketAddress) -> Task[Result[TcpStream, Error]]:
|
|
2581
|
+
let state = heap.must_alloc_zeroed[ConnectState](1)
|
|
2582
|
+
unsafe:
|
|
2583
|
+
read(state).ready = false
|
|
2584
|
+
read(state).status_code = 0
|
|
2585
|
+
read(state).result = Result[TcpStream, Error].success(value= zero[TcpStream])
|
|
2586
|
+
read(state).result_owned = false
|
|
2587
|
+
read(state).waiter_frame = null
|
|
2588
|
+
read(state).waiter = noop_waiter
|
|
2589
|
+
read(state).waiter_registered = false
|
|
2590
|
+
read(state).req = null
|
|
2591
|
+
read(state).handle = null
|
|
2592
|
+
read(state).destination = zero[SocketAddress]
|
|
2593
|
+
read(state).destination_owned = false
|
|
2594
|
+
read(state).released = false
|
|
2595
|
+
|
|
2596
|
+
match duplicate_socket_address(address):
|
|
2597
|
+
Result.failure as payload:
|
|
2598
|
+
let error = payload.error
|
|
2599
|
+
finish_connect(state, Result[TcpStream, Error].failure(error= error), error.code)
|
|
2600
|
+
return connect_task(state)
|
|
2601
|
+
Result.success as payload:
|
|
2602
|
+
unsafe:
|
|
2603
|
+
read(state).destination = payload.value
|
|
2604
|
+
read(state).destination_owned = true
|
|
2605
|
+
|
|
2606
|
+
let handle = alloc_tcp_handle()
|
|
2607
|
+
let init_status = libuv.tcp_init(aio_backend.runtime_loop(runtime), handle)
|
|
2608
|
+
if init_status != 0:
|
|
2609
|
+
unsafe: heap.release_bytes(ptr[void]<-handle)
|
|
2610
|
+
finish_connect(state, Result[TcpStream, Error].failure(error= libuv_error(init_status)), init_status)
|
|
2611
|
+
return connect_task(state)
|
|
2612
|
+
|
|
2613
|
+
let req = alloc_connect_request()
|
|
2614
|
+
unsafe:
|
|
2615
|
+
read(state).req = req
|
|
2616
|
+
read(state).handle = handle
|
|
2617
|
+
libuv.req_set_data(connect_req_as_base(req), ptr[void]<-state)
|
|
2618
|
+
|
|
2619
|
+
let destination_storage = unsafe: read(state).destination.storage else:
|
|
2620
|
+
unsafe:
|
|
2621
|
+
heap.release_bytes(ptr[void]<-req)
|
|
2622
|
+
read(state).req = null
|
|
2623
|
+
read(state).handle = null
|
|
2624
|
+
close_tcp_handle(handle)
|
|
2625
|
+
finish_connect(
|
|
2626
|
+
state,
|
|
2627
|
+
Result[TcpStream, Error].failure(error= invalid_address_error("socket address is released")),
|
|
2628
|
+
-1
|
|
2629
|
+
)
|
|
2630
|
+
return connect_task(state)
|
|
2631
|
+
|
|
2632
|
+
let queue_status = libuv.tcp_connect(
|
|
2633
|
+
req,
|
|
2634
|
+
handle,
|
|
2635
|
+
sockaddr_storage_as_sockaddr(destination_storage),
|
|
2636
|
+
connect_callback
|
|
2637
|
+
)
|
|
2638
|
+
if queue_status != 0:
|
|
2639
|
+
unsafe:
|
|
2640
|
+
heap.release_bytes(ptr[void]<-req)
|
|
2641
|
+
read(state).req = null
|
|
2642
|
+
read(state).handle = null
|
|
2643
|
+
close_tcp_handle(handle)
|
|
2644
|
+
finish_connect(state, Result[TcpStream, Error].failure(error= libuv_error(queue_status)), queue_status)
|
|
2645
|
+
|
|
2646
|
+
return connect_task(state)
|
|
2647
|
+
|
|
2648
|
+
|
|
2649
|
+
function listen_on_impl(runtime: aio.Runtime, address: SocketAddress, backlog: int) -> Result[TcpListener, Error]:
|
|
2650
|
+
let storage = address.storage else:
|
|
2651
|
+
return Result[TcpListener, Error].failure(error= invalid_address_error("socket address is released"))
|
|
2652
|
+
|
|
2653
|
+
let handle = alloc_tcp_handle()
|
|
2654
|
+
let init_status = libuv.tcp_init(aio_backend.runtime_loop(runtime), handle)
|
|
2655
|
+
if init_status != 0:
|
|
2656
|
+
unsafe: heap.release_bytes(ptr[void]<-handle)
|
|
2657
|
+
return Result[TcpListener, Error].failure(error= libuv_error(init_status))
|
|
2658
|
+
|
|
2659
|
+
let bind_status = libuv.tcp_bind(handle, sockaddr_storage_as_sockaddr(storage), 0)
|
|
2660
|
+
if bind_status != 0:
|
|
2661
|
+
close_tcp_handle(handle)
|
|
2662
|
+
return Result[TcpListener, Error].failure(error= libuv_error(bind_status))
|
|
2663
|
+
|
|
2664
|
+
let listen_status = libuv.listen(tcp_as_stream(handle), backlog, listener_connection_callback)
|
|
2665
|
+
if listen_status != 0:
|
|
2666
|
+
close_tcp_handle(handle)
|
|
2667
|
+
return Result[TcpListener, Error].failure(error= libuv_error(listen_status))
|
|
2668
|
+
|
|
2669
|
+
let listener_state = heap.must_alloc_zeroed[ListenerState](1)
|
|
2670
|
+
unsafe:
|
|
2671
|
+
read(listener_state).handle = handle
|
|
2672
|
+
read(listener_state).pending_connections = 0
|
|
2673
|
+
read(listener_state).pending_error_code = 0
|
|
2674
|
+
read(listener_state).accept_state = null
|
|
2675
|
+
libuv.handle_set_data(tcp_as_handle(handle), ptr[void]<-listener_state)
|
|
2676
|
+
|
|
2677
|
+
return Result[TcpListener, Error].success(value= TcpListener(handle = handle))
|
|
2678
|
+
|
|
2679
|
+
|
|
2680
|
+
extending Error:
|
|
2681
|
+
public editable function release() -> void:
|
|
2682
|
+
this.message.release()
|
|
2683
|
+
|
|
2684
|
+
|
|
2685
|
+
extending SocketAddress:
|
|
2686
|
+
public editable function release() -> void:
|
|
2687
|
+
heap.release(this.storage)
|
|
2688
|
+
this.storage = null
|
|
2689
|
+
this.len = 0
|
|
2690
|
+
|
|
2691
|
+
|
|
2692
|
+
public function copy() -> Result[SocketAddress, Error]:
|
|
2693
|
+
let storage = this.storage else:
|
|
2694
|
+
return Result[SocketAddress, Error].failure(error= invalid_address_error("socket address is released"))
|
|
2695
|
+
|
|
2696
|
+
return socket_address_from_sockaddr(sockaddr_storage_as_sockaddr(storage), this.len)
|
|
2697
|
+
|
|
2698
|
+
|
|
2699
|
+
public function equal(other: SocketAddress) -> bool:
|
|
2700
|
+
if this.len != other.len:
|
|
2701
|
+
return false
|
|
2702
|
+
|
|
2703
|
+
let left = this.storage else:
|
|
2704
|
+
return false
|
|
2705
|
+
|
|
2706
|
+
let right = other.storage else:
|
|
2707
|
+
return false
|
|
2708
|
+
|
|
2709
|
+
return cstring.compare_bytes(
|
|
2710
|
+
unsafe: const_ptr[void]<-left,
|
|
2711
|
+
unsafe: const_ptr[void]<-right,
|
|
2712
|
+
this.len
|
|
2713
|
+
) == 0
|
|
2714
|
+
|
|
2715
|
+
|
|
2716
|
+
public function host() -> Result[string.String, Error]:
|
|
2717
|
+
return socket_address_to_string_result(this)
|
|
2718
|
+
|
|
2719
|
+
|
|
2720
|
+
public function port() -> Result[int, Error]:
|
|
2721
|
+
let storage = this.storage else:
|
|
2722
|
+
return Result[int, Error].failure(
|
|
2723
|
+
error = invalid_address_error("socket address is released")
|
|
2724
|
+
)
|
|
2725
|
+
|
|
2726
|
+
let ss_ptr = unsafe: storage
|
|
2727
|
+
let family = (unsafe: read(ss_ptr)).ss_family
|
|
2728
|
+
|
|
2729
|
+
let v4_family = ipv4_socket_family()
|
|
2730
|
+
if family == v4_family:
|
|
2731
|
+
let in_ptr = unsafe: ptr[libuv.sockaddr_in]<-storage
|
|
2732
|
+
let nbo_port = (unsafe: read(in_ptr)).sin_port
|
|
2733
|
+
let host_port = int<-(((uint<-nbo_port) >> 8) | (((uint<-nbo_port) & 0xFFu) << 8))
|
|
2734
|
+
return Result[int, Error].success(value = host_port)
|
|
2735
|
+
|
|
2736
|
+
let v6_family = ipv6_socket_family()
|
|
2737
|
+
if family == v6_family:
|
|
2738
|
+
let in6_ptr = unsafe: ptr[libuv.sockaddr_in6]<-storage
|
|
2739
|
+
let nbo_port = (unsafe: read(in6_ptr)).sin6_port
|
|
2740
|
+
let host_port = int<-(((uint<-nbo_port) >> 8) | (((uint<-nbo_port) & 0xFFu) << 8))
|
|
2741
|
+
return Result[int, Error].success(value = host_port)
|
|
2742
|
+
|
|
2743
|
+
return Result[int, Error].failure(
|
|
2744
|
+
error = invalid_address_error("unknown address family")
|
|
2745
|
+
)
|
|
2746
|
+
|
|
2747
|
+
|
|
2748
|
+
extending UdpDatagram:
|
|
2749
|
+
public editable function release() -> void:
|
|
2750
|
+
this.data.release()
|
|
2751
|
+
this.source.release()
|
|
2752
|
+
|
|
2753
|
+
|
|
2754
|
+
extending TcpStream:
|
|
2755
|
+
public editable function release() -> void:
|
|
2756
|
+
let handle = this.handle else:
|
|
2757
|
+
return
|
|
2758
|
+
|
|
2759
|
+
this.handle = null
|
|
2760
|
+
close_tcp_stream_handle(handle)
|
|
2761
|
+
|
|
2762
|
+
|
|
2763
|
+
public function local_address() -> Result[SocketAddress, Error]:
|
|
2764
|
+
return tcp_socket_address_from_getsockname(this.handle)
|
|
2765
|
+
|
|
2766
|
+
|
|
2767
|
+
public function peer_address() -> Result[SocketAddress, Error]:
|
|
2768
|
+
return tcp_socket_address_from_getpeername(this.handle)
|
|
2769
|
+
|
|
2770
|
+
|
|
2771
|
+
public function socket_fd() -> Result[int, Error]:
|
|
2772
|
+
return tcp_socket_fd(this.handle)
|
|
2773
|
+
|
|
2774
|
+
|
|
2775
|
+
public function write_bytes(content: span[ubyte]) -> Task[Result[ptr_uint, Error]]:
|
|
2776
|
+
return write_on_impl(this.handle, content)
|
|
2777
|
+
|
|
2778
|
+
|
|
2779
|
+
public function read_once(max_bytes: ptr_uint) -> Task[Result[bytes.Bytes, Error]]:
|
|
2780
|
+
return read_once_impl(this.handle, max_bytes)
|
|
2781
|
+
|
|
2782
|
+
|
|
2783
|
+
public function read_exactly(byte_count: ptr_uint) -> Task[Result[bytes.Bytes, Error]]:
|
|
2784
|
+
return read_exactly_impl(this.handle, byte_count)
|
|
2785
|
+
|
|
2786
|
+
|
|
2787
|
+
public function shutdown() -> Task[Result[bool, Error]]:
|
|
2788
|
+
return shutdown_impl(this.handle)
|
|
2789
|
+
|
|
2790
|
+
|
|
2791
|
+
extending TcpListener:
|
|
2792
|
+
public editable function release() -> void:
|
|
2793
|
+
let handle = this.handle else:
|
|
2794
|
+
return
|
|
2795
|
+
|
|
2796
|
+
let state_raw = libuv.handle_get_data(tcp_as_handle(handle))
|
|
2797
|
+
if state_raw != null[ptr[void]]:
|
|
2798
|
+
let listener = unsafe: ptr[ListenerState]<-state_raw
|
|
2799
|
+
let pending_accept = unsafe: read(listener).accept_state
|
|
2800
|
+
if pending_accept != null[ptr[AcceptState]]:
|
|
2801
|
+
unsafe: read(listener).accept_state = null
|
|
2802
|
+
finish_accept(
|
|
2803
|
+
unsafe: pending_accept,
|
|
2804
|
+
Result[TcpStream, Error].failure(error= net_error("listener released")),
|
|
2805
|
+
-1
|
|
2806
|
+
)
|
|
2807
|
+
|
|
2808
|
+
this.handle = null
|
|
2809
|
+
if libuv.is_closing(tcp_as_handle(handle)) == 0:
|
|
2810
|
+
libuv.close(tcp_as_handle(handle), listener_close_callback)
|
|
2811
|
+
|
|
2812
|
+
|
|
2813
|
+
public function accept() -> Task[Result[TcpStream, Error]]:
|
|
2814
|
+
return accept_impl(this.handle)
|
|
2815
|
+
|
|
2816
|
+
|
|
2817
|
+
public function local_address() -> Result[SocketAddress, Error]:
|
|
2818
|
+
return tcp_socket_address_from_getsockname(this.handle)
|
|
2819
|
+
|
|
2820
|
+
|
|
2821
|
+
extending UdpSocket:
|
|
2822
|
+
public editable function release() -> void:
|
|
2823
|
+
let handle = this.handle else:
|
|
2824
|
+
return
|
|
2825
|
+
|
|
2826
|
+
let state_raw = libuv.handle_get_data(udp_as_handle(handle))
|
|
2827
|
+
if state_raw == null[ptr[void]]:
|
|
2828
|
+
this.handle = null
|
|
2829
|
+
close_raw_udp_handle(handle)
|
|
2830
|
+
return
|
|
2831
|
+
|
|
2832
|
+
let state = unsafe: ptr[UdpSocketState]<-state_raw
|
|
2833
|
+
if unsafe: read(state).pending_send_count > 0z:
|
|
2834
|
+
unsafe:
|
|
2835
|
+
read(state).closing = true
|
|
2836
|
+
this.handle = null
|
|
2837
|
+
return
|
|
2838
|
+
|
|
2839
|
+
this.handle = null
|
|
2840
|
+
close_udp_socket_handle(handle)
|
|
2841
|
+
|
|
2842
|
+
|
|
2843
|
+
public function local_address() -> Result[SocketAddress, Error]:
|
|
2844
|
+
return udp_socket_address_from_getsockname(this.handle)
|
|
2845
|
+
|
|
2846
|
+
|
|
2847
|
+
public function peer_address() -> Result[SocketAddress, Error]:
|
|
2848
|
+
return udp_socket_address_from_getpeername(this.handle)
|
|
2849
|
+
|
|
2850
|
+
|
|
2851
|
+
public function connect(destination: SocketAddress) -> Result[bool, Error]:
|
|
2852
|
+
return udp_connect_impl(this.handle, destination)
|
|
2853
|
+
|
|
2854
|
+
|
|
2855
|
+
public function send(content: span[ubyte]) -> Task[Result[ptr_uint, Error]]:
|
|
2856
|
+
return udp_send_connected_impl(this.handle, content)
|
|
2857
|
+
|
|
2858
|
+
|
|
2859
|
+
public function send_to(content: span[ubyte], destination: SocketAddress) -> Task[Result[ptr_uint, Error]]:
|
|
2860
|
+
return udp_send_to_impl(this.handle, content, destination)
|
|
2861
|
+
|
|
2862
|
+
|
|
2863
|
+
public function recv(max_bytes: ptr_uint) -> Task[Result[bytes.Bytes, Error]]:
|
|
2864
|
+
return recv_impl(this.handle, max_bytes)
|
|
2865
|
+
|
|
2866
|
+
|
|
2867
|
+
public function recv_from(max_bytes: ptr_uint) -> Task[Result[UdpDatagram, Error]]:
|
|
2868
|
+
return recv_from_impl(this.handle, max_bytes)
|
|
2869
|
+
|
|
2870
|
+
|
|
2871
|
+
public function set_broadcast(on: bool) -> int:
|
|
2872
|
+
let handle = this.handle else:
|
|
2873
|
+
return -1
|
|
2874
|
+
if on:
|
|
2875
|
+
return libuv.udp_set_broadcast(handle, 1)
|
|
2876
|
+
return libuv.udp_set_broadcast(handle, 0)
|
|
2877
|
+
|
|
2878
|
+
|
|
2879
|
+
public function ipv4(ip: str, port: int) -> Result[SocketAddress, Error]:
|
|
2880
|
+
var raw = zero[libuv.sockaddr_in]
|
|
2881
|
+
let status_code = libuv.ip4_addr(ip, port, raw)
|
|
2882
|
+
if status_code != 0:
|
|
2883
|
+
return Result[SocketAddress, Error].failure(error= libuv_error(status_code))
|
|
2884
|
+
|
|
2885
|
+
return socket_address_from_sockaddr(
|
|
2886
|
+
sockaddr_storage_as_sockaddr(unsafe: ptr[NativeSocketStorage]<-ptr_of(raw)),
|
|
2887
|
+
size_of(libuv.sockaddr_in)
|
|
2888
|
+
)
|
|
2889
|
+
|
|
2890
|
+
|
|
2891
|
+
public function ipv6(ip: str, port: int) -> Result[SocketAddress, Error]:
|
|
2892
|
+
var raw = zero[libuv.sockaddr_in6]
|
|
2893
|
+
let status_code = libuv.ip6_addr(ip, port, raw)
|
|
2894
|
+
if status_code != 0:
|
|
2895
|
+
return Result[SocketAddress, Error].failure(error= libuv_error(status_code))
|
|
2896
|
+
|
|
2897
|
+
return socket_address_from_sockaddr(
|
|
2898
|
+
sockaddr_storage_as_sockaddr(unsafe: ptr[NativeSocketStorage]<-ptr_of(raw)),
|
|
2899
|
+
size_of(libuv.sockaddr_in6)
|
|
2900
|
+
)
|
|
2901
|
+
|
|
2902
|
+
|
|
2903
|
+
public function resolve_first_on(runtime: aio.Runtime, node: str, service: str) -> Task[Result[SocketAddress, Error]]:
|
|
2904
|
+
return resolve_on_impl(runtime, node, service)
|
|
2905
|
+
|
|
2906
|
+
|
|
2907
|
+
public function resolve_first(node: str, service: str) -> Task[Result[SocketAddress, Error]]:
|
|
2908
|
+
return resolve_first_on(aio.current_runtime(), node, service)
|
|
2909
|
+
|
|
2910
|
+
|
|
2911
|
+
public function resolve_all_on(
|
|
2912
|
+
runtime: aio.Runtime,
|
|
2913
|
+
node: str,
|
|
2914
|
+
service: str
|
|
2915
|
+
) -> Task[Result[vec.Vec[SocketAddress], Error]]:
|
|
2916
|
+
return resolve_all_on_impl(runtime, node, service)
|
|
2917
|
+
|
|
2918
|
+
|
|
2919
|
+
public function resolve_all(node: str, service: str) -> Task[Result[vec.Vec[SocketAddress], Error]]:
|
|
2920
|
+
return resolve_all_on(aio.current_runtime(), node, service)
|
|
2921
|
+
|
|
2922
|
+
|
|
2923
|
+
public function connect_on(runtime: aio.Runtime, address: SocketAddress) -> Task[Result[TcpStream, Error]]:
|
|
2924
|
+
return connect_on_impl(runtime, address)
|
|
2925
|
+
|
|
2926
|
+
|
|
2927
|
+
public function connect(address: SocketAddress) -> Task[Result[TcpStream, Error]]:
|
|
2928
|
+
return connect_on(aio.current_runtime(), address)
|
|
2929
|
+
|
|
2930
|
+
|
|
2931
|
+
public function listen_on(runtime: aio.Runtime, address: SocketAddress, backlog: int) -> Result[TcpListener, Error]:
|
|
2932
|
+
return listen_on_impl(runtime, address, backlog)
|
|
2933
|
+
|
|
2934
|
+
|
|
2935
|
+
public function listen(address: SocketAddress, backlog: int) -> Result[TcpListener, Error]:
|
|
2936
|
+
return listen_on(aio.current_runtime(), address, backlog)
|
|
2937
|
+
|
|
2938
|
+
|
|
2939
|
+
public function udp_bind_on(runtime: aio.Runtime, address: SocketAddress) -> Result[UdpSocket, Error]:
|
|
2940
|
+
return udp_bind_on_impl(runtime, address)
|
|
2941
|
+
|
|
2942
|
+
|
|
2943
|
+
public function udp_bind(address: SocketAddress) -> Result[UdpSocket, Error]:
|
|
2944
|
+
return udp_bind_on(aio.current_runtime(), address)
|