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.
Files changed (189) hide show
  1. checksums.yaml +4 -4
  2. data/docs/index.html +4 -3
  3. data/lib/milk_tea/base.rb +1 -1
  4. data/std/asset_pack.mt +267 -0
  5. data/std/async/libuv_runtime.mt +539 -0
  6. data/std/async/mailbox.mt +191 -0
  7. data/std/async/runtime.mt +87 -0
  8. data/std/async.mt +87 -0
  9. data/std/base64.mt +185 -0
  10. data/std/behavior_tree.mt +396 -0
  11. data/std/binary.mt +314 -0
  12. data/std/binary_heap.mt +157 -0
  13. data/std/bitset.mt +239 -0
  14. data/std/box2d.mt +535 -0
  15. data/std/bytes.mt +46 -0
  16. data/std/c/box2d.mt +1254 -0
  17. data/std/c/cgltf.mt +647 -0
  18. data/std/c/cjson.mt +106 -0
  19. data/std/c/crypto.mt +11 -0
  20. data/std/c/crypto_support.h +51 -0
  21. data/std/c/ctype.mt +19 -0
  22. data/std/c/ctype_bindgen.h +29 -0
  23. data/std/c/curl.mt +1223 -0
  24. data/std/c/enet.mt +473 -0
  25. data/std/c/errno.mt +41 -0
  26. data/std/c/errno_bindgen.h +53 -0
  27. data/std/c/flecs.mt +2945 -0
  28. data/std/c/fs.linux.mt +43 -0
  29. data/std/c/fs.windows.mt +43 -0
  30. data/std/c/fs_support.h +954 -0
  31. data/std/c/gl.mt +2065 -0
  32. data/std/c/gl_registry_helpers.h +10748 -0
  33. data/std/c/glfw.mt +499 -0
  34. data/std/c/libc.mt +167 -0
  35. data/std/c/libuv.mt +1491 -0
  36. data/std/c/math.mt +22 -0
  37. data/std/c/math_bindgen.h +31 -0
  38. data/std/c/miniaudio.mt +3420 -0
  39. data/std/c/pcre2.mt +735 -0
  40. data/std/c/process.mt +58 -0
  41. data/std/c/process_support.h +1147 -0
  42. data/std/c/raygui.mt +1602 -0
  43. data/std/c/raylib.mt +1245 -0
  44. data/std/c/raymath.mt +163 -0
  45. data/std/c/rlgl.mt +434 -0
  46. data/std/c/rpng.mt +60 -0
  47. data/std/c/rres.mt +187 -0
  48. data/std/c/sdl3.mt +4132 -0
  49. data/std/c/sqlite3.mt +951 -0
  50. data/std/c/stb_image.mt +52 -0
  51. data/std/c/stb_image_resize2.mt +128 -0
  52. data/std/c/stb_image_write.mt +19 -0
  53. data/std/c/stb_rect_pack.mt +38 -0
  54. data/std/c/stb_truetype.mt +175 -0
  55. data/std/c/stb_vorbis.mt +31 -0
  56. data/std/c/stdio.mt +90 -0
  57. data/std/c/steamworks.h +5769 -0
  58. data/std/c/steamworks.mt +4771 -0
  59. data/std/c/string.mt +16 -0
  60. data/std/c/string_bindgen.h +36 -0
  61. data/std/c/sync.mt +33 -0
  62. data/std/c/sync_support.h +219 -0
  63. data/std/c/terminal.mt +24 -0
  64. data/std/c/terminal_support.h +408 -0
  65. data/std/c/time.mt +26 -0
  66. data/std/c/tls.mt +24 -0
  67. data/std/c/tls_support.h +626 -0
  68. data/std/c/tracy.mt +53 -0
  69. data/std/c/zlib.mt +20 -0
  70. data/std/c/zlib_support.h +239 -0
  71. data/std/c/zstd.mt +231 -0
  72. data/std/cell.mt +60 -0
  73. data/std/cgltf.mt +115 -0
  74. data/std/cjson.mt +90 -0
  75. data/std/cli.mt +768 -0
  76. data/std/cookie.mt +198 -0
  77. data/std/counter.mt +160 -0
  78. data/std/crypto.mt +74 -0
  79. data/std/cstring.mt +13 -0
  80. data/std/ctype.mt +52 -0
  81. data/std/curl/runtime.mt +261 -0
  82. data/std/curl.mt +38 -0
  83. data/std/deque.mt +348 -0
  84. data/std/encoding.mt +93 -0
  85. data/std/enet.mt +133 -0
  86. data/std/env.mt +41 -0
  87. data/std/errno.mt +47 -0
  88. data/std/flecs.mt +978 -0
  89. data/std/fmt.mt +271 -0
  90. data/std/fs.linux.mt +696 -0
  91. data/std/fs.windows.mt +711 -0
  92. data/std/fsm.mt +267 -0
  93. data/std/gl.mt +2062 -0
  94. data/std/glfw.mt +471 -0
  95. data/std/goap.mt +342 -0
  96. data/std/graph.mt +521 -0
  97. data/std/gzip.mt +77 -0
  98. data/std/hash.mt +429 -0
  99. data/std/http/server.mt +810 -0
  100. data/std/http.mt +1227 -0
  101. data/std/intern.mt +53 -0
  102. data/std/jobs.mt +288 -0
  103. data/std/json.mt +627 -0
  104. data/std/libc.mt +34 -0
  105. data/std/libuv.mt +554 -0
  106. data/std/linear_algebra.mt +243 -0
  107. data/std/linked_map.mt +372 -0
  108. data/std/linked_map_view.mt +49 -0
  109. data/std/linked_set.mt +117 -0
  110. data/std/log.mt +69 -0
  111. data/std/map.mt +418 -0
  112. data/std/math.mt +24 -0
  113. data/std/mem/arena.mt +137 -0
  114. data/std/mem/endian.mt +51 -0
  115. data/std/mem/heap.mt +298 -0
  116. data/std/mem/pool.mt +164 -0
  117. data/std/mem/stack.mt +47 -0
  118. data/std/mem/tracking.mt +119 -0
  119. data/std/miniaudio.mt +1299 -0
  120. data/std/multiset.mt +191 -0
  121. data/std/net/channel.mt +727 -0
  122. data/std/net/clock.mt +237 -0
  123. data/std/net/discovery.mt +277 -0
  124. data/std/net/lobby.mt +813 -0
  125. data/std/net/manager.mt +539 -0
  126. data/std/net/mux.mt +839 -0
  127. data/std/net/nat.mt +122 -0
  128. data/std/net/packet.mt +219 -0
  129. data/std/net/punch.mt +162 -0
  130. data/std/net/rpc.mt +119 -0
  131. data/std/net/session.mt +1157 -0
  132. data/std/net/stun.mt +252 -0
  133. data/std/net/sync.mt +183 -0
  134. data/std/net/turn.mt +459 -0
  135. data/std/net.mt +2944 -0
  136. data/std/oauth2.mt +408 -0
  137. data/std/option.mt +51 -0
  138. data/std/ordered_map.mt +497 -0
  139. data/std/ordered_set.mt +348 -0
  140. data/std/path.mt +368 -0
  141. data/std/pcre2/runtime.mt +35 -0
  142. data/std/pcre2.mt +78 -0
  143. data/std/priority_queue.mt +55 -0
  144. data/std/process.mt +837 -0
  145. data/std/queue.mt +55 -0
  146. data/std/random.mt +146 -0
  147. data/std/raygui.mt +99 -0
  148. data/std/raylib/debug_console.mt +71 -0
  149. data/std/raylib/easing.mt +388 -0
  150. data/std/raylib/packed_assets.mt +255 -0
  151. data/std/raylib/runtime.mt +30 -0
  152. data/std/raylib/tracy_gpu.mt +37 -0
  153. data/std/raylib.mt +1510 -0
  154. data/std/raymath.mt +153 -0
  155. data/std/result.mt +89 -0
  156. data/std/rlgl.mt +268 -0
  157. data/std/rpng.mt +46 -0
  158. data/std/rres.mt +36 -0
  159. data/std/sdl3/runtime.mt +54 -0
  160. data/std/sdl3.mt +1731 -0
  161. data/std/serialize.mt +68 -0
  162. data/std/set.mt +124 -0
  163. data/std/spatial.mt +176 -0
  164. data/std/sqlite3.mt +151 -0
  165. data/std/stack.mt +55 -0
  166. data/std/stb_image.mt +47 -0
  167. data/std/stb_image_resize2.mt +41 -0
  168. data/std/stb_image_write.mt +17 -0
  169. data/std/stb_rect_pack.mt +15 -0
  170. data/std/stb_truetype.mt +77 -0
  171. data/std/stb_vorbis.mt +16 -0
  172. data/std/stdio.mt +88 -0
  173. data/std/steamworks.mt +1542 -0
  174. data/std/str.mt +293 -0
  175. data/std/string.mt +234 -0
  176. data/std/sync.mt +194 -0
  177. data/std/tar.mt +704 -0
  178. data/std/terminal.mt +1002 -0
  179. data/std/testing.mt +266 -0
  180. data/std/thread.mt +120 -0
  181. data/std/time.mt +105 -0
  182. data/std/tls.mt +616 -0
  183. data/std/toml.mt +1310 -0
  184. data/std/tracy.mt +42 -0
  185. data/std/uri.mt +118 -0
  186. data/std/url.mt +372 -0
  187. data/std/vec.mt +433 -0
  188. data/std/zstd.mt +94 -0
  189. 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)