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/turn.mt ADDED
@@ -0,0 +1,459 @@
1
+ import std.async as aio
2
+ import std.binary as bin
3
+ import std.bytes as bytes
4
+ import std.crypto as crypto
5
+ import std.fmt as fmt
6
+ import std.libuv as libuv
7
+ import std.net as net
8
+ import std.string as string
9
+
10
+ const stun_magic_cookie: uint = 0x2112A442
11
+
12
+ const allocate_request: ushort = 0x0003
13
+ const allocate_success: ushort = 0x0103
14
+ const allocate_error: ushort = 0x0113
15
+ const send_indication: ushort = 0x0016
16
+ const data_indication: ushort = 0x0017
17
+
18
+ const attr_xor_relayed_address: ushort = 0x0016
19
+ const attr_xor_peer_address: ushort = 0x0017
20
+ const attr_data: ushort = 0x0012
21
+ const attr_requested_transport: ushort = 0x0019
22
+
23
+ const turn_header_len: ptr_uint = 20
24
+
25
+ const err_tid_failed: int = -1
26
+ const err_send_failed: int = -2
27
+ const err_recv_failed: int = -3
28
+ const err_allocate_rejected: int = -4
29
+ const err_timeout: int = -5
30
+ const err_parse_failed: int = -6
31
+ const err_invalid_address: int = -7
32
+ const err_no_data_attribute: int = -8
33
+
34
+ public struct TurnAllocation:
35
+ relay_address: net.SocketAddress
36
+
37
+ public struct TurnDatagram:
38
+ peer_address: net.SocketAddress
39
+ data: bytes.Bytes
40
+
41
+ public struct Error:
42
+ code: int
43
+ message: string.String
44
+
45
+
46
+ extending Error:
47
+ public editable function release() -> void:
48
+ this.message.release()
49
+
50
+
51
+ extending TurnAllocation:
52
+ public editable function release() -> void:
53
+ this.relay_address.release()
54
+
55
+
56
+ extending TurnDatagram:
57
+ public editable function release() -> void:
58
+ this.peer_address.release()
59
+ this.data.release()
60
+
61
+
62
+ function turn_error(code: int, msg: str) -> Error:
63
+ return Error(code = code, message = string.String.from_str(msg))
64
+
65
+
66
+ function read_ushort_be(data: span[ubyte], offset: ptr_uint) -> ushort:
67
+ let hi = uint<-data[offset]
68
+ let lo = uint<-data[offset + 1z]
69
+ return ushort<-((hi << 8) | lo)
70
+
71
+
72
+ function read_uint_be(data: span[ubyte], offset: ptr_uint) -> uint:
73
+ let b0 = uint<-data[offset]
74
+ let b1 = uint<-data[offset + 1z]
75
+ let b2 = uint<-data[offset + 2z]
76
+ let b3 = uint<-data[offset + 3z]
77
+ return (b0 << 24) | (b1 << 16) | (b2 << 8) | b3
78
+
79
+
80
+ function format_ipv4(addr: uint) -> string.String:
81
+ let a = (addr & 0xFFu)
82
+ let b = ((addr >> 8u) & 0xFFu)
83
+ let c = ((addr >> 16u) & 0xFFu)
84
+ let d = ((addr >> 24u) & 0xFFu)
85
+ var s = string.String.with_capacity(16)
86
+ fmt.append_uint(ref_of(s), d)
87
+ s.append(".")
88
+ fmt.append_uint(ref_of(s), c)
89
+ s.append(".")
90
+ fmt.append_uint(ref_of(s), b)
91
+ s.append(".")
92
+ fmt.append_uint(ref_of(s), a)
93
+ let result = string.String.from_str(s.as_str())
94
+ s.release()
95
+ return result
96
+
97
+
98
+ function transaction_id_from_bytes(data: bytes.Bytes) -> array[ubyte, 12]:
99
+ let span = data.as_span()
100
+ var tid = zero[array[ubyte, 12]]
101
+ var i: ptr_uint = 0
102
+ while i < 12z:
103
+ tid[i] = span[i]
104
+ i += 1
105
+ return tid
106
+
107
+
108
+ public function build_allocate_request(tid: array[ubyte, 12]) -> bytes.Bytes:
109
+ var w = bin.Writer.with_capacity(turn_header_len + 8z)
110
+
111
+ w.write_ubyte(0x00)
112
+ w.write_ubyte(0x03)
113
+ w.write_ubyte(0x00)
114
+ w.write_ubyte(0x08)
115
+
116
+ w.write_ubyte(0x21)
117
+ w.write_ubyte(0x12)
118
+ w.write_ubyte(0xA4)
119
+ w.write_ubyte(0x42)
120
+
121
+ var i: ptr_uint = 0
122
+ while i < 12z:
123
+ w.write_ubyte(tid[i])
124
+ i += 1
125
+
126
+ w.write_ubyte(0x00)
127
+ w.write_ubyte(0x19)
128
+ w.write_ubyte(0x00)
129
+ w.write_ubyte(0x04)
130
+ w.write_ubyte(0x11)
131
+ w.write_ubyte(0x00)
132
+ w.write_ubyte(0x00)
133
+ w.write_ubyte(0x00)
134
+
135
+ return w.finish()
136
+
137
+
138
+ public function parse_allocate_response(
139
+ packet: bytes.Bytes,
140
+ expected_tid: array[ubyte, 12]
141
+ ) -> Result[TurnAllocation, Error]:
142
+ let data = packet.as_span()
143
+ if data.len < turn_header_len:
144
+ return Result[TurnAllocation, Error].failure(
145
+ error = turn_error(err_parse_failed, "packet too small for TURN header")
146
+ )
147
+
148
+ let msg_type = read_ushort_be(data, 0z)
149
+ if msg_type == allocate_error:
150
+ return Result[TurnAllocation, Error].failure(
151
+ error = turn_error(err_allocate_rejected, "server rejected allocation")
152
+ )
153
+ if msg_type != allocate_success:
154
+ return Result[TurnAllocation, Error].failure(
155
+ error = turn_error(err_parse_failed, "not an allocate success response")
156
+ )
157
+
158
+ let cookie = read_uint_be(data, 4z)
159
+ if cookie != stun_magic_cookie:
160
+ return Result[TurnAllocation, Error].failure(
161
+ error = turn_error(err_parse_failed, "invalid magic cookie")
162
+ )
163
+
164
+ var j: ptr_uint = 0
165
+ while j < 12z:
166
+ if data[8z + j] != expected_tid[j]:
167
+ return Result[TurnAllocation, Error].failure(
168
+ error = turn_error(err_parse_failed, "transaction ID mismatch")
169
+ )
170
+ j += 1
171
+
172
+ var attr_len: ptr_uint = read_ushort_be(data, 2z)
173
+ var offset: ptr_uint = turn_header_len
174
+ while attr_len >= 4z:
175
+ if offset + 4z > data.len:
176
+ break
177
+ let attr_type = read_ushort_be(data, offset)
178
+ let alen = ptr_uint<-read_ushort_be(data, offset + 2z)
179
+ let padded = (alen + 3z) & (~3z)
180
+ if offset + 4z + alen > data.len:
181
+ break
182
+
183
+ if attr_type == attr_xor_relayed_address and alen >= 8z:
184
+ let family = data[offset + 5z]
185
+ if family == 0x01:
186
+ let xport = read_ushort_be(data, offset + 6z)
187
+ let port = xport ^ ushort<-((stun_magic_cookie >> 16u) & 0xFFFFu)
188
+ let xaddr = read_uint_be(data, offset + 8z)
189
+ let ip = xaddr ^ stun_magic_cookie
190
+ var ip_str = format_ipv4(ip)
191
+ defer ip_str.release()
192
+ let addr_result = net.ipv4(ip_str.as_str(), int<-port)
193
+ match addr_result:
194
+ Result.success as ap:
195
+ return Result[TurnAllocation, Error].success(
196
+ value = TurnAllocation(relay_address = ap.value)
197
+ )
198
+ Result.failure:
199
+ pass
200
+
201
+ offset = offset + 4z + padded
202
+ attr_len = attr_len - 4z - padded
203
+
204
+ return Result[TurnAllocation, Error].failure(
205
+ error = turn_error(err_parse_failed, "no XOR-RELAYED-ADDRESS found")
206
+ )
207
+
208
+
209
+ public async function allocate(
210
+ socket: net.UdpSocket,
211
+ turn_server: net.SocketAddress
212
+ ) -> Result[TurnAllocation, Error]:
213
+ let rand_result = crypto.random_bytes(12)
214
+ match rand_result:
215
+ Result.failure:
216
+ return Result[TurnAllocation, Error].failure(
217
+ error = turn_error(err_tid_failed, "failed to generate transaction ID")
218
+ )
219
+ Result.success as rp:
220
+ let tid = transaction_id_from_bytes(rp.value)
221
+ rp.value.release()
222
+ var request = build_allocate_request(tid)
223
+ defer request.release()
224
+ let send_result = await socket.send_to(request.as_span(), turn_server)
225
+ match send_result:
226
+ Result.failure:
227
+ return Result[TurnAllocation, Error].failure(
228
+ error = turn_error(err_send_failed, "failed to send allocate request")
229
+ )
230
+ Result.success:
231
+ pass
232
+
233
+ var frame: uint = 0
234
+ let recv_task = socket.recv_from(512)
235
+ while frame < 40:
236
+ if aio.completed(recv_task):
237
+ let recv_result = aio.result(recv_task)
238
+ match recv_result:
239
+ Result.failure:
240
+ return Result[TurnAllocation, Error].failure(
241
+ error = turn_error(err_recv_failed, "recv failed")
242
+ )
243
+ Result.success as dp:
244
+ var datagram = dp.value
245
+ let parse_result = parse_allocate_response(datagram.data, tid)
246
+ datagram.data.release()
247
+ datagram.source.release()
248
+ match parse_result:
249
+ Result.failure:
250
+ continue
251
+ Result.success as ap:
252
+ return Result[TurnAllocation, Error].success(value = ap.value)
253
+ await aio.sleep(50)
254
+ frame += 1
255
+
256
+ return Result[TurnAllocation, Error].failure(
257
+ error = turn_error(err_timeout, "allocate request timed out")
258
+ )
259
+
260
+
261
+ function addr_to_raw_ipv4(addr: net.SocketAddress) -> uint:
262
+ let storage = addr.storage else:
263
+ return 0
264
+ let in_ptr = unsafe: ptr[libuv.sockaddr_in]<-storage
265
+ return (unsafe: read(in_ptr)).sin_addr
266
+
267
+
268
+ public function build_send_indication(
269
+ tid: array[ubyte, 12],
270
+ peer: net.SocketAddress,
271
+ data: span[ubyte]
272
+ ) -> Result[bytes.Bytes, Error]:
273
+ let port_result = peer.port()
274
+ match port_result:
275
+ Result.failure:
276
+ return Result[bytes.Bytes, Error].failure(
277
+ error = turn_error(err_invalid_address, "failed to get peer port")
278
+ )
279
+ Result.success as pp:
280
+ let host_port = pp.value
281
+ let xport = ushort<-host_port ^ ushort<-((stun_magic_cookie >> 16u) & 0xFFFFu)
282
+ let ip_raw = addr_to_raw_ipv4(peer)
283
+ let xip = ip_raw ^ stun_magic_cookie
284
+
285
+ let data_len = data.len
286
+ let attr_total: ptr_uint = 12z + data_len
287
+ var w = bin.Writer.with_capacity(turn_header_len + attr_total)
288
+
289
+ w.write_ubyte(0x00)
290
+ w.write_ubyte(0x16)
291
+ w.write_ubyte(ubyte<-((ushort<-attr_total >> 8) & 0xFF))
292
+ w.write_ubyte(ubyte<-(ushort<-attr_total & 0xFF))
293
+ w.write_ubyte(0x21)
294
+ w.write_ubyte(0x12)
295
+ w.write_ubyte(0xA4)
296
+ w.write_ubyte(0x42)
297
+ var i: ptr_uint = 0
298
+ while i < 12z:
299
+ w.write_ubyte(tid[i])
300
+ i += 1
301
+
302
+ w.write_ubyte(0x00)
303
+ w.write_ubyte(0x17)
304
+ w.write_ubyte(0x00)
305
+ w.write_ubyte(0x08)
306
+ w.write_ubyte(0x00)
307
+ w.write_ubyte(0x01)
308
+ w.write_ubyte(ubyte<-((xport >> 8) & 0xFF))
309
+ w.write_ubyte(ubyte<-(xport & 0xFF))
310
+ w.write_ubyte(ubyte<-((xip >> 24) & 0xFF))
311
+ w.write_ubyte(ubyte<-((xip >> 16) & 0xFF))
312
+ w.write_ubyte(ubyte<-((xip >> 8) & 0xFF))
313
+ w.write_ubyte(ubyte<-(xip & 0xFF))
314
+
315
+ w.write_ubyte(0x00)
316
+ w.write_ubyte(0x12)
317
+ w.write_ubyte(ubyte<-((ushort<-data_len >> 8) & 0xFF))
318
+ w.write_ubyte(ubyte<-(ushort<-data_len & 0xFF))
319
+ var j: ptr_uint = 0
320
+ while j < data_len:
321
+ w.write_ubyte(data[j])
322
+ j += 1
323
+
324
+ return Result[bytes.Bytes, Error].success(value = w.finish())
325
+
326
+
327
+ public function parse_data_indication(
328
+ packet: bytes.Bytes
329
+ ) -> Result[TurnDatagram, Error]:
330
+ let data = packet.as_span()
331
+ if data.len < turn_header_len:
332
+ return Result[TurnDatagram, Error].failure(
333
+ error = turn_error(err_parse_failed, "packet too small")
334
+ )
335
+
336
+ let msg_type = read_ushort_be(data, 0z)
337
+ if msg_type != data_indication:
338
+ return Result[TurnDatagram, Error].failure(
339
+ error = turn_error(err_parse_failed, "not a data indication")
340
+ )
341
+
342
+ var attr_len: ptr_uint = read_ushort_be(data, 2z)
343
+ var offset: ptr_uint = turn_header_len
344
+ var found_peer: bool = false
345
+ var peer_addr: net.SocketAddress = zero[net.SocketAddress]
346
+ var found_data: bool = false
347
+ var payload: bytes.Bytes = bytes.Bytes.empty()
348
+
349
+ while attr_len >= 4z:
350
+ if offset + 4z > data.len:
351
+ break
352
+ let attr_type = read_ushort_be(data, offset)
353
+ let alen = ptr_uint<-read_ushort_be(data, offset + 2z)
354
+ let padded = (alen + 3z) & (~3z)
355
+ if offset + 4z + alen > data.len:
356
+ break
357
+
358
+ if attr_type == attr_xor_peer_address and alen >= 8z:
359
+ let family = data[offset + 5z]
360
+ if family == 0x01:
361
+ let xport = read_ushort_be(data, offset + 6z)
362
+ let port = xport ^ ushort<-((stun_magic_cookie >> 16u) & 0xFFFFu)
363
+ let xaddr = read_uint_be(data, offset + 8z)
364
+ let ip = xaddr ^ stun_magic_cookie
365
+ var ip_str = format_ipv4(ip)
366
+ defer ip_str.release()
367
+ let addr_result = net.ipv4(ip_str.as_str(), int<-port)
368
+ match addr_result:
369
+ Result.success as ap:
370
+ peer_addr = ap.value
371
+ found_peer = true
372
+ Result.failure:
373
+ pass
374
+
375
+ if attr_type == attr_data and alen > 0z:
376
+ var buf = bin.Writer.with_capacity(alen)
377
+ var k: ptr_uint = 0
378
+ while k < alen:
379
+ buf.write_ubyte(data[offset + 4z + k])
380
+ k += 1
381
+ payload = buf.finish()
382
+ found_data = true
383
+
384
+ offset = offset + 4z + padded
385
+ attr_len = attr_len - 4z - padded
386
+
387
+ if not found_peer or not found_data:
388
+ if found_data:
389
+ payload.release()
390
+ return Result[TurnDatagram, Error].failure(
391
+ error = turn_error(err_no_data_attribute, "data indication missing attributes")
392
+ )
393
+
394
+ return Result[TurnDatagram, Error].success(
395
+ value = TurnDatagram(peer_address = peer_addr, data = payload)
396
+ )
397
+
398
+
399
+ public async function send_data(
400
+ socket: net.UdpSocket,
401
+ turn_server: net.SocketAddress,
402
+ peer: net.SocketAddress,
403
+ payload: span[ubyte]
404
+ ) -> Result[ptr_uint, Error]:
405
+ let rand_result = crypto.random_bytes(12)
406
+ match rand_result:
407
+ Result.failure:
408
+ return Result[ptr_uint, Error].failure(
409
+ error = turn_error(err_tid_failed, "failed to generate transaction ID")
410
+ )
411
+ Result.success as rp:
412
+ let tid = transaction_id_from_bytes(rp.value)
413
+ rp.value.release()
414
+ let build_result = build_send_indication(tid, peer, payload)
415
+ match build_result:
416
+ Result.failure as bp:
417
+ return Result[ptr_uint, Error].failure(error = bp.error)
418
+ Result.success as bp:
419
+ var packet = bp.value
420
+ defer packet.release()
421
+ let send_result = await socket.send_to(packet.as_span(), turn_server)
422
+ match send_result:
423
+ Result.failure as sp:
424
+ return Result[ptr_uint, Error].failure(
425
+ error = turn_error(err_send_failed, "send indication failed")
426
+ )
427
+ Result.success as nrp:
428
+ return Result[ptr_uint, Error].success(value = nrp.value)
429
+
430
+
431
+ public async function recv_data(
432
+ socket: net.UdpSocket
433
+ ) -> Result[TurnDatagram, Error]:
434
+ var frame: uint = 0
435
+ let recv_task = socket.recv_from(4096)
436
+ while frame < 40:
437
+ if aio.completed(recv_task):
438
+ let recv_result = aio.result(recv_task)
439
+ match recv_result:
440
+ Result.failure:
441
+ return Result[TurnDatagram, Error].failure(
442
+ error = turn_error(err_recv_failed, "recv failed")
443
+ )
444
+ Result.success as dp:
445
+ var datagram = dp.value
446
+ let parse_result = parse_data_indication(datagram.data)
447
+ datagram.data.release()
448
+ datagram.source.release()
449
+ match parse_result:
450
+ Result.failure:
451
+ continue
452
+ Result.success as tp:
453
+ return Result[TurnDatagram, Error].success(value = tp.value)
454
+ await aio.sleep(50)
455
+ frame += 1
456
+
457
+ return Result[TurnDatagram, Error].failure(
458
+ error = turn_error(err_timeout, "recv from relay timed out")
459
+ )