/__w/smoldot/smoldot/repo/wasm-node/rust/src/bindings.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Smoldot |
2 | | // Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. |
3 | | // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 |
4 | | |
5 | | // This program is free software: you can redistribute it and/or modify |
6 | | // it under the terms of the GNU General Public License as published by |
7 | | // the Free Software Foundation, either version 3 of the License, or |
8 | | // (at your option) any later version. |
9 | | |
10 | | // This program is distributed in the hope that it will be useful, |
11 | | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | // GNU General Public License for more details. |
14 | | |
15 | | // You should have received a copy of the GNU General Public License |
16 | | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | | |
18 | | //! Imports and exports of the WebAssembly module. |
19 | | //! |
20 | | //! This module contains all the functions that tie together the Rust code and its host (i.e. |
21 | | //! the JavaScript code, normally). |
22 | | //! |
23 | | //! The functions found in the `extern` block are the functions that the Rust code *imports*, and |
24 | | //! need to be implemented on the host side and provided to the WebAssembly virtual machine. The |
25 | | //! other functions are functions that the Rust code *exports*, and can be called by the host. |
26 | | //! |
27 | | //! # Re-entrency |
28 | | //! |
29 | | //! As a rule, none of the implementations of the functions that the host provides is allowed |
30 | | //! to call a function exported by Rust. |
31 | | //! |
32 | | //! For example, the implementation of [`start_timer`] isn't allowed to call [`timer_finished`]. |
33 | | //! Instead, it must return, and later [`timer_finished`] be called independently. |
34 | | //! |
35 | | //! This avoids potential stack overflows and tricky borrowing-related situations. |
36 | | //! |
37 | | //! # About `u32`s and JavaScript |
38 | | //! |
39 | | //! Many functions below accept as parameter or return a `u32`. In reality, however, the |
40 | | //! WebAssembly specification doesn't mention unsigned integers. Only signed integers (and |
41 | | //! floating points) can be passed through the FFI layer. |
42 | | //! |
43 | | //! This isn't important when the Rust code provides a value that must later be provided back, as |
44 | | //! the conversion from the guest to the host is symmetrical to the conversion from the host to |
45 | | //! the guest. |
46 | | //! |
47 | | //! It is, however, important when the value needs to be interpreted from the host side, such as |
48 | | //! for example the `message_ptr` parameter of [`panic()`]. When using JavaScript as the host, you |
49 | | //! must do `>>> 0` on all the `u32` values before interpreting them, in order to be certain than |
50 | | //! they are treated as unsigned integers by the JavaScript. |
51 | | //! |
52 | | |
53 | | use alloc::vec::Vec; |
54 | | |
55 | | #[link(wasm_import_module = "smoldot")] |
56 | | extern "C" { |
57 | | /// Must stop the execution immediately. The message is a UTF-8 string found in the memory of |
58 | | /// the WebAssembly at offset `message_ptr` and with length `message_len`. |
59 | | /// |
60 | | /// > **Note**: This function is typically implemented using `throw`. |
61 | | /// |
62 | | /// After this function has been called, no further Wasm functions must be called again on |
63 | | /// this Wasm virtual machine. Explanation below. |
64 | | /// |
65 | | /// # About throwing and safety |
66 | | /// |
67 | | /// Rust programs can be configured in two panicking modes: `abort`, or `unwind`. Safe or |
68 | | /// unsafe Rust code must be written by keeping in mind that the execution of a function can |
69 | | /// be suddenly interrupted by a panic, but can rely on the fact that this panic will either |
70 | | /// completely abort the program, or unwind the stack. In the latter case, they can rely on |
71 | | /// the fact that `std::panic::catch_unwind` will catch this unwinding and let them perform |
72 | | /// some additional clean-ups. |
73 | | /// |
74 | | /// This function is typically implemented using `throw`. However, "just" throwing a JavaScript |
75 | | /// exception from within the implementation of this function is neither `abort`, because the |
76 | | /// JavaScript could call into the Wasm again later, nor `unwind`, because it isn't caught by |
77 | | /// `std::panic::catch_unwind`. By being neither of the two, it breaks the assumptions that |
78 | | /// some Rust codes might rely on for either correctness or safety. |
79 | | /// In order to solve this problem, we enforce that `panic` must behave like `abort`, and |
80 | | /// forbid calling into the Wasm virtual machine again. |
81 | | /// |
82 | | /// Beyond the `panic` function itself, any other FFI function that throws must similarly |
83 | | /// behave like `abort` and prevent any further execution. |
84 | | pub fn panic(message_ptr: u32, message_len: u32); |
85 | | |
86 | | /// Called in response to [`add_chain`] once the initialization of the chain is complete. |
87 | | /// |
88 | | /// If `error_msg_ptr` is equal to 0, then the chain initialization is successful. Otherwise, |
89 | | /// `error_msg_ptr` and `error_msg_len` designate a buffer in the memory of the WebAssembly |
90 | | /// virtual machine where a UTF-8 diagnostic error message can be found. |
91 | | pub fn chain_initialized(chain_id: u32, error_msg_ptr: u32, error_msg_len: u32); |
92 | | |
93 | | /// Fills the buffer of the WebAssembly virtual machine with random data, starting at `ptr` |
94 | | /// and for `len` bytes. |
95 | | /// |
96 | | /// This data will be used in order to generate secrets. Do not use a dummy implementation! |
97 | | pub fn random_get(ptr: u32, len: u32); |
98 | | |
99 | | /// Returns the system clock in number of microseconds since the UNIX epoch, ignoring leap |
100 | | /// seconds. |
101 | | /// |
102 | | /// This clock is allowed to go backwards. |
103 | | /// |
104 | | /// Must never return a negative number. Implementers should be aware that the system clock |
105 | | /// can be negative, and abort execution if that is the case. |
106 | | pub fn unix_timestamp_us() -> u64; |
107 | | |
108 | | /// Returns the number of microseconds since an especified point in time. Must never decrease |
109 | | /// over time. |
110 | | pub fn monotonic_clock_us() -> u64; |
111 | | |
112 | | /// Copies the entire content of the buffer with the given index to the memory of the |
113 | | /// WebAssembly at offset `target_pointer`. |
114 | | /// |
115 | | /// In situations where a buffer must be provided from the JavaScript to the Rust code, the |
116 | | /// JavaScript must (prior to calling the Rust function that requires the buffer) assign a |
117 | | /// "buffer index" to the buffer it wants to provide. The Rust code then calls the |
118 | | /// [`buffer_size`] and [`buffer_copy`] functions in order to obtain the length and content |
119 | | /// of the buffer. |
120 | | pub fn buffer_copy(buffer_index: u32, target_pointer: u32); |
121 | | |
122 | | /// Returns the size (in bytes) of the buffer with the given index. |
123 | | /// |
124 | | /// See the documentation of [`buffer_copy`] for context. |
125 | | pub fn buffer_size(buffer_index: u32) -> u32; |
126 | | |
127 | | /// The queue of JSON-RPC responses of the given chain is no longer empty. |
128 | | /// |
129 | | /// This function is only ever called after [`json_rpc_responses_peek`] has returned a `len` |
130 | | /// of 0. |
131 | | /// |
132 | | /// This function might be called spuriously, however this behavior must not be relied upon. |
133 | | pub fn json_rpc_responses_non_empty(chain_id: u32); |
134 | | |
135 | | /// Client is emitting a log entry. |
136 | | /// |
137 | | /// Each log entry is made of a log level (`1 = Error, 2 = Warn, 3 = Info, 4 = Debug, |
138 | | /// 5 = Trace`), a log target (e.g. "network"), and a log message. |
139 | | /// |
140 | | /// The log target and message is a UTF-8 string found in the memory of the WebAssembly |
141 | | /// virtual machine at offset `ptr` and with length `len`. |
142 | | pub fn log(level: u32, target_ptr: u32, target_len: u32, message_ptr: u32, message_len: u32); |
143 | | |
144 | | /// Called when [`advance_execution`] should be executed again. |
145 | | /// |
146 | | /// This function might be called from within [`advance_execution`], in which case |
147 | | /// [`advance_execution`] should be called again immediately after it returns. |
148 | | pub fn advance_execution_ready(); |
149 | | |
150 | | /// After at least `milliseconds` milliseconds have passed, [`timer_finished`] must be called. |
151 | | /// |
152 | | /// It is not a logic error to call [`timer_finished`] *before* `milliseconds` milliseconds |
153 | | /// have passed, and this will likely cause smoldot to restart a new timer for the remainder |
154 | | /// of the duration. |
155 | | /// |
156 | | /// When [`timer_finished`] is called, the value of the monotonic clock (in the bindings) |
157 | | /// must have increased by at least the given number of `milliseconds`. |
158 | | /// |
159 | | /// If `milliseconds` is 0, [`timer_finished`] should be called as soon as possible. |
160 | | /// |
161 | | /// `milliseconds` never contains a negative number, `NaN` or infinite. |
162 | | pub fn start_timer(milliseconds: f64); |
163 | | |
164 | | /// Must return the host supports connecting to a certain type of address. |
165 | | /// |
166 | | /// The `ty` parameter is equal to the first byte of the encoded address that would be passed |
167 | | /// to [`connection_new`]. See [`connection_new`] for more information. |
168 | | /// |
169 | | /// An additional `ty` value of `7` is supported, and means "non-secure WebSocket connection |
170 | | /// to localhost". |
171 | | /// |
172 | | /// Returns a non-zero value if the address is supported. Returns `0` if the address isn't |
173 | | /// supported. |
174 | | pub fn connection_type_supported(ty: u8) -> u32; |
175 | | |
176 | | /// Must initialize a new connection that tries to connect to the given address. |
177 | | /// |
178 | | /// The address to connect to is in the WebAssembly memory at offset `addr_ptr` and with |
179 | | /// `addr_len` bytes. The format is as follows: |
180 | | /// |
181 | | /// - One `type` byte (see below). |
182 | | /// - Two big-endian bytes representing the port (either TCP or UDP depending on the `type`) |
183 | | /// to connect to. |
184 | | /// - (optional) The 32 bytes SHA-256 hash of the certificate of the remote. |
185 | | /// - An UTF-8-encoded IP address or domain name. Use the `addr_len` parameter to determine |
186 | | /// its length. When using an IPv4, it is encoded as `a.b.c.d`. When using an IPv6, it is |
187 | | /// encoded according to RFC5952. |
188 | | /// |
189 | | /// The `type` byte defines the type of connection and whether the optional field is present: |
190 | | /// |
191 | | /// - `0`: TCP/IPv4 connection, with a port and an IPv4 address. |
192 | | /// - `1`: TCP/IPv6 connection, with a port and an IPv6 address. |
193 | | /// - `2`: TCP/IP connection, with a port and a domain name. |
194 | | /// - `4`: WebSocket connection, with a port and an IPv4 address. |
195 | | /// - `5`: WebSocket connection, with a port and an IPv6 address. |
196 | | /// - `6`: WebSocket connection, with a port and a domain name. |
197 | | /// - `14`: WebSocket secure connection, with a port and a domaine name. |
198 | | /// - `16`: WebRTC connection, with a port, an IPv4 address, and a remote certificate hash. |
199 | | /// - `17`: WebRTC connection, with a port, an IPv6 address, and a remote certificate hash. |
200 | | /// |
201 | | /// > **Note**: While these numbers seem arbitrary, they actually loosely follow a certain |
202 | | /// > scheme. The lowest 2 bits indicate the type of IP address, while the highest |
203 | | /// > bits indicate the type of connection. |
204 | | /// |
205 | | /// The `id` parameter is an identifier for this connection, as chosen by the Rust code. It |
206 | | /// must be passed on every interaction with this connection. |
207 | | /// |
208 | | /// At any time, a connection can be in either the `Open` (the initial state) or the `Reset` |
209 | | /// state. |
210 | | /// When in the `Open` state, the connection can transition to the `Reset` state if the remote |
211 | | /// closes the connection or refuses the connection altogether. When that happens, |
212 | | /// [`connection_reset`] must be called. Once in the `Reset` state, the connection cannot |
213 | | /// transition back to the `Open` state. |
214 | | /// |
215 | | /// If the connection is a multistream connection, then |
216 | | /// [`connection_multi_stream_set_handshake_info`] must later be called as soon as possible. |
217 | | /// |
218 | | /// There exists two kind of connections: single-stream and multi-stream. Single-stream |
219 | | /// connections are assumed to have a single stream open at all time and the encryption and |
220 | | /// multiplexing are handled internally by smoldot. Multi-stream connections open and close |
221 | | /// streams over time using [`connection_stream_opened`] and [`stream_reset`], and the |
222 | | /// encryption and multiplexing are handled by the user of these bindings. |
223 | | pub fn connection_new(id: u32, addr_ptr: u32, addr_len: u32); |
224 | | |
225 | | /// Abruptly close a connection previously initialized with [`connection_new`]. |
226 | | /// |
227 | | /// This destroys the identifier passed as parameter. This identifier must never be passed |
228 | | /// through the FFI boundary, unless the same identifier is later allocated again with |
229 | | /// [`connection_new`]. |
230 | | /// |
231 | | /// Must never be called if [`connection_reset`] has been called on that object in the past. |
232 | | /// |
233 | | /// The connection must be closed in the background. The Rust code isn't interested in incoming |
234 | | /// messages from this connection anymore. |
235 | | /// |
236 | | /// > **Note**: In JavaScript, remember to unregister event handlers before calling for |
237 | | /// > example `WebSocket.close()`. |
238 | | pub fn reset_connection(id: u32); |
239 | | |
240 | | /// Queues a new outbound substream opening. The [`connection_stream_opened`] function must |
241 | | /// later be called when the substream has been successfully opened. |
242 | | /// |
243 | | /// This function will only be called for multi-stream connections. The connection must |
244 | | /// currently be in the `Open` state. See the documentation of [`connection_new`] for details. |
245 | | /// |
246 | | /// > **Note**: No mechanism exists in this API to handle the situation where a substream fails |
247 | | /// > to open, as this is not supposed to happen. If you need to handle such a |
248 | | /// > situation, either try again opening a substream again or reset the entire |
249 | | /// > connection. |
250 | | pub fn connection_stream_open(connection_id: u32); |
251 | | |
252 | | /// Abruptly closes an existing substream of a multi-stream connection. The substream must |
253 | | /// currently be in the `Open` state. |
254 | | /// |
255 | | /// Must never be called if [`stream_reset`] has been called on that object in the past. |
256 | | /// |
257 | | /// This function will only be called for multi-stream connections. The connection must |
258 | | /// currently be in the `Open` state. See the documentation of [`connection_new`] for details. |
259 | | pub fn connection_stream_reset(connection_id: u32, stream_id: u32); |
260 | | |
261 | | /// Queues data on the given stream. |
262 | | /// |
263 | | /// `ptr` is a memory address where `len` consecutive elements of type [`StreamSendIoVector`] |
264 | | /// are found. Each element consists in two little-endian 32 bits unsigned integers: the first |
265 | | /// one is a pointer, and the second one is a length in bytes. The data to write on the stream |
266 | | /// consists in the concatenation of all these buffers. |
267 | | /// |
268 | | /// > **Note**: This interface is similar the famous UNIX function `writev`. `ptr` is the same |
269 | | /// > as `iov`, and `len` the same as `iovcnt`. |
270 | | /// > See <https://linux.die.net/man/2/writev>. |
271 | | /// |
272 | | /// If `connection_id` is a single-stream connection, then the value of `stream_id` should |
273 | | /// be ignored. If `connection_id` is a multi-stream connection, then the value of `stream_id` |
274 | | /// contains the identifier of the stream on which to send the data, as was provided to |
275 | | /// [`connection_stream_opened`]. |
276 | | /// |
277 | | /// The connection associated with that stream (and, in the case of a multi-stream connection, |
278 | | /// the stream itself must currently be in the `Open` state. See the documentation of |
279 | | /// [`connection_new`] for details. |
280 | | /// |
281 | | /// The size of the buffer must not exceed the number of writable bytes of the given stream. |
282 | | /// Use [`stream_writable_bytes`] to notify that more data can be sent on the stream. |
283 | | pub fn stream_send(connection_id: u32, stream_id: u32, ptr: u32, len: u32); |
284 | | |
285 | | /// Close the sending side of the given stream of the given connection. |
286 | | /// |
287 | | /// Never called for connection types where this isn't possible to implement (i.e. WebSocket |
288 | | /// and WebRTC at the moment). |
289 | | /// |
290 | | /// If `connection_id` is a single-stream connection, then the value of `stream_id` should |
291 | | /// be ignored. If `connection_id` is a multi-stream connection, then the value of `stream_id` |
292 | | /// contains the identifier of the stream whose sending side should be closed, as was provided |
293 | | /// to [`connection_stream_opened`]. |
294 | | /// |
295 | | /// The connection associated with that stream (and, in the case of a multi-stream connection, |
296 | | /// the stream itself must currently be in the `Open` state. See the documentation of |
297 | | /// [`connection_new`] for details. |
298 | | pub fn stream_send_close(connection_id: u32, stream_id: u32); |
299 | | |
300 | | /// Called when the Wasm execution enters the context of a certain task. This is useful for |
301 | | /// debugging purposes. |
302 | | /// |
303 | | /// Only one task can be currently executing at any time. |
304 | | /// |
305 | | /// The name of the task is a UTF-8 string found in the memory of the WebAssembly virtual |
306 | | /// machine at offset `ptr` and with length `len`. |
307 | | pub fn current_task_entered(ptr: u32, len: u32); |
308 | | |
309 | | /// Called when the Wasm execution leave the context of a certain task. This is useful for |
310 | | /// debugging purposes. |
311 | | /// |
312 | | /// Only one task can be currently executing at any time. |
313 | | pub fn current_task_exit(); |
314 | | } |
315 | | |
316 | | /// See [`stream_send`]. |
317 | | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
318 | | #[repr(C)] |
319 | | pub struct StreamSendIoVector { |
320 | | /// Pointer to a buffer of data to write. |
321 | | pub ptr: u32, |
322 | | /// Length of the buffer of data. |
323 | | pub len: u32, |
324 | | } |
325 | | |
326 | | /// Initializes the client. |
327 | | /// |
328 | | /// This is the first function that must be called. Failure to do so before calling another |
329 | | /// method will lead to a Rust panic. Calling this function multiple times will also lead to a |
330 | | /// panic. |
331 | | /// |
332 | | /// The client will emit log messages by calling the [`log()`] function, provided the log level is |
333 | | /// inferior or equal to the value of `max_log_level` passed here. |
334 | | #[no_mangle] |
335 | 0 | pub extern "C" fn init(max_log_level: u32) { |
336 | 0 | crate::init(max_log_level); |
337 | 0 | } |
338 | | |
339 | | /// Advances the execution of the client, performing CPU-heavy tasks. |
340 | | /// |
341 | | /// This function **must** be called regularly, otherwise nothing will happen. |
342 | | /// |
343 | | /// After this function is called or during a call to this function, [`advance_execution_ready`] |
344 | | /// might be called, indicating that [`advance_execution`] should be called again. |
345 | | #[no_mangle] |
346 | 0 | pub extern "C" fn advance_execution() { |
347 | 0 | super::advance_execution() |
348 | 0 | } |
349 | | |
350 | | /// Adds a chain to the client. The client will try to stay connected and synchronize this chain. |
351 | | /// |
352 | | /// Assign a so-called "buffer index" (a `u32`) representing the chain specification, database |
353 | | /// content, and list of potential relay chains, then provide these buffer indices to the function. |
354 | | /// The Rust code will call [`buffer_size`] and [`buffer_copy`] in order to obtain the content of |
355 | | /// these buffers. The buffer indices can be de-assigned and buffers destroyed once this function |
356 | | /// returns. |
357 | | /// |
358 | | /// The content of the chain specification and database content must be in UTF-8. |
359 | | /// |
360 | | /// > **Note**: The database content is an opaque string that can be obtained by calling |
361 | | /// > the `chainHead_unstable_finalizedDatabase` JSON-RPC function. |
362 | | /// |
363 | | /// The list of potential relay chains is a buffer containing a list of 32-bits-little-endian chain |
364 | | /// ids. If the chain specification refer to a parachain, these chain ids are the ones that will be |
365 | | /// looked up to find the corresponding relay chain. |
366 | | /// |
367 | | /// `json_rpc_max_pending_requests` indicates the size of the queue of JSON-RPC requests that |
368 | | /// haven't been answered yet. |
369 | | /// If `json_rpc_max_pending_requests` is 0, then no JSON-RPC service will be started and it is |
370 | | /// forbidden to send JSON-RPC requests targeting this chain. This can be used to save up |
371 | | /// resources. |
372 | | /// If `json_rpc_max_pending_requests` is 0, then the value of `json_rpc_max_subscriptions` is |
373 | | /// ignored. |
374 | | /// |
375 | | /// Calling this function allocates a chain id and starts the chain initialization in the |
376 | | /// background. Once the initialization is complete, the [`chain_initialized`] function will be |
377 | | /// called by smoldot. |
378 | | /// It is possible to call [`remove_chain`] while the initialization is still in progress in |
379 | | /// order to cancel it. |
380 | | #[no_mangle] |
381 | 0 | pub extern "C" fn add_chain( |
382 | 0 | chain_spec_buffer_index: u32, |
383 | 0 | database_content_buffer_index: u32, |
384 | 0 | json_rpc_max_pending_requests: u32, |
385 | 0 | json_rpc_max_subscriptions: u32, |
386 | 0 | potential_relay_chains_buffer_index: u32, |
387 | 0 | ) -> u32 { |
388 | 0 | super::add_chain( |
389 | 0 | get_buffer(chain_spec_buffer_index), |
390 | 0 | get_buffer(database_content_buffer_index), |
391 | 0 | json_rpc_max_pending_requests, |
392 | 0 | json_rpc_max_subscriptions, |
393 | 0 | get_buffer(potential_relay_chains_buffer_index), |
394 | 0 | ) |
395 | 0 | } |
396 | | |
397 | | /// Removes a chain previously added using [`add_chain`]. Instantly unsubscribes all the JSON-RPC |
398 | | /// subscriptions and cancels all in-progress requests corresponding to that chain. |
399 | | /// |
400 | | /// Can be called on a chain which hasn't finished initializing yet. |
401 | | #[no_mangle] |
402 | 0 | pub extern "C" fn remove_chain(chain_id: u32) { |
403 | 0 | super::remove_chain(chain_id); |
404 | 0 | } |
405 | | |
406 | | /// Emit a JSON-RPC request or notification towards the given chain previously added using |
407 | | /// [`add_chain`]. |
408 | | /// |
409 | | /// A buffer containing a UTF-8 JSON-RPC request or notification must be passed as parameter. The |
410 | | /// format of the JSON-RPC requests and notifications is described in |
411 | | /// [the standard JSON-RPC 2.0 specification](https://www.jsonrpc.org/specification). |
412 | | /// |
413 | | /// If the buffer isn't a valid JSON-RPC request, then an error JSON-RPC response with an `id` |
414 | | /// equal to `null` is generated, in accordance with the JSON-RPC 2.0 specification. |
415 | | /// |
416 | | /// Assign a so-called "buffer index" (a `u32`) representing the buffer containing the UTF-8 |
417 | | /// request, then provide this buffer index to the function. The Rust code will call |
418 | | /// [`buffer_size`] and [`buffer_copy`] in order to obtain the content of this buffer. The buffer |
419 | | /// index can be de-assigned and buffer destroyed once this function returns. |
420 | | /// |
421 | | /// Responses and notifications are notified using [`json_rpc_responses_non_empty`], and can |
422 | | /// be read with [`json_rpc_responses_peek`]. |
423 | | /// |
424 | | /// It is forbidden to call this function on a chain which hasn't finished initializing yet or a |
425 | | /// chain that was created with `json_rpc_running` equal to 0. |
426 | | /// |
427 | | /// This function returns: |
428 | | /// - 0 on success. |
429 | | /// - 1 if the chain has too many pending JSON-RPC requests and refuses to queue another one. |
430 | | /// |
431 | | #[no_mangle] |
432 | 0 | pub extern "C" fn json_rpc_send(text_buffer_index: u32, chain_id: u32) -> u32 { |
433 | 0 | super::json_rpc_send(get_buffer(text_buffer_index), chain_id) |
434 | 0 | } |
435 | | |
436 | | /// Obtains information about the first response in the queue of JSON-RPC responses. |
437 | | /// |
438 | | /// This function returns a pointer within the memory of the WebAssembly virtual machine where is |
439 | | /// stored a struct of type [`JsonRpcResponseInfo`]. This pointer remains valid until |
440 | | /// [`json_rpc_responses_pop`] or [`remove_chain`] is called with the same `chain_id`. |
441 | | /// |
442 | | /// The response or notification is a UTF-8 string found in the memory of the WebAssembly |
443 | | /// virtual machine at offset `ptr` and with length `len`, where `ptr` and `len` are found in the |
444 | | /// [`JsonRpcResponseInfo`]. |
445 | | /// |
446 | | /// If `len` is equal to 0, this indicates that the queue of JSON-RPC responses is empty. |
447 | | /// When a `len` of 0 is returned, [`json_rpc_responses_non_empty`] will later be called to |
448 | | /// indicate that it is no longer empty. |
449 | | /// |
450 | | /// After having read the response or notification, use [`json_rpc_responses_pop`] to remove it |
451 | | /// from the queue. You can then call [`json_rpc_responses_peek`] again to read the next response. |
452 | | #[no_mangle] |
453 | 0 | pub extern "C" fn json_rpc_responses_peek(chain_id: u32) -> u32 { |
454 | 0 | super::json_rpc_responses_peek(chain_id) |
455 | 0 | } |
456 | | |
457 | | /// See [`json_rpc_responses_peek`]. |
458 | | #[repr(C)] |
459 | | pub struct JsonRpcResponseInfo { |
460 | | /// Pointer in memory where the JSON-RPC response can be found. |
461 | | pub ptr: u32, |
462 | | /// Length of the JSON-RPC response in bytes. If 0, indicates that the queue is empty. |
463 | | pub len: u32, |
464 | | } |
465 | | |
466 | | /// Removes the first response from the queue of JSON-RPC responses. This is the response whose |
467 | | /// information can be retrieved using [`json_rpc_responses_peek`]. |
468 | | /// |
469 | | /// Calling this function invalidates the pointer previously returned by a call to |
470 | | /// [`json_rpc_responses_peek`] with the same `chain_id`. |
471 | | /// |
472 | | /// It is forbidden to call this function on a chain that hasn't finished initializing yet, or a |
473 | | /// chain that was created with `json_rpc_running` equal to 0. |
474 | | #[no_mangle] |
475 | 0 | pub extern "C" fn json_rpc_responses_pop(chain_id: u32) { |
476 | 0 | super::json_rpc_responses_pop(chain_id); |
477 | 0 | } |
478 | | |
479 | | /// Must be called in response to [`start_timer`] after the given duration has passed. |
480 | | #[no_mangle] |
481 | 0 | pub extern "C" fn timer_finished() { |
482 | 0 | crate::timers::timer_finished(); |
483 | 0 | } |
484 | | |
485 | | /// Called by the JavaScript code in order to provide information about a multistream connection. |
486 | | /// |
487 | | /// Must be called at most once per connection object. |
488 | | /// |
489 | | /// See also [`connection_new`]. |
490 | | /// |
491 | | /// Assign a so-called "buffer index" (a `u32`) representing the buffer containing the handshake |
492 | | /// type, then provide this buffer index to the function. The Rust code will call [`buffer_size`] |
493 | | /// and [`buffer_copy`] in order to obtain the content of this buffer. The buffer index can be |
494 | | /// de-assigned and buffer destroyed once this function returns. |
495 | | /// |
496 | | /// The buffer must contain a single 0 byte (indicating WebRTC), followed with the SHA-256 hash of |
497 | | /// the local node's TLS certificate. |
498 | | #[no_mangle] |
499 | 0 | pub extern "C" fn connection_multi_stream_set_handshake_info( |
500 | 0 | connection_id: u32, |
501 | 0 | handshake_ty_buffer_index: u32, |
502 | 0 | ) { |
503 | 0 | crate::platform::connection_multi_stream_set_handshake_info( |
504 | 0 | connection_id, |
505 | 0 | get_buffer(handshake_ty_buffer_index), |
506 | 0 | ); |
507 | 0 | } |
508 | | |
509 | | /// Notify of a message being received on the stream. The connection associated with that stream |
510 | | /// (and, in the case of a multi-stream connection, the stream itself) must be in the `Open` state. |
511 | | /// |
512 | | /// Assign a so-called "buffer index" (a `u32`) representing the buffer containing the message, |
513 | | /// then provide this buffer index to the function. The Rust code will call [`buffer_size`] and |
514 | | /// [`buffer_copy`] in order to obtain the content of this buffer. The buffer index can be |
515 | | /// de-assigned and buffer destroyed once this function returns. |
516 | | /// |
517 | | /// If `connection_id` is a single-stream connection, then the value of `stream_id` is ignored. |
518 | | /// If `connection_id` is a multi-stream connection, then `stream_id` corresponds to the stream |
519 | | /// on which the data was received, as was provided to [`connection_stream_opened`]. |
520 | | /// |
521 | | /// See also [`connection_new`]. |
522 | | #[no_mangle] |
523 | 0 | pub extern "C" fn stream_message(connection_id: u32, stream_id: u32, buffer_index: u32) { |
524 | 0 | crate::platform::stream_message(connection_id, stream_id, get_buffer(buffer_index)); |
525 | 0 | } |
526 | | |
527 | | /// Notify that extra bytes can be written onto the stream. The connection associated with that |
528 | | /// stream (and, in the case of a multi-stream connection, the stream itself) must be in the |
529 | | /// `Open` state. |
530 | | /// |
531 | | /// The total of writable bytes must not go beyond reasonable values (e.g. a few megabytes). It |
532 | | /// is not legal to provide a dummy implementation that simply passes an exceedingly large value. |
533 | | /// |
534 | | /// If `connection_id` is a single-stream connection, then the value of `stream_id` is ignored. |
535 | | /// If `connection_id` is a multi-stream connection, then `stream_id` corresponds to the stream |
536 | | /// on which the data was received, as was provided to [`connection_stream_opened`]. |
537 | | #[no_mangle] |
538 | 0 | pub extern "C" fn stream_writable_bytes(connection_id: u32, stream_id: u32, num_bytes: u32) { |
539 | 0 | crate::platform::stream_writable_bytes(connection_id, stream_id, num_bytes); |
540 | 0 | } |
541 | | |
542 | | /// Called by the JavaScript code when the given multi-stream connection has a new substream. |
543 | | /// |
544 | | /// `connection_id` *must* be a multi-stream connection. |
545 | | /// |
546 | | /// The value of `stream_id` is chosen at the discretion of the caller. It is illegal to use the |
547 | | /// same `stream_id` as an existing stream on that same connection that is still open. |
548 | | /// |
549 | | /// For the `outbound` parameter, pass `0` if the substream has been opened by the remote, and any |
550 | | /// value other than `0` if the substream has been opened in response to a call to |
551 | | /// [`connection_stream_open`]. |
552 | | #[no_mangle] |
553 | 0 | pub extern "C" fn connection_stream_opened(connection_id: u32, stream_id: u32, outbound: u32) { |
554 | 0 | crate::platform::connection_stream_opened(connection_id, stream_id, outbound); |
555 | 0 | } |
556 | | |
557 | | /// Can be called at any point by the JavaScript code if the connection switches to the `Reset` |
558 | | /// state. |
559 | | /// |
560 | | /// Must only be called once per connection object. |
561 | | /// Must never be called if [`reset_connection`] has been called on that object in the past. |
562 | | /// |
563 | | /// Assign a so-called "buffer index" (a `u32`) representing the buffer containing the UTF-8 |
564 | | /// reason for closing, then provide this buffer index to the function. The Rust code will call |
565 | | /// [`buffer_size`] and [`buffer_copy`] in order to obtain the content of this buffer. The buffer |
566 | | /// index can be de-assigned and buffer destroyed once this function returns. |
567 | | /// |
568 | | /// See also [`connection_new`]. |
569 | | #[no_mangle] |
570 | 0 | pub extern "C" fn connection_reset(connection_id: u32, buffer_index: u32) { |
571 | 0 | crate::platform::connection_reset(connection_id, get_buffer(buffer_index)); |
572 | 0 | } |
573 | | |
574 | | /// Can be called at any point by the JavaScript code if the stream switches to the `Reset` |
575 | | /// state. |
576 | | /// |
577 | | /// Must only be called once per stream. |
578 | | /// Must never be called if [`connection_stream_reset`] has been called on that object in the past. |
579 | | /// |
580 | | /// The `stream_id` becomes dead and can be re-used for another stream on the same connection. |
581 | | /// |
582 | | /// It is illegal to call this function on a single-stream connections. |
583 | | /// |
584 | | /// Assign a so-called "buffer index" (a `u32`) representing the buffer containing the UTF-8 |
585 | | /// reason for closing, then provide this buffer index to the function. The Rust code will call |
586 | | /// [`buffer_size`] and [`buffer_copy`] in order to obtain the content of this buffer. The buffer |
587 | | /// index can be de-assigned and buffer destroyed once this function returns. |
588 | | /// |
589 | | /// See also [`connection_new`]. |
590 | | #[no_mangle] |
591 | 0 | pub extern "C" fn stream_reset(connection_id: u32, stream_id: u32, buffer_index: u32) { |
592 | 0 | crate::platform::stream_reset(connection_id, stream_id, get_buffer(buffer_index)); |
593 | 0 | } |
594 | | |
595 | 0 | pub(crate) fn get_buffer(buffer_index: u32) -> Vec<u8> { |
596 | 0 | unsafe { |
597 | 0 | let len = usize::try_from(buffer_size(buffer_index)).unwrap(); |
598 | 0 |
|
599 | 0 | let mut buffer = Vec::<u8>::with_capacity(len); |
600 | 0 | buffer_copy( |
601 | 0 | buffer_index, |
602 | 0 | buffer.spare_capacity_mut().as_mut_ptr() as usize as u32, |
603 | 0 | ); |
604 | 0 | buffer.set_len(len); |
605 | 0 | buffer |
606 | 0 | } |
607 | 0 | } |