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/mux.mt ADDED
@@ -0,0 +1,839 @@
1
+ import std.async as aio
2
+ import std.binary as bin
3
+ import std.bytes as bytes
4
+ import std.deque as deque
5
+ import std.mem.heap as heap
6
+ import std.net as net
7
+ import std.net.session as sess
8
+ import std.vec as vec
9
+
10
+ public const flag_reliable: ubyte = 0x01
11
+ public const flag_fragmented: ubyte = 0x04
12
+
13
+ public const meta_channel: ubyte = 0xFF
14
+ public const type_peer_joined: ushort = 0xFFFE
15
+ public const type_peer_left: ushort = 0xFFFD
16
+
17
+ const wire_header_size: ptr_uint = 4
18
+ const fragment_header_size: ptr_uint = 6
19
+
20
+ public struct MuxedSendOptions:
21
+ reliable: bool
22
+ fragmented: bool
23
+
24
+ public struct MuxedConfig:
25
+ fragment_size: ptr_uint
26
+ fragment_timeout_frames: uint
27
+
28
+ public struct MuxedMessage:
29
+ peer_id: uint
30
+ channel_id: ubyte
31
+ type_id: ushort
32
+ msg_flags: ubyte
33
+ payload: bytes.Bytes
34
+
35
+ public struct MuxedConnection:
36
+ conn: sess.Connection
37
+ config: MuxedConfig
38
+ event_queue: deque.Deque[MuxedMessage]
39
+ frag_buffers: vec.Vec[FragBuffer]
40
+ next_group_id: ushort
41
+ current_frame: uint
42
+
43
+ public struct MuxedSession:
44
+ session: sess.Session
45
+ config: MuxedConfig
46
+ event_queue: deque.Deque[MuxedMessage]
47
+ frag_buffers: vec.Vec[FragBuffer]
48
+ next_group_id: ushort
49
+ current_frame: uint
50
+
51
+ struct FragBuffer:
52
+ group_id: ushort
53
+ peer_id: uint
54
+ channel_id: ubyte
55
+ type_id: ushort
56
+ msg_flags: ubyte
57
+ total: ushort
58
+ received_count: ushort
59
+ received_bits: uint
60
+ data: bytes.Bytes
61
+ last_frame: uint
62
+
63
+ struct WireHeader:
64
+ channel_id: ubyte
65
+ type_id: ushort
66
+ msg_flags: ubyte
67
+
68
+
69
+ extending MuxedSendOptions:
70
+ public function to_flags() -> ubyte:
71
+ var send_flags: ubyte = 0
72
+ if this.reliable:
73
+ send_flags |= flag_reliable
74
+ if this.fragmented:
75
+ send_flags |= flag_fragmented
76
+ return send_flags
77
+
78
+
79
+ extending MuxedConfig:
80
+ public static function default() -> MuxedConfig:
81
+ return MuxedConfig(
82
+ fragment_size = 1000,
83
+ fragment_timeout_frames = 120
84
+ )
85
+
86
+
87
+ extending MuxedMessage:
88
+ public editable function release() -> void:
89
+ this.payload.release()
90
+
91
+
92
+ public function mux_connect_on(
93
+ runtime: aio.Runtime,
94
+ local_address: net.SocketAddress,
95
+ remote_address: net.SocketAddress,
96
+ config: MuxedConfig
97
+ ) -> Result[MuxedConnection, net.Error]:
98
+ let payload_size = config.fragment_size + wire_header_size + fragment_header_size + 32
99
+ let session_config = sess.Config.default(payload_size)
100
+ let conn_result = sess.connect_on(runtime, local_address, remote_address, session_config)
101
+ match conn_result:
102
+ Result.failure as p:
103
+ return Result[MuxedConnection, net.Error].failure(
104
+ error = p.error
105
+ )
106
+ Result.success as p:
107
+ let conn = MuxedConnection(
108
+ conn = p.value,
109
+ config = config,
110
+ event_queue = deque.Deque[MuxedMessage].create(),
111
+ frag_buffers = vec.Vec[FragBuffer].create(),
112
+ next_group_id = 1,
113
+ current_frame = 0
114
+ )
115
+ return Result[MuxedConnection, net.Error].success(value = conn)
116
+
117
+
118
+ public async function mux_connect(
119
+ local_address: net.SocketAddress,
120
+ remote_address: net.SocketAddress,
121
+ config: MuxedConfig
122
+ ) -> Result[MuxedConnection, net.Error]:
123
+ match mux_connect_on(aio.current_runtime(), local_address, remote_address, config):
124
+ Result.failure as p:
125
+ return Result[MuxedConnection, net.Error].failure(error = p.error)
126
+ Result.success as p:
127
+ var mux_conn = p.value
128
+ match await mux_conn.connect_to_peer():
129
+ Result.failure as cp:
130
+ mux_conn.release()
131
+ return Result[MuxedConnection, net.Error].failure(error = cp.error)
132
+ Result.success:
133
+ return Result[MuxedConnection, net.Error].success(value = mux_conn)
134
+
135
+
136
+ public function mux_listen_on(
137
+ runtime: aio.Runtime,
138
+ local_address: net.SocketAddress,
139
+ config: MuxedConfig
140
+ ) -> Result[MuxedSession, net.Error]:
141
+ let payload_size = config.fragment_size + wire_header_size + fragment_header_size + 32
142
+ let session_config = sess.Config.default(payload_size)
143
+ let listen_result = sess.listen_on(runtime, local_address, session_config)
144
+ match listen_result:
145
+ Result.failure as p:
146
+ return Result[MuxedSession, net.Error].failure(
147
+ error = p.error
148
+ )
149
+ Result.success as p:
150
+ return Result[MuxedSession, net.Error].success(value = MuxedSession(
151
+ session = p.value,
152
+ config = config,
153
+ event_queue = deque.Deque[MuxedMessage].create(),
154
+ frag_buffers = vec.Vec[FragBuffer].create(),
155
+ next_group_id = 1,
156
+ current_frame = 0
157
+ ))
158
+
159
+
160
+ public function mux_listen(
161
+ local_address: net.SocketAddress,
162
+ config: MuxedConfig
163
+ ) -> Result[MuxedSession, net.Error]:
164
+ return mux_listen_on(aio.current_runtime(), local_address, config)
165
+
166
+
167
+ extending MuxedConnection:
168
+ public editable function release() -> void:
169
+ release_frag_buffers(ref_of(this.frag_buffers))
170
+ this.frag_buffers.release()
171
+ release_event_queue(ref_of(this.event_queue))
172
+ this.event_queue.release()
173
+ this.conn.release()
174
+
175
+
176
+ public function state() -> sess.ConnectionState:
177
+ return this.conn.state()
178
+
179
+
180
+ public function local_address() -> Result[net.SocketAddress, net.Error]:
181
+ return this.conn.local_address()
182
+
183
+
184
+ public function peer_address() -> Result[net.SocketAddress, net.Error]:
185
+ return this.conn.peer_address()
186
+
187
+
188
+ public async editable function connect_to_peer() -> Result[bool, net.Error]:
189
+ match await this.conn.connect_to_peer():
190
+ Result.failure as p:
191
+ return Result[bool, net.Error].failure(error = p.error)
192
+ Result.success as p:
193
+ return Result[bool, net.Error].success(value = p.value)
194
+
195
+
196
+ public async editable function tick(frame: uint) -> Result[bool, net.Error]:
197
+ this.current_frame = frame
198
+ let conn_result = await this.conn.tick(frame)
199
+ drain_incoming_conn(ref_of(this))
200
+ prune_frag_buffers(ref_of(this.frag_buffers), frame, this.config.fragment_timeout_frames)
201
+ match conn_result:
202
+ Result.failure as p:
203
+ return Result[bool, net.Error].failure(error = p.error)
204
+ Result.success as p:
205
+ return Result[bool, net.Error].success(value = p.value)
206
+
207
+
208
+ public editable function try_recv() -> Option[MuxedMessage]:
209
+ return this.event_queue.pop_front()
210
+
211
+
212
+ public async editable function recv() -> Result[Option[MuxedMessage], net.Error]:
213
+ while true:
214
+ let ev = this.try_recv()
215
+ match ev:
216
+ Option.some as p:
217
+ return Result[Option[MuxedMessage], net.Error].success(
218
+ value = Option[MuxedMessage].some(value = p.value)
219
+ )
220
+ Option.none:
221
+ let sess_result = await this.conn.recv()
222
+ match sess_result:
223
+ Result.failure as p:
224
+ return Result[Option[MuxedMessage], net.Error].failure(
225
+ error = p.error
226
+ )
227
+ Result.success as sess_p:
228
+ match sess_p.value:
229
+ Option.none:
230
+ pass
231
+ Option.some as msg_p:
232
+ var msg = msg_p.value
233
+ demux_conn(ref_of(this), ref_of(msg), this.current_frame)
234
+ let queued = this.try_recv()
235
+ match queued:
236
+ Option.some as q:
237
+ return Result[Option[MuxedMessage], net.Error].success(
238
+ value = Option[MuxedMessage].some(value = q.value)
239
+ )
240
+ Option.none:
241
+ pass
242
+
243
+
244
+ public async editable function mux_send(
245
+ channel_id: ubyte,
246
+ type_id: ushort,
247
+ data: span[ubyte],
248
+ send_flags: ubyte
249
+ ) -> Result[bool, net.Error]:
250
+ if (send_flags & flag_fragmented) != 0 and data.len > this.config.fragment_size:
251
+ return await send_fragmented_conn(ref_of(this), channel_id, type_id, data, send_flags)
252
+ return await send_single_conn(ref_of(this), channel_id, type_id, data, send_flags)
253
+
254
+
255
+ public async editable function disconnect() -> Result[bool, net.Error]:
256
+ match await this.conn.disconnect_peer():
257
+ Result.failure as p:
258
+ return Result[bool, net.Error].failure(error = p.error)
259
+ Result.success as p:
260
+ return Result[bool, net.Error].success(value = p.value)
261
+
262
+
263
+ extending MuxedSession:
264
+ public editable function release() -> void:
265
+ release_frag_buffers(ref_of(this.frag_buffers))
266
+ this.frag_buffers.release()
267
+ release_event_queue(ref_of(this.event_queue))
268
+ this.event_queue.release()
269
+ this.session.release()
270
+
271
+
272
+ public function local_address() -> Result[net.SocketAddress, net.Error]:
273
+ return this.session.local_address()
274
+
275
+
276
+ public function peer_count() -> ptr_uint:
277
+ return this.session.peer_count()
278
+
279
+
280
+ public async editable function tick(frame: uint) -> Result[bool, net.Error]:
281
+ this.current_frame = frame
282
+ let sess_result = await this.session.tick(frame)
283
+ drain_incoming_session(ref_of(this))
284
+ prune_frag_buffers(ref_of(this.frag_buffers), frame, this.config.fragment_timeout_frames)
285
+ match sess_result:
286
+ Result.failure as p:
287
+ return Result[bool, net.Error].failure(error = p.error)
288
+ Result.success as p:
289
+ return Result[bool, net.Error].success(value = p.value)
290
+
291
+
292
+ public editable function try_recv() -> Option[MuxedMessage]:
293
+ return this.event_queue.pop_front()
294
+
295
+
296
+ public async editable function recv() -> Result[Option[MuxedMessage], net.Error]:
297
+ while true:
298
+ let ev = this.try_recv()
299
+ match ev:
300
+ Option.some as p:
301
+ return Result[Option[MuxedMessage], net.Error].success(
302
+ value = Option[MuxedMessage].some(value = p.value)
303
+ )
304
+ Option.none:
305
+ let sess_result = await this.session.recv()
306
+ match sess_result:
307
+ Result.failure as p:
308
+ return Result[Option[MuxedMessage], net.Error].failure(
309
+ error = p.error
310
+ )
311
+ Result.success as sess_p:
312
+ match sess_p.value:
313
+ Option.none:
314
+ pass
315
+ Option.some as msg_p:
316
+ var msg = msg_p.value
317
+ demux_session(ref_of(this), ref_of(msg), this.current_frame)
318
+ let queued = this.try_recv()
319
+ match queued:
320
+ Option.some as q:
321
+ return Result[Option[MuxedMessage], net.Error].success(
322
+ value = Option[MuxedMessage].some(value = q.value)
323
+ )
324
+ Option.none:
325
+ pass
326
+
327
+
328
+ public async editable function mux_send(
329
+ peer_id: uint,
330
+ channel_id: ubyte,
331
+ type_id: ushort,
332
+ data: span[ubyte],
333
+ send_flags: ubyte
334
+ ) -> Result[bool, net.Error]:
335
+ if (send_flags & flag_fragmented) != 0 and data.len > this.config.fragment_size:
336
+ return await send_fragmented_session(ref_of(this), peer_id, channel_id, type_id, data, send_flags)
337
+ return await send_single_session(ref_of(this), peer_id, channel_id, type_id, data, send_flags)
338
+
339
+
340
+ public async editable function kick(peer_id: uint, reason: ubyte) -> Result[bool, net.Error]:
341
+ match await this.session.kick(peer_id, reason):
342
+ Result.failure as p:
343
+ return Result[bool, net.Error].failure(error = p.error)
344
+ Result.success as p:
345
+ return Result[bool, net.Error].success(value = p.value)
346
+
347
+
348
+ function encode_frame(channel_id: ubyte, type_id: ushort, msg_flags: ubyte, payload: span[ubyte]) -> bytes.Bytes:
349
+ var w = bin.Writer.with_capacity(wire_header_size + payload.len)
350
+ w.write_ubyte(channel_id)
351
+ w.write_ushort(type_id)
352
+ w.write_ubyte(msg_flags)
353
+ w.write_bytes(payload)
354
+ return w.finish()
355
+
356
+
357
+ function encode_fragment_frame(
358
+ channel_id: ubyte,
359
+ type_id: ushort,
360
+ msg_flags: ubyte,
361
+ group_id: ushort,
362
+ frag_index: ushort,
363
+ total: ushort,
364
+ payload: span[ubyte]
365
+ ) -> bytes.Bytes:
366
+ var w = bin.Writer.with_capacity(wire_header_size + fragment_header_size + payload.len)
367
+ w.write_ubyte(channel_id)
368
+ w.write_ushort(type_id)
369
+ w.write_ubyte(msg_flags | flag_fragmented)
370
+ w.write_ushort(group_id)
371
+ w.write_ushort(frag_index)
372
+ w.write_ushort(total)
373
+ w.write_bytes(payload)
374
+ return w.finish()
375
+
376
+
377
+ async function send_single_conn(
378
+ mux: ref[MuxedConnection],
379
+ channel_id: ubyte,
380
+ type_id: ushort,
381
+ data: span[ubyte],
382
+ send_flags: ubyte
383
+ ) -> Result[bool, net.Error]:
384
+ var frame = encode_frame(channel_id, type_id, send_flags, data)
385
+ defer frame.release()
386
+ if (send_flags & flag_reliable) != 0:
387
+ let result = await mux.conn.send_reliable(frame.as_span(), 0)
388
+ return result
389
+ let result = await mux.conn.send(frame.as_span())
390
+ return result
391
+
392
+
393
+ async function send_single_session(
394
+ mux: ref[MuxedSession],
395
+ peer_id: uint,
396
+ channel_id: ubyte,
397
+ type_id: ushort,
398
+ data: span[ubyte],
399
+ send_flags: ubyte
400
+ ) -> Result[bool, net.Error]:
401
+ var frame = encode_frame(channel_id, type_id, send_flags, data)
402
+ defer frame.release()
403
+ if (send_flags & flag_reliable) != 0:
404
+ let result = await mux.session.send_reliable(peer_id, frame.as_span(), 0)
405
+ return result
406
+ let result = await mux.session.send(peer_id, frame.as_span())
407
+ return result
408
+
409
+
410
+ async function send_fragmented_conn(
411
+ mux: ref[MuxedConnection],
412
+ channel_id: ubyte,
413
+ type_id: ushort,
414
+ data: span[ubyte],
415
+ send_flags: ubyte
416
+ ) -> Result[bool, net.Error]:
417
+ let group_id = mux.next_group_id
418
+ mux.next_group_id += 1
419
+ let frag_flags = send_flags | flag_fragmented
420
+ let chunk_size = mux.config.fragment_size
421
+ var total: ushort = 0
422
+ var remaining = data.len
423
+ while remaining > 0:
424
+ let chunk_len = if remaining < chunk_size: remaining else: chunk_size
425
+ if chunk_len == 0:
426
+ break
427
+ total += 1
428
+ remaining -= chunk_len
429
+
430
+ remaining = data.len
431
+ var offset: ptr_uint = 0
432
+ var frag_index: ushort = 0
433
+ while remaining > 0:
434
+ let chunk_len = if remaining < chunk_size: remaining else: chunk_size
435
+ if chunk_len == 0:
436
+ break
437
+ let chunk = unsafe: span[ubyte](data = data.data + offset, len = chunk_len)
438
+ var frame = encode_fragment_frame(channel_id, type_id, frag_flags, group_id, frag_index, total, chunk)
439
+ defer frame.release()
440
+ if (send_flags & flag_reliable) != 0:
441
+ let _ = await mux.conn.send_reliable(frame.as_span(), 0)
442
+ else:
443
+ let _ = await mux.conn.send(frame.as_span())
444
+ offset += chunk_len
445
+ remaining -= chunk_len
446
+ frag_index += 1
447
+ return Result[bool, net.Error].success(value = true)
448
+
449
+
450
+ async function send_fragmented_session(
451
+ mux: ref[MuxedSession],
452
+ peer_id: uint,
453
+ channel_id: ubyte,
454
+ type_id: ushort,
455
+ data: span[ubyte],
456
+ send_flags: ubyte
457
+ ) -> Result[bool, net.Error]:
458
+ let group_id = mux.next_group_id
459
+ mux.next_group_id += 1
460
+ let frag_flags = send_flags | flag_fragmented
461
+ let chunk_size = mux.config.fragment_size
462
+ var total: ushort = 0
463
+ var remaining = data.len
464
+ while remaining > 0:
465
+ let chunk_len = if remaining < chunk_size: remaining else: chunk_size
466
+ if chunk_len == 0:
467
+ break
468
+ total += 1
469
+ remaining -= chunk_len
470
+
471
+ remaining = data.len
472
+ var offset: ptr_uint = 0
473
+ var frag_index: ushort = 0
474
+ while remaining > 0:
475
+ let chunk_len = if remaining < chunk_size: remaining else: chunk_size
476
+ if chunk_len == 0:
477
+ break
478
+ let chunk = unsafe: span[ubyte](data = data.data + offset, len = chunk_len)
479
+ var frame = encode_fragment_frame(channel_id, type_id, frag_flags, group_id, frag_index, total, chunk)
480
+ defer frame.release()
481
+ if (send_flags & flag_reliable) != 0:
482
+ let _ = await mux.session.send_reliable(peer_id, frame.as_span(), 0)
483
+ else:
484
+ let _ = await mux.session.send(peer_id, frame.as_span())
485
+ offset += chunk_len
486
+ remaining -= chunk_len
487
+ frag_index += 1
488
+ return Result[bool, net.Error].success(value = true)
489
+
490
+
491
+ function decode_wire_header(data: span[ubyte]) -> Result[WireHeader, net.Error]:
492
+ if data.len < wire_header_size:
493
+ return Result[WireHeader, net.Error].failure(error = net.net_error("mux payload too short"))
494
+ var r = bin.reader(data)
495
+ let channel_id = r.read_ubyte() else:
496
+ return Result[WireHeader, net.Error].failure(error = net.net_error("mux malformed header"))
497
+ let type_id = r.read_ushort() else:
498
+ return Result[WireHeader, net.Error].failure(error = net.net_error("mux malformed header"))
499
+ let wire_flags = r.read_ubyte() else:
500
+ return Result[WireHeader, net.Error].failure(error = net.net_error("mux malformed header"))
501
+ return Result[WireHeader, net.Error].success(value = WireHeader(
502
+ channel_id = channel_id,
503
+ type_id = type_id,
504
+ msg_flags = wire_flags
505
+ ))
506
+
507
+
508
+ function drain_incoming_conn(mux: ref[MuxedConnection]) -> void:
509
+ while true:
510
+ let ev = mux.conn.try_recv()
511
+ match ev:
512
+ Option.none:
513
+ break
514
+ Option.some as p:
515
+ var e = p.value
516
+ demux_conn(mux, ref_of(e), mux.current_frame)
517
+
518
+
519
+ function drain_incoming_session(mux: ref[MuxedSession]) -> void:
520
+ while true:
521
+ let ev = mux.session.try_recv()
522
+ match ev:
523
+ Option.none:
524
+ break
525
+ Option.some as p:
526
+ var e = p.value
527
+ demux_session(mux, ref_of(e), mux.current_frame)
528
+
529
+
530
+ function demux_conn(mux: ref[MuxedConnection], ev: ref[sess.PeerEvent], frame: uint) -> void:
531
+ if ev.kind == sess.PeerEventKind.peer_joined:
532
+ mux.event_queue.push_back(MuxedMessage(
533
+ peer_id = ev.peer_id,
534
+ channel_id = meta_channel,
535
+ type_id = type_peer_joined,
536
+ msg_flags = 0,
537
+ payload = bytes.Bytes.empty()
538
+ ))
539
+ ev.release()
540
+ return
541
+
542
+ if ev.kind == sess.PeerEventKind.peer_left:
543
+ mux.event_queue.push_back(MuxedMessage(
544
+ peer_id = ev.peer_id,
545
+ channel_id = meta_channel,
546
+ type_id = type_peer_left,
547
+ msg_flags = 0,
548
+ payload = bytes.Bytes.empty()
549
+ ))
550
+ ev.release()
551
+ return
552
+
553
+ if ev.kind != sess.PeerEventKind.user_data:
554
+ ev.release()
555
+ return
556
+
557
+ let data = ev.payload.as_span()
558
+ if data.len < wire_header_size:
559
+ ev.release()
560
+ return
561
+
562
+ let header_result = decode_wire_header(data)
563
+ match header_result:
564
+ Result.failure:
565
+ ev.release()
566
+ return
567
+ Result.success as hp:
568
+ let h = hp.value
569
+ if (h.msg_flags & flag_fragmented) != 0:
570
+ handle_fragment_conn(mux, h, data, frame)
571
+ else:
572
+ let payload_len = data.len - wire_header_size
573
+ var payload = bytes.Bytes.empty()
574
+ if payload_len > 0:
575
+ unsafe:
576
+ payload = bytes.Bytes.copy(span[ubyte](data = data.data + wire_header_size, len = payload_len))
577
+ mux.event_queue.push_back(MuxedMessage(
578
+ peer_id = ev.peer_id,
579
+ channel_id = h.channel_id,
580
+ type_id = h.type_id,
581
+ msg_flags = h.msg_flags,
582
+ payload = payload
583
+ ))
584
+ ev.release()
585
+
586
+
587
+ function demux_session(mux: ref[MuxedSession], ev: ref[sess.PeerEvent], frame: uint) -> void:
588
+ if ev.kind == sess.PeerEventKind.peer_joined:
589
+ mux.event_queue.push_back(MuxedMessage(
590
+ peer_id = ev.peer_id,
591
+ channel_id = meta_channel,
592
+ type_id = type_peer_joined,
593
+ msg_flags = 0,
594
+ payload = bytes.Bytes.empty()
595
+ ))
596
+ ev.release()
597
+ return
598
+
599
+ if ev.kind == sess.PeerEventKind.peer_left:
600
+ mux.event_queue.push_back(MuxedMessage(
601
+ peer_id = ev.peer_id,
602
+ channel_id = meta_channel,
603
+ type_id = type_peer_left,
604
+ msg_flags = 0,
605
+ payload = bytes.Bytes.empty()
606
+ ))
607
+ ev.release()
608
+ return
609
+
610
+ if ev.kind != sess.PeerEventKind.user_data:
611
+ ev.release()
612
+ return
613
+
614
+ let data = ev.payload.as_span()
615
+ if data.len < wire_header_size:
616
+ ev.release()
617
+ return
618
+
619
+ let header_result = decode_wire_header(data)
620
+ match header_result:
621
+ Result.failure:
622
+ ev.release()
623
+ return
624
+ Result.success as hp:
625
+ let h = hp.value
626
+ if (h.msg_flags & flag_fragmented) != 0:
627
+ handle_fragment_session(mux, h, data, frame, ev.peer_id)
628
+ else:
629
+ let payload_len = data.len - wire_header_size
630
+ var payload = bytes.Bytes.empty()
631
+ if payload_len > 0:
632
+ unsafe:
633
+ payload = bytes.Bytes.copy(span[ubyte](data = data.data + wire_header_size, len = payload_len))
634
+ mux.event_queue.push_back(MuxedMessage(
635
+ peer_id = ev.peer_id,
636
+ channel_id = h.channel_id,
637
+ type_id = h.type_id,
638
+ msg_flags = h.msg_flags,
639
+ payload = payload
640
+ ))
641
+ ev.release()
642
+
643
+
644
+ function handle_fragment_conn(mux: ref[MuxedConnection], h: WireHeader, data: span[ubyte], frame: uint) -> void:
645
+ if data.len < wire_header_size + fragment_header_size:
646
+ return
647
+ unsafe:
648
+ let group_lo = ushort<-read(data.data + wire_header_size)
649
+ let group_hi = ushort<-read(data.data + wire_header_size + 1)
650
+ let group_id = group_lo | (group_hi << 8)
651
+ let index_lo = ushort<-read(data.data + wire_header_size + 2)
652
+ let index_hi = ushort<-read(data.data + wire_header_size + 3)
653
+ let frag_index = index_lo | (index_hi << 8)
654
+ let total_lo = ushort<-read(data.data + wire_header_size + 4)
655
+ let total_hi = ushort<-read(data.data + wire_header_size + 5)
656
+ let total = total_lo | (total_hi << 8)
657
+ assemble_fragment(
658
+ ref_of(mux.frag_buffers),
659
+ ref_of(mux.event_queue),
660
+ mux.config,
661
+ h,
662
+ group_id,
663
+ frag_index,
664
+ total,
665
+ data,
666
+ frame,
667
+ 0
668
+ )
669
+
670
+
671
+ function handle_fragment_session(
672
+ mux: ref[MuxedSession],
673
+ h: WireHeader,
674
+ data: span[ubyte],
675
+ frame: uint,
676
+ peer_id: uint
677
+ ) -> void:
678
+ if data.len < wire_header_size + fragment_header_size:
679
+ return
680
+ unsafe:
681
+ let group_lo = ushort<-read(data.data + wire_header_size)
682
+ let group_hi = ushort<-read(data.data + wire_header_size + 1)
683
+ let group_id = group_lo | (group_hi << 8)
684
+ let index_lo = ushort<-read(data.data + wire_header_size + 2)
685
+ let index_hi = ushort<-read(data.data + wire_header_size + 3)
686
+ let frag_index = index_lo | (index_hi << 8)
687
+ let total_lo = ushort<-read(data.data + wire_header_size + 4)
688
+ let total_hi = ushort<-read(data.data + wire_header_size + 5)
689
+ let total = total_lo | (total_hi << 8)
690
+ assemble_fragment(
691
+ ref_of(mux.frag_buffers),
692
+ ref_of(mux.event_queue),
693
+ mux.config,
694
+ h,
695
+ group_id,
696
+ frag_index,
697
+ total,
698
+ data,
699
+ frame,
700
+ peer_id
701
+ )
702
+
703
+
704
+ function assemble_fragment(
705
+ buffers: ref[vec.Vec[FragBuffer]],
706
+ queue: ref[deque.Deque[MuxedMessage]],
707
+ config: MuxedConfig,
708
+ h: WireHeader,
709
+ group_id: ushort,
710
+ frag_index: ushort,
711
+ total: ushort,
712
+ data: span[ubyte],
713
+ frame: uint,
714
+ peer_id: uint
715
+ ) -> void:
716
+ let payload_start = wire_header_size + fragment_header_size
717
+ if data.len <= payload_start:
718
+ return
719
+ let payload_len = data.len - payload_start
720
+ if frag_index >= total:
721
+ return
722
+
723
+ let buf_index = find_frag_buffer(buffers, peer_id, group_id)
724
+ if buf_index < 0:
725
+ let full_size = ptr_uint<-total * config.fragment_size
726
+ var buf = bytes.Bytes.empty()
727
+ if full_size > 0:
728
+ let buf_data = heap.must_alloc[ubyte](full_size)
729
+ var fill: ptr_uint = 0
730
+ while fill < full_size:
731
+ unsafe: read(buf_data + fill) = 0
732
+ fill += 1
733
+ buf = bytes.Bytes(data = buf_data, len = full_size)
734
+ buffers.push(FragBuffer(
735
+ group_id = group_id,
736
+ peer_id = peer_id,
737
+ channel_id = h.channel_id,
738
+ type_id = h.type_id,
739
+ msg_flags = h.msg_flags,
740
+ total = total,
741
+ received_count = 1,
742
+ received_bits = (1 << (uint<-frag_index)),
743
+ data = buf,
744
+ last_frame = frame
745
+ ))
746
+ let dest_start = ptr_uint<-frag_index * config.fragment_size
747
+ if dest_start + payload_len <= full_size:
748
+ unsafe:
749
+ copy_bytes(ptr[ubyte]<-buf.data, dest_start, data, payload_start, payload_len)
750
+ return
751
+
752
+ let buf_ptr = buffers.get(ptr_uint<-buf_index) else:
753
+ return
754
+ let bit_flag: uint = 1 << uint<-frag_index
755
+ if (unsafe: read(buf_ptr).received_bits & bit_flag) != 0:
756
+ return
757
+
758
+ unsafe: read(buf_ptr).received_count += 1
759
+ unsafe: read(buf_ptr).received_bits |= bit_flag
760
+ unsafe: read(buf_ptr).last_frame = frame
761
+ let dest_start = ptr_uint<-frag_index * config.fragment_size
762
+ let full_size = ptr_uint<-total * config.fragment_size
763
+ if dest_start + payload_len <= full_size:
764
+ unsafe:
765
+ copy_bytes(ptr[ubyte]<-read(buf_ptr).data.data, dest_start, data, payload_start, payload_len)
766
+
767
+ if unsafe: read(buf_ptr).received_count == unsafe: read(buf_ptr).total:
768
+ var final_data = bytes.Bytes.empty()
769
+ if full_size > 0:
770
+ let copy_src = unsafe: read(buf_ptr).data.data
771
+ unsafe:
772
+ final_data = bytes.Bytes.copy(span[ubyte](data = ptr[ubyte]<-copy_src, len = full_size))
773
+ queue.push_back(MuxedMessage(
774
+ peer_id = peer_id,
775
+ channel_id = h.channel_id,
776
+ type_id = h.type_id,
777
+ msg_flags = h.msg_flags,
778
+ payload = final_data
779
+ ))
780
+ unsafe: read(buf_ptr).data.release()
781
+ buffers.remove(ptr_uint<-buf_index)
782
+
783
+
784
+ function copy_bytes(
785
+ dest: ptr[ubyte],
786
+ dest_offset: ptr_uint,
787
+ src_data: span[ubyte],
788
+ src_offset: ptr_uint,
789
+ count: ptr_uint
790
+ ) -> void:
791
+ unsafe:
792
+ var i: ptr_uint = 0
793
+ while i < count:
794
+ read(dest + dest_offset + i) = read(src_data.data + src_offset + i)
795
+ i += 1
796
+
797
+
798
+ function find_frag_buffer(buffers: ref[vec.Vec[FragBuffer]], peer_id: uint, group_id: ushort) -> int:
799
+ var index: ptr_uint = 0
800
+ while index < buffers.len():
801
+ let buf_ptr = buffers.get(index) else:
802
+ return -1
803
+ if unsafe: read(buf_ptr).group_id == group_id and unsafe: read(buf_ptr).peer_id == peer_id:
804
+ return int<-index
805
+ index += 1
806
+ return -1
807
+
808
+
809
+ function prune_frag_buffers(buffers: ref[vec.Vec[FragBuffer]], frame: uint, timeout_frames: uint) -> void:
810
+ var index: int = int<-(buffers.len())
811
+ index -= 1
812
+ while index >= 0:
813
+ let buf_ptr = buffers.get(ptr_uint<-index) else:
814
+ return
815
+ if frame > unsafe: read(buf_ptr).last_frame + timeout_frames:
816
+ unsafe: read(buf_ptr).data.release()
817
+ buffers.remove(ptr_uint<-index)
818
+ index -= 1
819
+
820
+
821
+ function release_frag_buffers(buffers: ref[vec.Vec[FragBuffer]]) -> void:
822
+ var index: ptr_uint = 0
823
+ while index < buffers.len():
824
+ let buf_ptr = buffers.get(index) else:
825
+ return
826
+ unsafe: read(buf_ptr).data.release()
827
+ index += 1
828
+ buffers.clear()
829
+
830
+
831
+ function release_event_queue(queue: ref[deque.Deque[MuxedMessage]]) -> void:
832
+ while true:
833
+ let msg = queue.pop_front()
834
+ match msg:
835
+ Option.none:
836
+ break
837
+ Option.some as p:
838
+ var m = p.value
839
+ m.release()