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 node = match v1_node_mut(node) {
113 Ok(n) => n,
114 Err(_) => return set_v1_pointer_error(out_node_error, RnsEmbeddedV1NodeErrorCode::InvalidHandle),
115 };
116 if config.is_null() {
117 return set_v1_pointer_error(
118 out_node_error,
119 RnsEmbeddedV1NodeErrorCode::InvalidPointer,
120 );
121 }
122 let config = unsafe { &*config };
125 let node_config = match v1_node_config(config) {
126 Ok(config) => config,
127 Err(err) => return set_v1_node_error(out_node_error, err),
128 };
129 match node.node.start(node_config) {
130 Ok(()) => clear_v1_node_error(out_node_error),
131 Err(err) => set_v1_node_error(out_node_error, err),
132 }
133 })
134}
135
136#[no_mangle]
137pub extern "C" fn rns_embedded_v1_node_stop(
138 node: *mut RnsEmbeddedV1Node,
139 out_node_error: *mut RnsEmbeddedV1NodeError,
140) -> RnsEmbeddedStatus {
141 ffi_v1_node_error_boundary(out_node_error, || {
142 let node = match v1_node_mut(node) {
143 Ok(n) => n,
144 Err(_) => return set_v1_pointer_error(out_node_error, RnsEmbeddedV1NodeErrorCode::InvalidHandle),
145 };
146 match node.node.stop() {
147 Ok(()) => clear_v1_node_error(out_node_error),
148 Err(err) => set_v1_node_error(out_node_error, err),
149 }
150 })
151}
152
153#[no_mangle]
154pub extern "C" fn rns_embedded_v1_node_restart(
155 node: *mut RnsEmbeddedV1Node,
156 config: *const RnsEmbeddedV1NodeConfig,
157 out_node_error: *mut RnsEmbeddedV1NodeError,
158) -> RnsEmbeddedStatus {
159 ffi_v1_node_error_boundary(out_node_error, || {
160 let node = match v1_node_mut(node) {
161 Ok(n) => n,
162 Err(_) => return set_v1_pointer_error(out_node_error, RnsEmbeddedV1NodeErrorCode::InvalidHandle),
163 };
164 if config.is_null() {
165 return set_v1_pointer_error(
166 out_node_error,
167 RnsEmbeddedV1NodeErrorCode::InvalidPointer,
168 );
169 }
170 let config = unsafe { &*config };
173 let node_config = match v1_node_config(config) {
174 Ok(config) => config,
175 Err(err) => return set_v1_node_error(out_node_error, err),
176 };
177 match node.node.restart(node_config) {
178 Ok(()) => clear_v1_node_error(out_node_error),
179 Err(err) => set_v1_node_error(out_node_error, err),
180 }
181 })
182}
183
184#[no_mangle]
185pub extern "C" fn rns_embedded_v1_node_get_status(
186 node: *mut RnsEmbeddedV1Node,
187 out_status: *mut RnsEmbeddedV1NodeStatus,
188) -> RnsEmbeddedStatus {
189 ffi_status_boundary(|| {
190 let node = match v1_node_mut(node) {
191 Ok(n) => n,
192 Err(_) => return RnsEmbeddedStatus::InvalidArgument,
193 };
194 if out_status.is_null() {
195 return RnsEmbeddedStatus::InvalidArgument;
196 }
197 let status = node.node.get_status();
198 unsafe {
201 *out_status = map_v1_status(status);
202 }
203 RnsEmbeddedStatus::Ok
204 })
205}
206
207#[no_mangle]
208pub extern "C" fn rns_embedded_v1_node_send(
209 node: *mut RnsEmbeddedV1Node,
210 destination_ptr: *const u8,
211 body_ptr: *const u8,
212 body_len: usize,
213 out_receipt: *mut RnsEmbeddedV1SendReceipt,
214 out_node_error: *mut RnsEmbeddedV1NodeError,
215) -> RnsEmbeddedStatus {
216 ffi_v1_node_error_boundary(out_node_error, || {
217 let node = match v1_node_mut(node) {
218 Ok(n) => n,
219 Err(_) => return set_v1_pointer_error(out_node_error, RnsEmbeddedV1NodeErrorCode::InvalidHandle),
220 };
221 if destination_ptr.is_null() || out_receipt.is_null() {
222 return set_v1_pointer_error(
223 out_node_error,
224 RnsEmbeddedV1NodeErrorCode::InvalidPointer,
225 );
226 }
227 let Some(body) = byte_slice(body_ptr, body_len) else {
228 return set_v1_pointer_error(
229 out_node_error,
230 RnsEmbeddedV1NodeErrorCode::InvalidPointer,
231 );
232 };
233 let destination_slice = unsafe { core::slice::from_raw_parts(destination_ptr, 16) };
236 let mut destination = [0_u8; 16];
237 destination.copy_from_slice(destination_slice);
238 match node.node.send(destination, body, SendOptions) {
239 Ok(receipt) => {
240 unsafe {
243 *out_receipt = map_v1_receipt(receipt);
244 }
245 clear_v1_node_error(out_node_error)
246 }
247 Err(err) => set_v1_node_error(out_node_error, err),
248 }
249 })
250}
251
252#[no_mangle]
253pub extern "C" fn rns_embedded_v1_node_broadcast(
254 node: *mut RnsEmbeddedV1Node,
255 destinations_ptr: *const u8,
256 destination_count: usize,
257 body_ptr: *const u8,
258 body_len: usize,
259 out_receipt: *mut RnsEmbeddedV1SendReceipt,
260 out_node_error: *mut RnsEmbeddedV1NodeError,
261) -> RnsEmbeddedStatus {
262 ffi_v1_node_error_boundary(out_node_error, || {
263 let node = match v1_node_mut(node) {
264 Ok(n) => n,
265 Err(_) => return set_v1_pointer_error(out_node_error, RnsEmbeddedV1NodeErrorCode::InvalidHandle),
266 };
267 if out_receipt.is_null() {
268 return set_v1_pointer_error(
269 out_node_error,
270 RnsEmbeddedV1NodeErrorCode::InvalidPointer,
271 );
272 }
273 let Some(body) = byte_slice(body_ptr, body_len) else {
274 return set_v1_pointer_error(
275 out_node_error,
276 RnsEmbeddedV1NodeErrorCode::InvalidPointer,
277 );
278 };
279 let destinations = match destination_list(destinations_ptr, destination_count) {
280 Ok(destinations) => destinations,
281 Err(_) => {
282 return set_v1_pointer_error(
283 out_node_error,
284 RnsEmbeddedV1NodeErrorCode::InvalidPointer,
285 )
286 }
287 };
288 match node.node.broadcast(body, BroadcastOptions { destinations }) {
289 Ok(receipt) => {
290 unsafe {
293 *out_receipt = map_v1_receipt(receipt);
294 }
295 clear_v1_node_error(out_node_error)
296 }
297 Err(err) => set_v1_node_error(out_node_error, err),
298 }
299 })
300}
301
302#[no_mangle]
303pub extern "C" fn rns_embedded_v1_node_set_log_level(
304 node: *mut RnsEmbeddedV1Node,
305 level: RnsEmbeddedV1LogLevel,
306 out_node_error: *mut RnsEmbeddedV1NodeError,
307) -> RnsEmbeddedStatus {
308 ffi_v1_node_error_boundary(out_node_error, || {
309 let node = match v1_node_mut(node) {
310 Ok(n) => n,
311 Err(_) => return set_v1_pointer_error(out_node_error, RnsEmbeddedV1NodeErrorCode::InvalidHandle),
312 };
313 match node.node.set_log_level(map_v1_log_level(level)) {
314 Ok(()) => clear_v1_node_error(out_node_error),
315 Err(err) => set_v1_node_error(out_node_error, err),
316 }
317 })
318}
319
320#[no_mangle]
321pub extern "C" fn rns_embedded_v1_node_subscribe_events(
322 node: *mut RnsEmbeddedV1Node,
323 out_subscription: *mut *mut RnsEmbeddedEventSubscription,
324 out_node_error: *mut RnsEmbeddedV1NodeError,
325) -> RnsEmbeddedStatus {
326 ffi_v1_node_error_boundary(out_node_error, || {
327 let node = match v1_node_mut(node) {
328 Ok(n) => n,
329 Err(_) => return set_v1_pointer_error(out_node_error, RnsEmbeddedV1NodeErrorCode::InvalidHandle),
330 };
331 if out_subscription.is_null() {
332 return set_v1_pointer_error(
333 out_node_error,
334 RnsEmbeddedV1NodeErrorCode::InvalidPointer,
335 );
336 }
337 match node.node.subscribe_events() {
338 Ok(subscription) => {
339 unsafe {
342 *out_subscription =
343 Box::into_raw(Box::new(RnsEmbeddedEventSubscription { subscription }));
344 }
345 clear_v1_node_error(out_node_error)
346 }
347 Err(err) => set_v1_node_error(out_node_error, err),
348 }
349 })
350}
351
352#[no_mangle]
353pub extern "C" fn rns_embedded_v1_subscription_next(
354 subscription: *mut RnsEmbeddedEventSubscription,
355 timeout_ms: u64,
356 out_poll_result: *mut RnsEmbeddedV1PollResult,
357 out_event: *mut RnsEmbeddedV1NodeEvent,
358 out_node_error: *mut RnsEmbeddedV1NodeError,
359) -> RnsEmbeddedStatus {
360 ffi_v1_node_error_boundary(out_node_error, || {
361 let subscription = match v1_subscription_mut(subscription) {
362 Ok(s) => s,
363 Err(_) => return set_v1_pointer_error(out_node_error, RnsEmbeddedV1NodeErrorCode::InvalidHandle),
364 };
365 if out_poll_result.is_null() || out_event.is_null() {
366 return set_v1_pointer_error(
367 out_node_error,
368 RnsEmbeddedV1NodeErrorCode::InvalidPointer,
369 );
370 }
371 match subscription.subscription.next(timeout_ms) {
372 Ok(result) => {
373 unsafe {
376 *out_poll_result = map_v1_poll_result(&result);
377 *out_event = match result {
378 PollResult::Event(ref event) => map_v1_event(event),
379 _ => RnsEmbeddedV1NodeEvent::default(),
380 };
381 }
382 set_v1_poll_sideband_error(out_node_error, &result)
383 }
384 Err(err) => set_v1_node_error(out_node_error, err),
385 }
386 })
387}
388
389#[no_mangle]
390pub extern "C" fn rns_embedded_v1_subscription_close(
391 subscription: *mut RnsEmbeddedEventSubscription,
392 out_node_error: *mut RnsEmbeddedV1NodeError,
393) -> RnsEmbeddedStatus {
394 ffi_v1_node_error_boundary(out_node_error, || {
395 if subscription.is_null() {
396 return clear_v1_node_error(out_node_error);
397 }
398 let boxed = unsafe { Box::from_raw(subscription) };
401 match boxed.subscription.close() {
402 Ok(()) => clear_v1_node_error(out_node_error),
403 Err(err) => set_v1_node_error(out_node_error, err),
404 }
405 })
406}
407
408fn node_mut<'a>(node: *mut RnsEmbeddedNode) -> Option<&'a mut RnsEmbeddedNode> {
409 if node.is_null() {
410 return None;
411 }
412 Some(unsafe { &mut *node })
415}
416
417fn v1_node_mut<'a>(node: *mut RnsEmbeddedV1Node) -> Result<&'a mut RnsEmbeddedV1Node, &'static str> {
418 if node.is_null() {
419 return Err("null node pointer");
420 }
421 Ok(unsafe { &mut *node })
424}
425
426fn v1_subscription_mut<'a>(
427 subscription: *mut RnsEmbeddedEventSubscription,
428) -> Result<&'a mut RnsEmbeddedEventSubscription, &'static str> {
429 if subscription.is_null() {
430 return Err("null subscription pointer");
431 }
432 Ok(unsafe { &mut *subscription })
435}
436
437fn byte_slice<'a>(ptr: *const u8, len: usize) -> Option<&'a [u8]> {
438 if len == 0 {
439 return Some(&[]);
440 }
441 if ptr.is_null() {
442 return None;
443 }
444 Some(unsafe { core::slice::from_raw_parts(ptr, len) })
447}