rns_embedded_ffi/lib_parts/
rns_embedded_node_get_lifecycle_stat.rs1#[no_mangle]
2pub extern "C" fn rns_embedded_node_get_lifecycle_state(
3 node: *mut RnsEmbeddedNode,
4) -> RnsEmbeddedLifecycleState {
5 let Some(node) = node_mut(node) else {
6 return RnsEmbeddedLifecycleState::Boot;
7 };
8 match node.runtime.lifecycle_state() {
9 NodeLifecycleState::Boot => RnsEmbeddedLifecycleState::Boot,
10 NodeLifecycleState::Unprovisioned => RnsEmbeddedLifecycleState::Unprovisioned,
11 NodeLifecycleState::ProvisionedOffline => RnsEmbeddedLifecycleState::ProvisionedOffline,
12 NodeLifecycleState::TcpOnline => RnsEmbeddedLifecycleState::TcpOnline,
13 NodeLifecycleState::BleRecovery => RnsEmbeddedLifecycleState::BleRecovery,
14 NodeLifecycleState::FailureReconnect => RnsEmbeddedLifecycleState::FailureReconnect,
15 }
16}
17
18#[no_mangle]
19pub extern "C" fn rns_embedded_node_push_inbound_wire(
20 node: *mut RnsEmbeddedNode,
21 bytes_ptr: *const u8,
22 bytes_len: usize,
23) -> RnsEmbeddedStatus {
24 let Some(node) = node_mut(node) else {
25 return RnsEmbeddedStatus::InvalidArgument;
26 };
27 let Some(bytes) = byte_slice(bytes_ptr, bytes_len) else {
28 return RnsEmbeddedStatus::InvalidArgument;
29 };
30 map_status(node.transport.push_inbound_wire(bytes))
31}
32
33#[no_mangle]
34pub extern "C" fn rns_embedded_node_take_outbound_wire(
35 node: *mut RnsEmbeddedNode,
36 out_ptr: *mut u8,
37 out_capacity: usize,
38 out_len: *mut usize,
39) -> RnsEmbeddedStatus {
40 let Some(node) = node_mut(node) else {
41 return RnsEmbeddedStatus::InvalidArgument;
42 };
43 if out_ptr.is_null() || out_len.is_null() {
44 return RnsEmbeddedStatus::InvalidArgument;
45 }
46
47 let Some(frame) = node.transport.take_outbound_wire() else {
48 unsafe {
50 *out_len = 0;
51 }
52 return RnsEmbeddedStatus::NotFound;
53 };
54 if frame.len() > out_capacity {
55 unsafe {
57 *out_len = frame.len();
58 }
59 return RnsEmbeddedStatus::Backpressure;
60 }
61 unsafe {
65 core::ptr::copy_nonoverlapping(frame.as_ptr(), out_ptr, frame.len());
66 *out_len = frame.len();
67 }
68 RnsEmbeddedStatus::Ok
69}
70
71#[no_mangle]
72pub extern "C" fn rns_embedded_node_queue_message(
73 node: *mut RnsEmbeddedNode,
74 destination_ptr: *const u8,
75 body_ptr: *const u8,
76 body_len: usize,
77 out_sequence: *mut u32,
78) -> RnsEmbeddedStatus {
79 let Some(node) = node_mut(node) else {
80 return RnsEmbeddedStatus::InvalidArgument;
81 };
82 if destination_ptr.is_null() || out_sequence.is_null() {
83 return RnsEmbeddedStatus::InvalidArgument;
84 }
85 let destination_slice = unsafe { core::slice::from_raw_parts(destination_ptr, 16) };
88 let mut destination = [0_u8; 16];
89 destination.copy_from_slice(destination_slice);
90 let Some(body) = byte_slice(body_ptr, body_len) else {
91 return RnsEmbeddedStatus::InvalidArgument;
92 };
93 match node.runtime.queue_message(destination, body) {
94 Ok(sequence) => {
95 unsafe {
97 *out_sequence = sequence;
98 }
99 RnsEmbeddedStatus::Ok
100 }
101 Err(err) => map_embedded_error(err),
102 }
103}
104
105#[no_mangle]
106pub extern "C" fn rns_embedded_v1_node_start(
107 node: *mut RnsEmbeddedV1Node,
108 config: *const RnsEmbeddedV1NodeConfig,
109 out_node_error: *mut RnsEmbeddedV1NodeError,
110) -> RnsEmbeddedStatus {
111 ffi_v1_node_error_boundary(out_node_error, || {
112 let Some(node) = v1_node_mut(node) else {
113 return set_v1_pointer_error(out_node_error, RnsEmbeddedV1NodeErrorCode::InvalidHandle);
114 };
115 if config.is_null() {
116 return set_v1_pointer_error(
117 out_node_error,
118 RnsEmbeddedV1NodeErrorCode::InvalidPointer,
119 );
120 }
121 let config = unsafe { &*config };
124 let node_config = match v1_node_config(config) {
125 Ok(config) => config,
126 Err(err) => return set_v1_node_error(out_node_error, err),
127 };
128 match node.node.start(node_config) {
129 Ok(()) => clear_v1_node_error(out_node_error),
130 Err(err) => set_v1_node_error(out_node_error, err),
131 }
132 })
133}
134
135#[no_mangle]
136pub extern "C" fn rns_embedded_v1_node_stop(
137 node: *mut RnsEmbeddedV1Node,
138 out_node_error: *mut RnsEmbeddedV1NodeError,
139) -> RnsEmbeddedStatus {
140 ffi_v1_node_error_boundary(out_node_error, || {
141 let Some(node) = v1_node_mut(node) else {
142 return set_v1_pointer_error(out_node_error, RnsEmbeddedV1NodeErrorCode::InvalidHandle);
143 };
144 match node.node.stop() {
145 Ok(()) => clear_v1_node_error(out_node_error),
146 Err(err) => set_v1_node_error(out_node_error, err),
147 }
148 })
149}
150
151#[no_mangle]
152pub extern "C" fn rns_embedded_v1_node_restart(
153 node: *mut RnsEmbeddedV1Node,
154 config: *const RnsEmbeddedV1NodeConfig,
155 out_node_error: *mut RnsEmbeddedV1NodeError,
156) -> RnsEmbeddedStatus {
157 ffi_v1_node_error_boundary(out_node_error, || {
158 let Some(node) = v1_node_mut(node) else {
159 return set_v1_pointer_error(out_node_error, RnsEmbeddedV1NodeErrorCode::InvalidHandle);
160 };
161 if config.is_null() {
162 return set_v1_pointer_error(
163 out_node_error,
164 RnsEmbeddedV1NodeErrorCode::InvalidPointer,
165 );
166 }
167 let config = unsafe { &*config };
170 let node_config = match v1_node_config(config) {
171 Ok(config) => config,
172 Err(err) => return set_v1_node_error(out_node_error, err),
173 };
174 match node.node.restart(node_config) {
175 Ok(()) => clear_v1_node_error(out_node_error),
176 Err(err) => set_v1_node_error(out_node_error, err),
177 }
178 })
179}
180
181#[no_mangle]
182pub extern "C" fn rns_embedded_v1_node_get_status(
183 node: *mut RnsEmbeddedV1Node,
184 out_status: *mut RnsEmbeddedV1NodeStatus,
185) -> RnsEmbeddedStatus {
186 ffi_status_boundary(|| {
187 let Some(node) = v1_node_mut(node) else {
188 return RnsEmbeddedStatus::InvalidArgument;
189 };
190 if out_status.is_null() {
191 return RnsEmbeddedStatus::InvalidArgument;
192 }
193 let status = node.node.get_status();
194 unsafe {
197 *out_status = map_v1_status(status);
198 }
199 RnsEmbeddedStatus::Ok
200 })
201}
202
203#[no_mangle]
204pub extern "C" fn rns_embedded_v1_node_send(
205 node: *mut RnsEmbeddedV1Node,
206 destination_ptr: *const u8,
207 body_ptr: *const u8,
208 body_len: usize,
209 out_receipt: *mut RnsEmbeddedV1SendReceipt,
210 out_node_error: *mut RnsEmbeddedV1NodeError,
211) -> RnsEmbeddedStatus {
212 ffi_v1_node_error_boundary(out_node_error, || {
213 let Some(node) = v1_node_mut(node) else {
214 return set_v1_pointer_error(out_node_error, RnsEmbeddedV1NodeErrorCode::InvalidHandle);
215 };
216 if destination_ptr.is_null() || out_receipt.is_null() {
217 return set_v1_pointer_error(
218 out_node_error,
219 RnsEmbeddedV1NodeErrorCode::InvalidPointer,
220 );
221 }
222 let Some(body) = byte_slice(body_ptr, body_len) else {
223 return set_v1_pointer_error(
224 out_node_error,
225 RnsEmbeddedV1NodeErrorCode::InvalidPointer,
226 );
227 };
228 let destination_slice = unsafe { core::slice::from_raw_parts(destination_ptr, 16) };
231 let mut destination = [0_u8; 16];
232 destination.copy_from_slice(destination_slice);
233 match node.node.send(destination, body, SendOptions) {
234 Ok(receipt) => {
235 unsafe {
238 *out_receipt = map_v1_receipt(receipt);
239 }
240 clear_v1_node_error(out_node_error)
241 }
242 Err(err) => set_v1_node_error(out_node_error, err),
243 }
244 })
245}
246
247#[no_mangle]
248pub extern "C" fn rns_embedded_v1_node_broadcast(
249 node: *mut RnsEmbeddedV1Node,
250 destinations_ptr: *const u8,
251 destination_count: usize,
252 body_ptr: *const u8,
253 body_len: usize,
254 out_receipt: *mut RnsEmbeddedV1SendReceipt,
255 out_node_error: *mut RnsEmbeddedV1NodeError,
256) -> RnsEmbeddedStatus {
257 ffi_v1_node_error_boundary(out_node_error, || {
258 let Some(node) = v1_node_mut(node) else {
259 return set_v1_pointer_error(out_node_error, RnsEmbeddedV1NodeErrorCode::InvalidHandle);
260 };
261 if out_receipt.is_null() {
262 return set_v1_pointer_error(
263 out_node_error,
264 RnsEmbeddedV1NodeErrorCode::InvalidPointer,
265 );
266 }
267 let Some(body) = byte_slice(body_ptr, body_len) else {
268 return set_v1_pointer_error(
269 out_node_error,
270 RnsEmbeddedV1NodeErrorCode::InvalidPointer,
271 );
272 };
273 let destinations = match destination_list(destinations_ptr, destination_count) {
274 Some(destinations) => destinations,
275 None => {
276 return set_v1_pointer_error(
277 out_node_error,
278 RnsEmbeddedV1NodeErrorCode::InvalidPointer,
279 )
280 }
281 };
282 match node.node.broadcast(body, BroadcastOptions { destinations }) {
283 Ok(receipt) => {
284 unsafe {
287 *out_receipt = map_v1_receipt(receipt);
288 }
289 clear_v1_node_error(out_node_error)
290 }
291 Err(err) => set_v1_node_error(out_node_error, err),
292 }
293 })
294}
295
296#[no_mangle]
297pub extern "C" fn rns_embedded_v1_node_set_log_level(
298 node: *mut RnsEmbeddedV1Node,
299 level: RnsEmbeddedV1LogLevel,
300 out_node_error: *mut RnsEmbeddedV1NodeError,
301) -> RnsEmbeddedStatus {
302 ffi_v1_node_error_boundary(out_node_error, || {
303 let Some(node) = v1_node_mut(node) else {
304 return set_v1_pointer_error(out_node_error, RnsEmbeddedV1NodeErrorCode::InvalidHandle);
305 };
306 match node.node.set_log_level(map_v1_log_level(level)) {
307 Ok(()) => clear_v1_node_error(out_node_error),
308 Err(err) => set_v1_node_error(out_node_error, err),
309 }
310 })
311}
312
313#[no_mangle]
314pub extern "C" fn rns_embedded_v1_node_subscribe_events(
315 node: *mut RnsEmbeddedV1Node,
316 out_subscription: *mut *mut RnsEmbeddedEventSubscription,
317 out_node_error: *mut RnsEmbeddedV1NodeError,
318) -> RnsEmbeddedStatus {
319 ffi_v1_node_error_boundary(out_node_error, || {
320 let Some(node) = v1_node_mut(node) else {
321 return set_v1_pointer_error(out_node_error, RnsEmbeddedV1NodeErrorCode::InvalidHandle);
322 };
323 if out_subscription.is_null() {
324 return set_v1_pointer_error(
325 out_node_error,
326 RnsEmbeddedV1NodeErrorCode::InvalidPointer,
327 );
328 }
329 match node.node.subscribe_events() {
330 Ok(subscription) => {
331 unsafe {
334 *out_subscription =
335 Box::into_raw(Box::new(RnsEmbeddedEventSubscription { subscription }));
336 }
337 clear_v1_node_error(out_node_error)
338 }
339 Err(err) => set_v1_node_error(out_node_error, err),
340 }
341 })
342}
343
344#[no_mangle]
345pub extern "C" fn rns_embedded_v1_subscription_next(
346 subscription: *mut RnsEmbeddedEventSubscription,
347 timeout_ms: u64,
348 out_poll_result: *mut RnsEmbeddedV1PollResult,
349 out_event: *mut RnsEmbeddedV1NodeEvent,
350 out_node_error: *mut RnsEmbeddedV1NodeError,
351) -> RnsEmbeddedStatus {
352 ffi_v1_node_error_boundary(out_node_error, || {
353 let Some(subscription) = v1_subscription_mut(subscription) else {
354 return set_v1_pointer_error(out_node_error, RnsEmbeddedV1NodeErrorCode::InvalidHandle);
355 };
356 if out_poll_result.is_null() || out_event.is_null() {
357 return set_v1_pointer_error(
358 out_node_error,
359 RnsEmbeddedV1NodeErrorCode::InvalidPointer,
360 );
361 }
362 match subscription.subscription.next(timeout_ms) {
363 Ok(result) => {
364 unsafe {
367 *out_poll_result = map_v1_poll_result(&result);
368 *out_event = match result {
369 PollResult::Event(ref event) => map_v1_event(event),
370 _ => RnsEmbeddedV1NodeEvent::default(),
371 };
372 }
373 set_v1_poll_sideband_error(out_node_error, &result)
374 }
375 Err(err) => set_v1_node_error(out_node_error, err),
376 }
377 })
378}
379
380#[no_mangle]
381pub extern "C" fn rns_embedded_v1_subscription_close(
382 subscription: *mut RnsEmbeddedEventSubscription,
383 out_node_error: *mut RnsEmbeddedV1NodeError,
384) -> RnsEmbeddedStatus {
385 ffi_v1_node_error_boundary(out_node_error, || {
386 if subscription.is_null() {
387 return clear_v1_node_error(out_node_error);
388 }
389 let boxed = unsafe { Box::from_raw(subscription) };
392 match boxed.subscription.close() {
393 Ok(()) => clear_v1_node_error(out_node_error),
394 Err(err) => set_v1_node_error(out_node_error, err),
395 }
396 })
397}
398
399fn node_mut<'a>(node: *mut RnsEmbeddedNode) -> Option<&'a mut RnsEmbeddedNode> {
400 if node.is_null() {
401 return None;
402 }
403 Some(unsafe { &mut *node })
406}
407
408fn v1_node_mut<'a>(node: *mut RnsEmbeddedV1Node) -> Option<&'a mut RnsEmbeddedV1Node> {
409 if node.is_null() {
410 return None;
411 }
412 Some(unsafe { &mut *node })
415}
416
417fn v1_subscription_mut<'a>(
418 subscription: *mut RnsEmbeddedEventSubscription,
419) -> Option<&'a mut RnsEmbeddedEventSubscription> {
420 if subscription.is_null() {
421 return None;
422 }
423 Some(unsafe { &mut *subscription })
426}
427
428fn byte_slice<'a>(ptr: *const u8, len: usize) -> Option<&'a [u8]> {
429 if len == 0 {
430 return Some(&[]);
431 }
432 if ptr.is_null() {
433 return None;
434 }
435 Some(unsafe { core::slice::from_raw_parts(ptr, len) })
438}