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/stun.mt ADDED
@@ -0,0 +1,252 @@
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.net as net
7
+ import std.string as string
8
+
9
+ const google_stun: str = "stun.l.google.com"
10
+ const google_stun_port: int = 19302
11
+
12
+ const stun_magic_cookie: uint = 0x2112A442
13
+ const stun_header_len: ptr_uint = 20
14
+
15
+ const err_tid_failed: int = -1
16
+ const err_packet_too_small: int = -2
17
+ const err_not_binding_response: int = -3
18
+ const err_bad_cookie: int = -4
19
+ const err_tid_mismatch: int = -5
20
+ const err_no_xor_address: int = -6
21
+ const err_address_failed: int = -7
22
+ const err_send_failed: int = -8
23
+ const err_recv_failed: int = -9
24
+ const err_timeout: int = -10
25
+ const err_bind_failed: int = -11
26
+
27
+ public struct StunResult:
28
+ public_address: net.SocketAddress
29
+
30
+ public struct Error:
31
+ code: int
32
+ message: string.String
33
+
34
+
35
+ extending Error:
36
+ public editable function release() -> void:
37
+ this.message.release()
38
+
39
+
40
+ extending StunResult:
41
+ public editable function release() -> void:
42
+ this.public_address.release()
43
+
44
+
45
+ function stun_error(code: int, msg: str) -> Error:
46
+ return Error(code = code, message = string.String.from_str(msg))
47
+
48
+
49
+ function transaction_id_from_bytes(data: bytes.Bytes) -> array[ubyte, 12]:
50
+ let span = data.as_span()
51
+ var tid = zero[array[ubyte, 12]]
52
+ var i: ptr_uint = 0
53
+ while i < 12z:
54
+ tid[i] = span[i]
55
+ i += 1
56
+ return tid
57
+
58
+
59
+ public function build_binding_request(tid: array[ubyte, 12]) -> bytes.Bytes:
60
+ var w = bin.Writer.with_capacity(stun_header_len)
61
+ w.write_ubyte(0x00)
62
+ w.write_ubyte(0x01)
63
+ w.write_ubyte(0x00)
64
+ w.write_ubyte(0x00)
65
+ w.write_ubyte(0x21)
66
+ w.write_ubyte(0x12)
67
+ w.write_ubyte(0xA4)
68
+ w.write_ubyte(0x42)
69
+ var i: ptr_uint = 0
70
+ while i < 12z:
71
+ w.write_ubyte(tid[i])
72
+ i += 1
73
+ return w.finish()
74
+
75
+
76
+ function read_ushort_be(data: span[ubyte], offset: ptr_uint) -> ushort:
77
+ let hi = uint<-data[offset]
78
+ let lo = uint<-data[offset + 1z]
79
+ return ushort<-((hi << 8) | lo)
80
+
81
+
82
+ function read_uint_be(data: span[ubyte], offset: ptr_uint) -> uint:
83
+ let b0 = uint<-data[offset]
84
+ let b1 = uint<-data[offset + 1z]
85
+ let b2 = uint<-data[offset + 2z]
86
+ let b3 = uint<-data[offset + 3z]
87
+ return (b0 << 24) | (b1 << 16) | (b2 << 8) | b3
88
+
89
+
90
+ function format_ipv4(addr: uint) -> string.String:
91
+ let a = (addr & 0xFFu)
92
+ let b = ((addr >> 8u) & 0xFFu)
93
+ let c = ((addr >> 16u) & 0xFFu)
94
+ let d = ((addr >> 24u) & 0xFFu)
95
+ var s = string.String.with_capacity(16)
96
+ fmt.append_uint(ref_of(s), d)
97
+ s.append(".")
98
+ fmt.append_uint(ref_of(s), c)
99
+ s.append(".")
100
+ fmt.append_uint(ref_of(s), b)
101
+ s.append(".")
102
+ fmt.append_uint(ref_of(s), a)
103
+ let result = string.String.from_str(s.as_str())
104
+ s.release()
105
+ return result
106
+
107
+
108
+ public function parse_binding_response(
109
+ packet: bytes.Bytes,
110
+ expected_tid: array[ubyte, 12]
111
+ ) -> Result[StunResult, Error]:
112
+ let data = packet.as_span()
113
+ if data.len < stun_header_len:
114
+ return Result[StunResult, Error].failure(error = stun_error(
115
+ err_packet_too_small,
116
+ "packet too small for STUN header"
117
+ ))
118
+
119
+ let msg_type = read_ushort_be(data, 0z)
120
+ if msg_type != 0x0101:
121
+ return Result[StunResult, Error].failure(error = stun_error(
122
+ err_not_binding_response,
123
+ "not a binding success response"
124
+ ))
125
+
126
+ var attr_len: ptr_uint = read_ushort_be(data, 2z)
127
+ let cookie = read_uint_be(data, 4z)
128
+ if cookie != stun_magic_cookie:
129
+ return Result[StunResult, Error].failure(error = stun_error(err_bad_cookie, "invalid magic cookie"))
130
+
131
+ var j: ptr_uint = 0
132
+ while j < 12z:
133
+ if data[8z + j] != expected_tid[j]:
134
+ return Result[StunResult, Error].failure(error = stun_error(err_tid_mismatch, "transaction ID mismatch"))
135
+ j += 1
136
+
137
+ var offset: ptr_uint = stun_header_len
138
+ while attr_len >= 4z:
139
+ if offset + 4z > data.len:
140
+ break
141
+ let attr_type = read_ushort_be(data, offset)
142
+ let alen = ptr_uint<-read_ushort_be(data, offset + 2z)
143
+ let padded = (alen + 3z) & (~3z)
144
+ if offset + 4z + alen > data.len:
145
+ break
146
+
147
+ if attr_type == 0x0020 and alen >= 8z and data[offset + 5z] == 0x01:
148
+ let xport = read_ushort_be(data, offset + 6z)
149
+ let port = xport ^ ushort<-((stun_magic_cookie >> 16u) & 0xFFFFu)
150
+ let xaddr = read_uint_be(data, offset + 8z)
151
+ let ip = xaddr ^ stun_magic_cookie
152
+ var ip_str = format_ipv4(ip)
153
+ defer ip_str.release()
154
+ let addr_result = net.ipv4(ip_str.as_str(), int<-port)
155
+ match addr_result:
156
+ Result.failure:
157
+ return Result[StunResult, Error].failure(error = stun_error(
158
+ err_address_failed,
159
+ "failed to construct address"
160
+ ))
161
+ Result.success as addr_payload:
162
+ return Result[StunResult, Error].success(value = StunResult(public_address = addr_payload.value))
163
+
164
+ offset = offset + 4z + padded
165
+ attr_len = attr_len - 4z - padded
166
+
167
+ return Result[StunResult, Error].failure(error = stun_error(
168
+ err_no_xor_address,
169
+ "no XOR-MAPPED-ADDRESS attribute found"
170
+ ))
171
+
172
+
173
+ public async function resolve_public_address(
174
+ socket: net.UdpSocket,
175
+ stun_server: net.SocketAddress
176
+ ) -> Result[StunResult, Error]:
177
+ let rand_result = crypto.random_bytes(12)
178
+ match rand_result:
179
+ Result.failure:
180
+ return Result[StunResult, Error].failure(error = stun_error(
181
+ err_tid_failed,
182
+ "failed to generate transaction ID"
183
+ ))
184
+ Result.success as rp:
185
+ let tid = transaction_id_from_bytes(rp.value)
186
+ rp.value.release()
187
+ var request = build_binding_request(tid)
188
+ defer request.release()
189
+ let send_result = await socket.send_to(request.as_span(), stun_server)
190
+ match send_result:
191
+ Result.failure:
192
+ return Result[StunResult, Error].failure(error = stun_error(
193
+ err_send_failed,
194
+ "failed to send STUN request"
195
+ ))
196
+ Result.success:
197
+ pass
198
+
199
+ var frame: uint = 0
200
+ let recv_task = socket.recv_from(512)
201
+ while frame < 40:
202
+ if aio.completed(recv_task):
203
+ let recv_result = aio.result(recv_task)
204
+ match recv_result:
205
+ Result.failure:
206
+ return Result[StunResult, Error].failure(error = stun_error(err_recv_failed, "recv failed"))
207
+ Result.success as dp:
208
+ var datagram = dp.value
209
+ let parse_result = parse_binding_response(datagram.data, tid)
210
+ datagram.data.release()
211
+ datagram.source.release()
212
+ match parse_result:
213
+ Result.failure:
214
+ continue
215
+ Result.success as srp:
216
+ return Result[StunResult, Error].success(value = srp.value)
217
+ await aio.sleep(50)
218
+ frame += 1
219
+
220
+ return Result[StunResult, Error].failure(error = stun_error(err_timeout, "STUN request timed out"))
221
+
222
+
223
+ public async function resolve_public_address_on(
224
+ runtime: aio.Runtime,
225
+ local_addr: net.SocketAddress,
226
+ stun_server: net.SocketAddress
227
+ ) -> Result[StunResult, Error]:
228
+ let bind_result = net.udp_bind_on(runtime, local_addr)
229
+ match bind_result:
230
+ Result.failure:
231
+ return Result[StunResult, Error].failure(
232
+ error = stun_error(err_bind_failed, "failed to bind socket")
233
+ )
234
+ Result.success as bp:
235
+ var socket = bp.value
236
+ defer socket.release()
237
+ return await resolve_public_address(socket, stun_server)
238
+
239
+
240
+ public async function resolve(
241
+ stun_server: net.SocketAddress
242
+ ) -> Result[StunResult, Error]:
243
+ let local_result = net.ipv4("0.0.0.0", 0)
244
+ match local_result:
245
+ Result.failure:
246
+ return Result[StunResult, Error].failure(
247
+ error = stun_error(err_bind_failed, "failed to create local address")
248
+ )
249
+ Result.success as la:
250
+ var local_addr = la.value
251
+ defer local_addr.release()
252
+ return await resolve_public_address_on(aio.current_runtime(), local_addr, stun_server)
data/std/net/sync.mt ADDED
@@ -0,0 +1,183 @@
1
+ import std.net.mux as mux
2
+ import std.net.session as sess
3
+ import std.vec as vec
4
+
5
+ public struct SyncValue[T]:
6
+ value: T
7
+ dirty: bool
8
+
9
+
10
+ extending SyncValue[T]:
11
+ public editable function set(new_value: T) -> void:
12
+ this.value = new_value
13
+ this.dirty = true
14
+
15
+
16
+ public function get() -> T:
17
+ return this.value
18
+
19
+
20
+ public editable function mark_clean() -> void:
21
+ this.dirty = false
22
+
23
+
24
+ public function has_changed() -> bool:
25
+ return this.dirty
26
+
27
+ public struct SyncList[T]:
28
+ items: vec.Vec[T]
29
+ dirty: bool
30
+
31
+
32
+ extending SyncList[T]:
33
+ public editable function push(item: T) -> void:
34
+ this.items.push(item)
35
+ this.dirty = true
36
+
37
+
38
+ public editable function clear() -> void:
39
+ this.items.clear()
40
+ this.dirty = true
41
+
42
+
43
+ public function len() -> ptr_uint:
44
+ return this.items.len()
45
+
46
+
47
+ public function get(index: ptr_uint) -> ptr[T]?:
48
+ return this.items.get(index)
49
+
50
+
51
+ public function at(index: ptr_uint) -> Option[T]:
52
+ return this.items.at(index)
53
+
54
+
55
+ public editable function mark_clean() -> void:
56
+ this.dirty = false
57
+
58
+
59
+ public function has_changed() -> bool:
60
+ return this.dirty
61
+
62
+ public struct Lerp:
63
+ previous: float
64
+ target: float
65
+ elapsed: float
66
+ duration: float
67
+
68
+
69
+ extending Lerp:
70
+ public editable function set_target(new_target: float, dur: float) -> void:
71
+ this.previous = this.target
72
+ this.target = new_target
73
+ this.elapsed = 0.0
74
+ this.duration = dur
75
+
76
+
77
+ public editable function tick(dt: float) -> void:
78
+ this.elapsed = this.elapsed + dt
79
+
80
+
81
+ public function current() -> float:
82
+ if this.duration <= 0.0:
83
+ return this.target
84
+ var t: float = this.elapsed / this.duration
85
+ if t > 1.0:
86
+ t = 1.0
87
+ return this.previous + (this.target - this.previous) * t
88
+
89
+
90
+ public function has_arrived() -> bool:
91
+ return this.elapsed >= this.duration
92
+
93
+ public struct CompressedUshort:
94
+ min: float
95
+ max: float
96
+
97
+
98
+ extending CompressedUshort:
99
+ public function encode(value: float) -> ushort:
100
+ var clamped: float = value
101
+ if clamped < this.min:
102
+ clamped = this.min
103
+ if clamped > this.max:
104
+ clamped = this.max
105
+ let ratio = (clamped - this.min) / (this.max - this.min)
106
+ return ushort<-(ratio * 65535.0)
107
+
108
+
109
+ public function decode(encoded: ushort) -> float:
110
+ let ratio = float<-encoded / 65535.0
111
+ return this.min + ratio * (this.max - this.min)
112
+
113
+ public struct CompressedUbyte:
114
+ min: float
115
+ max: float
116
+
117
+
118
+ extending CompressedUbyte:
119
+ public function encode(value: float) -> ubyte:
120
+ var clamped: float = value
121
+ if clamped < this.min:
122
+ clamped = this.min
123
+ if clamped > this.max:
124
+ clamped = this.max
125
+ let ratio = (clamped - this.min) / (this.max - this.min)
126
+ return ubyte<-(ratio * 255.0)
127
+
128
+
129
+ public function decode(encoded: ubyte) -> float:
130
+ let ratio = float<-encoded / 255.0
131
+ return this.min + ratio * (this.max - this.min)
132
+
133
+ public struct TickBuffer[T]:
134
+ entries: vec.Vec[T]
135
+ base_tick: uint
136
+
137
+
138
+ extending TickBuffer[T]:
139
+ public editable function push(tick: uint, value: T) -> void:
140
+ let offset: ptr_uint = ptr_uint<-(tick - this.base_tick)
141
+ while offset >= this.entries.len():
142
+ this.entries.push(value)
143
+ return
144
+ let ptr = this.entries.get(offset) else:
145
+ return
146
+ unsafe:
147
+ read(ptr) = value
148
+
149
+
150
+ public function get(tick: uint) -> Option[T]:
151
+ if tick < this.base_tick:
152
+ return Option[T].none()
153
+ let offset: ptr_uint = ptr_uint<-(tick - this.base_tick)
154
+ if offset >= this.entries.len():
155
+ return Option[T].none()
156
+ let ptr = this.entries.get(offset) else:
157
+ return Option[T].none()
158
+ return Option[T].some(value = unsafe: read(ptr))
159
+
160
+
161
+ public function earliest_tick() -> uint:
162
+ return this.base_tick
163
+
164
+
165
+ public function latest_tick() -> uint:
166
+ return this.base_tick + uint<-this.entries.len()
167
+
168
+
169
+ public async function broadcast(
170
+ session: ref[mux.MuxedSession],
171
+ channel_id: ubyte,
172
+ type_id: ushort,
173
+ payload: span[ubyte],
174
+ send_flags: ubyte
175
+ ) -> void:
176
+ var i: ptr_uint = 0
177
+ while i < session.session.peers.len():
178
+ let peer_ptr = session.session.peers.get(i) else:
179
+ break
180
+ let peer_id = unsafe: read(peer_ptr).peer_id
181
+ if unsafe: read(peer_ptr).channel_state != sess.ConnectionState.disconnected:
182
+ let _ = await session.mux_send(peer_id, channel_id, type_id, payload, send_flags)
183
+ i += 1