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
@@ -0,0 +1,727 @@
1
+ import std.async as aio
2
+ import std.bytes as bytes
3
+ import std.net as net
4
+ import std.string as string
5
+ import std.vec as vec
6
+
7
+ const header_magic: uint = 0x4D545331
8
+ const header_bytes: ptr_uint = 17
9
+ const reliable_flag: ubyte = 1
10
+ const ack_only_flag: ubyte = 2
11
+ const ack_window_size: ptr_uint = 32
12
+ const max_uint_value: ulong = 0xFFFFFFFF
13
+ const half_sequence_range: uint = 0x80000000
14
+
15
+ public struct Config:
16
+ max_payload_bytes: ptr_uint
17
+ max_pending_reliable: ptr_uint
18
+ resend_after_frames: uint
19
+
20
+ public struct Message:
21
+ sequence: uint
22
+ reliable: bool
23
+ payload: bytes.Bytes
24
+
25
+ public struct HostMessage:
26
+ source: net.SocketAddress
27
+ sequence: uint
28
+ reliable: bool
29
+ payload: bytes.Bytes
30
+
31
+ public struct Channel:
32
+ socket: net.UdpSocket
33
+ config: Config
34
+ protocol: ProtocolState
35
+
36
+ public struct Host:
37
+ socket: net.UdpSocket
38
+ config: Config
39
+ peers: vec.Vec[PeerState]
40
+
41
+ struct PacketHeader:
42
+ sequence: uint
43
+ ack: uint
44
+ ack_bits: uint
45
+ packet_flags: ubyte
46
+
47
+ struct PendingReliable:
48
+ sequence: uint
49
+ payload: bytes.Bytes
50
+ last_sent_frame: uint
51
+
52
+ struct ProtocolState:
53
+ next_sequence: uint
54
+ received_initialized: bool
55
+ received_sequence: uint
56
+ received_mask: uint
57
+ pending_reliable: vec.Vec[PendingReliable]
58
+
59
+ struct PeerState:
60
+ address: net.SocketAddress
61
+ protocol: ProtocolState
62
+
63
+
64
+ function encode_uint(value: uint) -> array[ubyte, 4]:
65
+ return array[ubyte, 4](
66
+ ubyte<-((value >> 24) & 255),
67
+ ubyte<-((value >> 16) & 255),
68
+ ubyte<-((value >> 8) & 255),
69
+ ubyte<-(value & 255)
70
+ )
71
+
72
+
73
+ function decode_uint(data: span[ubyte], offset: ptr_uint) -> uint:
74
+ return (
75
+ ((uint<-data[offset]) << 24)
76
+ | ((uint<-data[offset + 1]) << 16)
77
+ | ((uint<-data[offset + 2]) << 8)
78
+ | (uint<-data[offset + 3])
79
+ )
80
+
81
+
82
+ function sequence_gap(newer: uint, older: uint) -> uint:
83
+ if newer >= older:
84
+ return newer - older
85
+
86
+ return uint<-((ulong<-newer) + (max_uint_value - ulong<-older) + 1)
87
+
88
+
89
+ function sequence_more_recent(left: uint, right: uint) -> bool:
90
+ let forward_gap = sequence_gap(left, right)
91
+ return forward_gap != 0 and forward_gap < half_sequence_range
92
+
93
+
94
+ function sequence_is_acked(sequence: uint, ack: uint, ack_bits: uint) -> bool:
95
+ if sequence == ack:
96
+ return true
97
+
98
+ if sequence_more_recent(sequence, ack):
99
+ return false
100
+
101
+ let distance = sequence_gap(ack, sequence)
102
+ if distance == 0 or distance > uint<-ack_window_size:
103
+ return false
104
+
105
+ let mask = (1u) << (distance - 1)
106
+ return (ack_bits & mask) != 0
107
+
108
+
109
+ function create_protocol_state() -> ProtocolState:
110
+ return ProtocolState(
111
+ next_sequence = 0,
112
+ received_initialized = false,
113
+ received_sequence = 0,
114
+ received_mask = 0,
115
+ pending_reliable = vec.Vec[PendingReliable].create()
116
+ )
117
+
118
+
119
+ function release_protocol_state(protocol: ptr[ProtocolState]) -> void:
120
+ while true:
121
+ let removed = unsafe: read(protocol).pending_reliable.pop()
122
+ if removed.is_none():
123
+ break
124
+ var entry = removed.unwrap()
125
+ entry.payload.release()
126
+
127
+ unsafe: read(protocol).pending_reliable.release()
128
+
129
+
130
+ function release_peer_state(peer: ptr[PeerState]) -> void:
131
+ let protocol = unsafe: ptr_of(read(peer).protocol)
132
+ release_protocol_state(protocol)
133
+ unsafe: read(peer).address.release()
134
+
135
+
136
+ function allocate_sequence(protocol: ptr[ProtocolState]) -> uint:
137
+ let sequence = unsafe: read(protocol).next_sequence
138
+ unsafe: read(protocol).next_sequence += 1
139
+ return sequence
140
+
141
+
142
+ function pending_window_limit(config: Config) -> ptr_uint:
143
+ if config.max_pending_reliable < ack_window_size:
144
+ return config.max_pending_reliable
145
+
146
+ return ack_window_size
147
+
148
+
149
+ function build_packet(
150
+ sequence: uint,
151
+ ack: uint,
152
+ ack_bits: uint,
153
+ packet_flags: ubyte,
154
+ content: span[ubyte]
155
+ ) -> bytes.Bytes:
156
+ var buffer = vec.Vec[ubyte].with_capacity(header_bytes + content.len)
157
+ defer buffer.release()
158
+
159
+ buffer.append_array(encode_uint(header_magic))
160
+ buffer.append_array(encode_uint(sequence))
161
+ buffer.append_array(encode_uint(ack))
162
+ buffer.append_array(encode_uint(ack_bits))
163
+ buffer.push(packet_flags)
164
+ buffer.append_span(content)
165
+ return bytes.Bytes.copy(buffer.as_span())
166
+
167
+
168
+ function decode_header(packet: bytes.Bytes) -> Result[PacketHeader, net.Error]:
169
+ if packet.len < header_bytes:
170
+ return Result[PacketHeader, net.Error].failure(error = net.Error(
171
+ code = -1,
172
+ message = string.String.from_str("udp channel packet is too small")
173
+ ))
174
+
175
+ let packet_span = packet.as_span()
176
+ let magic = decode_uint(packet_span, 0)
177
+ if magic != header_magic:
178
+ return Result[PacketHeader, net.Error].failure(error = net.Error(
179
+ code = -1,
180
+ message = string.String.from_str("udp channel packet has an invalid header")
181
+ ))
182
+
183
+ return Result[PacketHeader, net.Error].success(value = PacketHeader(
184
+ sequence = decode_uint(packet_span, 4),
185
+ ack = decode_uint(packet_span, 8),
186
+ ack_bits = decode_uint(packet_span, 12),
187
+ packet_flags = packet_span[16]
188
+ ))
189
+
190
+
191
+ function copy_payload(packet: bytes.Bytes) -> bytes.Bytes:
192
+ if packet.len == header_bytes:
193
+ return bytes.Bytes.empty()
194
+
195
+ let packet_span = packet.as_span()
196
+ unsafe:
197
+ return bytes.Bytes.copy(span[ubyte](
198
+ data = packet_span.data + header_bytes,
199
+ len = packet_span.len - header_bytes
200
+ ))
201
+
202
+
203
+ function remove_acked_pending(protocol: ptr[ProtocolState], ack: uint, ack_bits: uint) -> void:
204
+ var index: ptr_uint = 0
205
+ while true:
206
+ let pending_len = unsafe: read(protocol).pending_reliable.len()
207
+ if index >= pending_len:
208
+ break
209
+
210
+ let entry_ptr = unsafe: read(protocol).pending_reliable.get(index) else:
211
+ fatal(c"udp channel pending entry missing storage")
212
+
213
+ if sequence_is_acked(unsafe: read(entry_ptr).sequence, ack, ack_bits):
214
+ let removed = unsafe: read(protocol).pending_reliable.remove(index)
215
+ var entry = removed.expect("udp channel pending entry removal failed")
216
+ entry.payload.release()
217
+ continue
218
+
219
+ index += 1
220
+
221
+
222
+ function mark_received(protocol: ptr[ProtocolState], sequence: uint) -> bool:
223
+ let received_initialized = unsafe: read(protocol).received_initialized
224
+ if not received_initialized:
225
+ unsafe:
226
+ read(protocol).received_initialized = true
227
+ read(protocol).received_sequence = sequence
228
+ read(protocol).received_mask = 0
229
+ return true
230
+
231
+ let current_sequence = unsafe: read(protocol).received_sequence
232
+ if sequence == current_sequence:
233
+ return false
234
+
235
+ if sequence_more_recent(sequence, current_sequence):
236
+ let distance = sequence_gap(sequence, current_sequence)
237
+ if distance > uint<-ack_window_size:
238
+ unsafe: read(protocol).received_mask = 0
239
+ else:
240
+ if distance < uint<-ack_window_size:
241
+ unsafe: read(protocol).received_mask = read(protocol).received_mask << distance
242
+ else:
243
+ unsafe: read(protocol).received_mask = 0
244
+
245
+ unsafe: read(protocol).received_mask |= (1) << (distance - 1)
246
+
247
+ unsafe: read(protocol).received_sequence = sequence
248
+ return true
249
+
250
+ let current_mask = unsafe: read(protocol).received_mask
251
+ let distance = sequence_gap(current_sequence, sequence)
252
+ if distance == 0 or distance > uint<-ack_window_size:
253
+ return false
254
+
255
+ let mask = (1u) << (distance - 1)
256
+ if (current_mask & mask) != 0:
257
+ return false
258
+
259
+ unsafe: read(protocol).received_mask |= mask
260
+ return true
261
+
262
+
263
+ async function send_connected_packet(
264
+ socket: net.UdpSocket,
265
+ protocol: ptr[ProtocolState],
266
+ sequence: uint,
267
+ packet_flags: ubyte,
268
+ content: span[ubyte]
269
+ ) -> Result[bool, net.Error]:
270
+ var ack: uint = 0
271
+ var ack_bits: uint = 0
272
+ let received_initialized = unsafe: read(protocol).received_initialized
273
+ if received_initialized:
274
+ ack = unsafe: read(protocol).received_sequence
275
+ ack_bits = unsafe: read(protocol).received_mask
276
+
277
+ var framed = build_packet(sequence, ack, ack_bits, packet_flags, content)
278
+ defer framed.release()
279
+
280
+ (await socket.send(framed.as_span()))?
281
+ return Result[bool, net.Error].success(value = true)
282
+
283
+
284
+ async function send_packet_to(
285
+ socket: net.UdpSocket,
286
+ destination: net.SocketAddress,
287
+ protocol: ptr[ProtocolState],
288
+ sequence: uint,
289
+ packet_flags: ubyte,
290
+ content: span[ubyte]
291
+ ) -> Result[bool, net.Error]:
292
+ var ack: uint = 0
293
+ var ack_bits: uint = 0
294
+ let received_initialized = unsafe: read(protocol).received_initialized
295
+ if received_initialized:
296
+ ack = unsafe: read(protocol).received_sequence
297
+ ack_bits = unsafe: read(protocol).received_mask
298
+
299
+ var framed = build_packet(sequence, ack, ack_bits, packet_flags, content)
300
+ defer framed.release()
301
+
302
+ (await socket.send_to(framed.as_span(), destination))?
303
+ return Result[bool, net.Error].success(value = true)
304
+
305
+
306
+ async function send_connected_ack_only(socket: net.UdpSocket, protocol: ptr[ProtocolState]) -> Result[bool, net.Error]:
307
+ let sequence = allocate_sequence(protocol)
308
+ return await send_connected_packet(socket, protocol, sequence, ack_only_flag, bytes.Bytes.empty().as_span())
309
+
310
+
311
+ async function send_ack_only_to(
312
+ socket: net.UdpSocket,
313
+ destination: net.SocketAddress,
314
+ protocol: ptr[ProtocolState]
315
+ ) -> Result[bool, net.Error]:
316
+ let sequence = allocate_sequence(protocol)
317
+ return await send_packet_to(socket, destination, protocol, sequence, ack_only_flag, bytes.Bytes.empty().as_span())
318
+
319
+
320
+ function find_peer_index(host: ref[Host], address: net.SocketAddress) -> Option[ptr_uint]:
321
+ var index: ptr_uint = 0
322
+ while index < host.peers.len():
323
+ let peer_ptr = host.peers.get(index) else:
324
+ fatal(c"udp channel host peer missing storage")
325
+
326
+ let same_address = unsafe: read(peer_ptr).address.equal(address)
327
+ if same_address:
328
+ return Option[ptr_uint].some(value = index)
329
+
330
+ index += 1
331
+
332
+ return Option[ptr_uint].none
333
+
334
+
335
+ function get_or_create_peer(host: ref[Host], address: net.SocketAddress) -> Result[ptr[PeerState], net.Error]:
336
+ match find_peer_index(host, address):
337
+ Option.some as payload:
338
+ let peer_ptr = host.peers.get(payload.value) else:
339
+ fatal(c"udp channel host peer lookup missing storage")
340
+ return Result[ptr[PeerState], net.Error].success(value = peer_ptr)
341
+ Option.none:
342
+ let addr = address.copy()?
343
+ host.peers.push(PeerState(address = addr, protocol = create_protocol_state()))
344
+ let peer_ptr = host.peers.last() else:
345
+ fatal(c"udp channel host peer insertion missing storage")
346
+ return Result[ptr[PeerState], net.Error].success(value = peer_ptr)
347
+
348
+
349
+ public function wrap_connected(socket: net.UdpSocket, config: Config) -> Channel:
350
+ return Channel(socket = socket, config = config, protocol = create_protocol_state())
351
+
352
+
353
+ public function connect_on(
354
+ runtime: aio.Runtime,
355
+ local_address: net.SocketAddress,
356
+ remote_address: net.SocketAddress,
357
+ config: Config
358
+ ) -> Result[Channel, net.Error]:
359
+ var socket = net.udp_bind_on(runtime, local_address)?
360
+ match socket.connect(remote_address):
361
+ Result.failure as connect_payload:
362
+ socket.release()
363
+ return Result[Channel, net.Error].failure(error = connect_payload.error)
364
+ Result.success as connect_payload:
365
+ if not connect_payload.value:
366
+ socket.release()
367
+ return Result[Channel, net.Error].failure(error = net.Error(
368
+ code = -1,
369
+ message = string.String.from_str("udp connect did not complete")
370
+ ))
371
+ return Result[Channel, net.Error].success(value = wrap_connected(socket, config))
372
+
373
+
374
+ public function connect(
375
+ local_address: net.SocketAddress,
376
+ remote_address: net.SocketAddress,
377
+ config: Config
378
+ ) -> Result[Channel, net.Error]:
379
+ return connect_on(aio.current_runtime(), local_address, remote_address, config)
380
+
381
+
382
+ public function listen_on(
383
+ runtime: aio.Runtime,
384
+ local_address: net.SocketAddress,
385
+ config: Config
386
+ ) -> Result[Host, net.Error]:
387
+ let socket = net.udp_bind_on(runtime, local_address)?
388
+ return Result[Host, net.Error].success(value = Host(
389
+ socket = socket,
390
+ config = config,
391
+ peers = vec.Vec[PeerState].create()
392
+ ))
393
+
394
+
395
+ public function listen(local_address: net.SocketAddress, config: Config) -> Result[Host, net.Error]:
396
+ return listen_on(aio.current_runtime(), local_address, config)
397
+
398
+
399
+ extending Config:
400
+ public static function default(max_payload_bytes: ptr_uint) -> Config:
401
+ return Config(
402
+ max_payload_bytes = max_payload_bytes,
403
+ max_pending_reliable = ack_window_size,
404
+ resend_after_frames = 5
405
+ )
406
+
407
+
408
+ extending Message:
409
+ public editable function release() -> void:
410
+ this.payload.release()
411
+
412
+
413
+ extending HostMessage:
414
+ public editable function release() -> void:
415
+ this.payload.release()
416
+ this.source.release()
417
+
418
+
419
+ extending Channel:
420
+ public editable function release() -> void:
421
+ let protocol = unsafe: ptr_of(this.protocol)
422
+ release_protocol_state(protocol)
423
+ this.socket.release()
424
+
425
+
426
+ public function local_address() -> Result[net.SocketAddress, net.Error]:
427
+ return this.socket.local_address()
428
+
429
+
430
+ public function peer_address() -> Result[net.SocketAddress, net.Error]:
431
+ return this.socket.peer_address()
432
+
433
+
434
+ public function pending_reliable_len() -> ptr_uint:
435
+ return this.protocol.pending_reliable.len()
436
+
437
+
438
+ public async editable function send(content: span[ubyte]) -> Result[uint, net.Error]:
439
+ if content.len > this.config.max_payload_bytes:
440
+ return Result[uint, net.Error].failure(error = net.Error(
441
+ code = -2,
442
+ message = string.String.from_str("udp channel payload exceeds configured maximum")
443
+ ))
444
+
445
+ let protocol = unsafe: ptr_of(this.protocol)
446
+ let sequence = allocate_sequence(protocol)
447
+ (await send_connected_packet(this.socket, protocol, sequence, 0, content))?
448
+ return Result[uint, net.Error].success(value = sequence)
449
+
450
+
451
+ public async editable function send_reliable(content: span[ubyte], frame: uint) -> Result[uint, net.Error]:
452
+ if content.len > this.config.max_payload_bytes:
453
+ return Result[uint, net.Error].failure(error = net.Error(
454
+ code = -2,
455
+ message = string.String.from_str("udp channel payload exceeds configured maximum")
456
+ ))
457
+
458
+ let protocol = unsafe: ptr_of(this.protocol)
459
+ let pending_len = unsafe: read(protocol).pending_reliable.len()
460
+ if pending_len >= pending_window_limit(this.config):
461
+ return Result[uint, net.Error].failure(error = net.Error(
462
+ code = -3,
463
+ message = string.String.from_str("udp channel reliable window is full")
464
+ ))
465
+
466
+ let sequence = allocate_sequence(protocol)
467
+ (await send_connected_packet(this.socket, protocol, sequence, reliable_flag, content))?
468
+ unsafe: read(protocol).pending_reliable.push(PendingReliable(
469
+ sequence = sequence,
470
+ payload = bytes.Bytes.copy(content),
471
+ last_sent_frame = frame
472
+ ))
473
+ return Result[uint, net.Error].success(value = sequence)
474
+
475
+
476
+ public async editable function recv() -> Result[Option[Message], net.Error]:
477
+ var packet = (await this.socket.recv(this.config.max_payload_bytes + header_bytes))?
478
+ defer packet.release()
479
+
480
+ let header = decode_header(packet)?
481
+ let protocol = unsafe: ptr_of(this.protocol)
482
+ remove_acked_pending(protocol, header.ack, header.ack_bits)
483
+ let is_new = mark_received(protocol, header.sequence)
484
+ let is_reliable = (header.packet_flags & reliable_flag) != 0
485
+ if is_reliable:
486
+ (await send_connected_ack_only(this.socket, protocol))?
487
+
488
+ if (header.packet_flags & ack_only_flag) != 0:
489
+ return Result[Option[Message], net.Error].success(value = Option[Message].none)
490
+
491
+ if not is_new:
492
+ return Result[Option[Message], net.Error].success(value = Option[Message].none)
493
+
494
+ return Result[Option[Message], net.Error].success(value = Option[Message].some(value = Message(
495
+ sequence = header.sequence,
496
+ reliable = is_reliable,
497
+ payload = copy_payload(packet)
498
+ )))
499
+
500
+
501
+ public async editable function tick(frame: uint) -> Result[ptr_uint, net.Error]:
502
+ let protocol = unsafe: ptr_of(this.protocol)
503
+ var resent: ptr_uint = 0
504
+ var index: ptr_uint = 0
505
+ while true:
506
+ let pending_len = unsafe: read(protocol).pending_reliable.len()
507
+ if index >= pending_len:
508
+ break
509
+
510
+ let entry_ptr = unsafe: read(protocol).pending_reliable.get(index) else:
511
+ fatal(c"udp channel pending entry missing storage")
512
+
513
+ let last_sent_frame = unsafe: read(entry_ptr).last_sent_frame
514
+ if sequence_gap(frame, last_sent_frame) < this.config.resend_after_frames:
515
+ index += 1
516
+ continue
517
+
518
+ (await send_connected_packet(
519
+ this.socket,
520
+ protocol,
521
+ unsafe: read(entry_ptr).sequence,
522
+ reliable_flag,
523
+ unsafe: read(entry_ptr).payload.as_span()
524
+ ))?
525
+ unsafe: read(entry_ptr).last_sent_frame = frame
526
+ resent += 1
527
+
528
+ index += 1
529
+
530
+ return Result[ptr_uint, net.Error].success(value = resent)
531
+
532
+
533
+ extending Host:
534
+ public editable function release() -> void:
535
+ while true:
536
+ let removed = this.peers.pop()
537
+ if removed.is_none():
538
+ break
539
+ var peer = removed.unwrap()
540
+ let peer_ptr = unsafe: ptr_of(peer)
541
+ release_peer_state(peer_ptr)
542
+
543
+ this.peers.release()
544
+ this.socket.release()
545
+
546
+
547
+ public function local_address() -> Result[net.SocketAddress, net.Error]:
548
+ return this.socket.local_address()
549
+
550
+
551
+ public function peer_count() -> ptr_uint:
552
+ return this.peers.len()
553
+
554
+
555
+ public function pending_reliable_len() -> ptr_uint:
556
+ var total: ptr_uint = 0
557
+ var index: ptr_uint = 0
558
+ while index < this.peers.len():
559
+ let peer_ptr = this.peers.get(index) else:
560
+ fatal(c"udp channel host peer missing storage")
561
+
562
+ let protocol = unsafe: ptr_of(read(peer_ptr).protocol)
563
+ total += unsafe: read(protocol).pending_reliable.len()
564
+ index += 1
565
+
566
+ return total
567
+
568
+
569
+ public async editable function send(
570
+ destination: net.SocketAddress,
571
+ content: span[ubyte]
572
+ ) -> Result[uint, net.Error]:
573
+ if content.len > this.config.max_payload_bytes:
574
+ return Result[uint, net.Error].failure(error = net.Error(
575
+ code = -2,
576
+ message = string.String.from_str("udp channel payload exceeds configured maximum")
577
+ ))
578
+
579
+ let peer_ptr = get_or_create_peer(ref_of(this), destination)?
580
+ let protocol = unsafe: ptr_of(read(peer_ptr).protocol)
581
+ let sequence = allocate_sequence(protocol)
582
+ (await send_packet_to(
583
+ this.socket,
584
+ unsafe: read(peer_ptr).address,
585
+ protocol,
586
+ sequence,
587
+ 0,
588
+ content
589
+ ))?
590
+ return Result[uint, net.Error].success(value = sequence)
591
+
592
+
593
+ public async editable function send_reliable(
594
+ destination: net.SocketAddress,
595
+ content: span[ubyte],
596
+ frame: uint
597
+ ) -> Result[uint, net.Error]:
598
+ if content.len > this.config.max_payload_bytes:
599
+ return Result[uint, net.Error].failure(error = net.Error(
600
+ code = -2,
601
+ message = string.String.from_str("udp channel payload exceeds configured maximum")
602
+ ))
603
+
604
+ let peer_ptr = get_or_create_peer(ref_of(this), destination)?
605
+ let protocol = unsafe: ptr_of(read(peer_ptr).protocol)
606
+ let pending_len = unsafe: read(protocol).pending_reliable.len()
607
+ if pending_len >= pending_window_limit(this.config):
608
+ return Result[uint, net.Error].failure(error = net.Error(
609
+ code = -3,
610
+ message = string.String.from_str("udp channel reliable window is full")
611
+ ))
612
+
613
+ let sequence = allocate_sequence(protocol)
614
+ (await send_packet_to(
615
+ this.socket,
616
+ unsafe: read(peer_ptr).address,
617
+ protocol,
618
+ sequence,
619
+ reliable_flag,
620
+ content
621
+ ))?
622
+ unsafe: read(protocol).pending_reliable.push(PendingReliable(
623
+ sequence = sequence,
624
+ payload = bytes.Bytes.copy(content),
625
+ last_sent_frame = frame
626
+ ))
627
+ return Result[uint, net.Error].success(value = sequence)
628
+
629
+
630
+ public async editable function recv() -> Result[Option[HostMessage], net.Error]:
631
+ var datagram = (await this.socket.recv_from(this.config.max_payload_bytes + header_bytes))?
632
+
633
+ let header_result = decode_header(datagram.data)
634
+ match header_result:
635
+ Result.failure as header_payload:
636
+ datagram.release()
637
+ return Result[Option[HostMessage], net.Error].failure(error = header_payload.error)
638
+ Result.success as header_payload:
639
+ let peer_result = get_or_create_peer(ref_of(this), datagram.source)
640
+ match peer_result:
641
+ Result.failure as peer_payload:
642
+ datagram.release()
643
+ return Result[Option[HostMessage], net.Error].failure(error = peer_payload.error)
644
+ Result.success as peer_payload:
645
+ let peer_ptr = peer_payload.value
646
+ let protocol = unsafe: ptr_of(read(peer_ptr).protocol)
647
+ let header = header_payload.value
648
+ remove_acked_pending(protocol, header.ack, header.ack_bits)
649
+ let is_new = mark_received(protocol, header.sequence)
650
+ let is_reliable = (header.packet_flags & reliable_flag) != 0
651
+ if is_reliable:
652
+ let ack_result = await send_ack_only_to(this.socket, datagram.source, protocol)
653
+ match ack_result:
654
+ Result.failure as ack_payload:
655
+ datagram.release()
656
+ return Result[
657
+ Option[HostMessage],
658
+ net.Error
659
+ ].failure(error = ack_payload.error)
660
+ Result.success as ack_payload:
661
+ ack_payload.value
662
+
663
+ if (header.packet_flags & ack_only_flag) != 0:
664
+ datagram.release()
665
+ return Result[
666
+ Option[HostMessage],
667
+ net.Error
668
+ ].success(value = Option[HostMessage].none)
669
+
670
+ if not is_new:
671
+ datagram.release()
672
+ return Result[
673
+ Option[HostMessage],
674
+ net.Error
675
+ ].success(value = Option[HostMessage].none)
676
+
677
+ let payload = copy_payload(datagram.data)
678
+ datagram.data.release()
679
+ return Result[
680
+ Option[HostMessage],
681
+ net.Error
682
+ ].success(value = Option[HostMessage].some(value = HostMessage(
683
+ source = datagram.source,
684
+ sequence = header.sequence,
685
+ reliable = is_reliable,
686
+ payload = payload
687
+ )))
688
+
689
+
690
+ public async editable function tick(frame: uint) -> Result[ptr_uint, net.Error]:
691
+ var resent: ptr_uint = 0
692
+ var peer_index: ptr_uint = 0
693
+ while peer_index < this.peers.len():
694
+ let peer_ptr = this.peers.get(peer_index) else:
695
+ fatal(c"udp channel host peer missing storage")
696
+
697
+ let protocol = unsafe: ptr_of(read(peer_ptr).protocol)
698
+ var index: ptr_uint = 0
699
+ while true:
700
+ let pending_len = unsafe: read(protocol).pending_reliable.len()
701
+ if index >= pending_len:
702
+ break
703
+
704
+ let entry_ptr = unsafe: read(protocol).pending_reliable.get(index) else:
705
+ fatal(c"udp channel pending entry missing storage")
706
+
707
+ let last_sent_frame = unsafe: read(entry_ptr).last_sent_frame
708
+ if sequence_gap(frame, last_sent_frame) < this.config.resend_after_frames:
709
+ index += 1
710
+ continue
711
+
712
+ (await send_packet_to(
713
+ this.socket,
714
+ unsafe: read(peer_ptr).address,
715
+ protocol,
716
+ unsafe: read(entry_ptr).sequence,
717
+ reliable_flag,
718
+ unsafe: read(entry_ptr).payload.as_span()
719
+ ))?
720
+ unsafe: read(entry_ptr).last_sent_frame = frame
721
+ resent += 1
722
+
723
+ index += 1
724
+
725
+ peer_index += 1
726
+
727
+ return Result[ptr_uint, net.Error].success(value = resent)