1#![allow(non_camel_case_types)]
14
15use crate::api::{
16 iox2_callback_context, iox2_callback_progression_e, iox2_config_ptr, iox2_node_name_ptr,
17 iox2_service_builder_h, iox2_service_builder_t, iox2_service_name_ptr, iox2_service_type_e,
18 AssertNonNullHandle, HandleToType, IntoCInt, ServiceBuilderUnion, IOX2_OK,
19};
20
21use iceoryx2::node::{NodeId, NodeListFailure, NodeView};
22use iceoryx2::prelude::*;
23use iceoryx2_bb_elementary::static_assert::*;
24use iceoryx2_ffi_macros::iceoryx2_ffi;
25
26use core::ffi::c_int;
27use core::mem::ManuallyDrop;
28use std::time::Duration;
29
30#[repr(C)]
33#[derive(Copy, Clone)]
34pub enum iox2_node_list_failure_e {
35 INSUFFICIENT_PERMISSIONS = IOX2_OK as isize + 1,
36 INTERRUPT,
37 INTERNAL_ERROR,
38}
39
40impl IntoCInt for NodeListFailure {
41 fn into_c_int(self) -> c_int {
42 (match self {
43 NodeListFailure::InsufficientPermissions => {
44 iox2_node_list_failure_e::INSUFFICIENT_PERMISSIONS
45 }
46 NodeListFailure::Interrupt => iox2_node_list_failure_e::INTERRUPT,
47 NodeListFailure::InternalError => iox2_node_list_failure_e::INTERNAL_ERROR,
48 }) as c_int
49 }
50}
51
52#[repr(C)]
53#[derive(Copy, Clone)]
54pub enum iox2_node_event_e {
55 TICK = 0,
56 TERMINATION_REQUEST,
57 INTERRUPT_SIGNAL,
58}
59
60impl IntoCInt for NodeEvent {
61 fn into_c_int(self) -> c_int {
62 (match self {
63 NodeEvent::Tick => iox2_node_event_e::TICK,
64 NodeEvent::TerminationRequest => iox2_node_event_e::TERMINATION_REQUEST,
65 NodeEvent::InterruptSignal => iox2_node_event_e::INTERRUPT_SIGNAL,
66 }) as c_int
67 }
68}
69
70pub(super) union NodeUnion {
71 ipc: ManuallyDrop<Node<ipc::Service>>,
72 local: ManuallyDrop<Node<local::Service>>,
73}
74
75impl NodeUnion {
76 pub(super) fn new_ipc(node: Node<ipc::Service>) -> Self {
77 Self {
78 ipc: ManuallyDrop::new(node),
79 }
80 }
81 pub(super) fn new_local(node: Node<local::Service>) -> Self {
82 Self {
83 local: ManuallyDrop::new(node),
84 }
85 }
86}
87
88#[repr(C)]
89#[repr(align(8))] pub struct iox2_node_storage_t {
91 internal: [u8; 16], }
93
94#[repr(C)]
95#[iceoryx2_ffi(NodeUnion)]
96pub struct iox2_node_t {
97 pub(super) service_type: iox2_service_type_e,
98 pub(super) value: iox2_node_storage_t,
99 pub(super) deleter: fn(*mut iox2_node_t),
100}
101
102impl iox2_node_t {
103 pub(super) fn init(
104 &mut self,
105 service_type: iox2_service_type_e,
106 value: NodeUnion,
107 deleter: fn(*mut iox2_node_t),
108 ) {
109 self.service_type = service_type;
110 self.value.init(value);
111 self.deleter = deleter;
112 }
113}
114
115pub struct iox2_name_h_t;
116pub type iox2_node_h = *mut iox2_name_h_t;
118pub type iox2_node_h_ref = *const iox2_node_h;
120
121impl AssertNonNullHandle for iox2_node_h {
122 fn assert_non_null(self) {
123 debug_assert!(!self.is_null());
124 }
125}
126
127impl AssertNonNullHandle for iox2_node_h_ref {
128 fn assert_non_null(self) {
129 debug_assert!(!self.is_null());
130 unsafe {
131 debug_assert!(!(*self).is_null());
132 }
133 }
134}
135
136impl HandleToType for iox2_node_h {
137 type Target = *mut iox2_node_t;
138
139 fn as_type(self) -> Self::Target {
140 self as *mut _ as _
141 }
142}
143
144impl HandleToType for iox2_node_h_ref {
145 type Target = *mut iox2_node_t;
146
147 fn as_type(self) -> Self::Target {
148 unsafe { *self as *mut _ as _ }
149 }
150}
151
152#[repr(C)]
153#[derive(Copy, Clone)]
154pub enum iox2_node_state_e {
155 ALIVE,
156 DEAD,
157 INACCESSIBLE,
158 UNDEFINED,
159}
160
161pub type iox2_node_id_ptr = *const NodeId;
164pub type iox2_node_id_ptr_mut = *mut NodeId;
166
167pub type iox2_node_list_callback = extern "C" fn(
179 iox2_node_state_e,
180 iox2_node_id_ptr,
181 iox2_node_name_ptr,
182 iox2_config_ptr,
183 iox2_callback_context,
184) -> iox2_callback_progression_e;
185
186#[no_mangle]
196pub unsafe extern "C" fn iox2_node_name(node_handle: iox2_node_h_ref) -> iox2_node_name_ptr {
197 node_handle.assert_non_null();
198
199 let node = &mut *node_handle.as_type();
200
201 match node.service_type {
202 iox2_service_type_e::IPC => node.value.as_ref().ipc.name(),
203 iox2_service_type_e::LOCAL => node.value.as_ref().local.name(),
204 }
205}
206
207#[no_mangle]
214pub unsafe extern "C" fn iox2_node_wait(
215 node_handle: iox2_node_h_ref,
216 cycle_time_sec: u64,
217 cycle_time_nsec: u32,
218) -> c_int {
219 node_handle.assert_non_null();
220
221 let node = &mut *node_handle.as_type();
222 let cycle_time =
223 Duration::from_secs(cycle_time_sec) + Duration::from_nanos(cycle_time_nsec as u64);
224 match node.service_type {
225 iox2_service_type_e::IPC => node.value.as_ref().ipc.wait(cycle_time),
226 iox2_service_type_e::LOCAL => node.value.as_ref().local.wait(cycle_time),
227 }
228 .into_c_int()
229}
230
231#[no_mangle]
237pub unsafe extern "C" fn iox2_node_config(node_handle: iox2_node_h_ref) -> iox2_config_ptr {
238 node_handle.assert_non_null();
239
240 let node = &mut *node_handle.as_type();
241
242 match node.service_type {
243 iox2_service_type_e::IPC => node.value.as_ref().ipc.config(),
244 iox2_service_type_e::LOCAL => node.value.as_ref().local.config(),
245 }
246}
247
248#[no_mangle]
254pub unsafe extern "C" fn iox2_node_id(node_handle: iox2_node_h_ref) -> iox2_node_id_ptr {
255 node_handle.assert_non_null();
256 todo!() }
258
259fn iox2_node_list_impl<S: Service>(
260 node_state: &NodeState<S>,
261 callback: iox2_node_list_callback,
262 callback_ctx: iox2_callback_context,
263) -> CallbackProgression {
264 match node_state {
265 NodeState::Alive(alive_node_view) => {
266 let (node_name, config) = alive_node_view
267 .details()
268 .as_ref()
269 .map(|view| (view.name() as _, view.config() as _))
270 .unwrap_or((std::ptr::null(), std::ptr::null()));
271 callback(
272 iox2_node_state_e::ALIVE,
273 alive_node_view.id(),
274 node_name,
275 config,
276 callback_ctx,
277 )
278 .into()
279 }
280 NodeState::Dead(dead_node_view) => {
281 let (node_name, config) = dead_node_view
282 .details()
283 .as_ref()
284 .map(|view| (view.name() as _, view.config() as _))
285 .unwrap_or((std::ptr::null(), std::ptr::null()));
286 callback(
287 iox2_node_state_e::DEAD,
288 dead_node_view.id(),
289 node_name,
290 config,
291 callback_ctx,
292 )
293 .into()
294 }
295 NodeState::Inaccessible(ref node_id) => callback(
296 iox2_node_state_e::INACCESSIBLE,
297 node_id,
298 std::ptr::null(),
299 std::ptr::null(),
300 callback_ctx,
301 )
302 .into(),
303 NodeState::Undefined(ref node_id) => callback(
304 iox2_node_state_e::UNDEFINED,
305 node_id,
306 std::ptr::null(),
307 std::ptr::null(),
308 callback_ctx,
309 )
310 .into(),
311 }
312}
313
314#[no_mangle]
330pub unsafe extern "C" fn iox2_node_list(
331 service_type: iox2_service_type_e,
332 config_ptr: iox2_config_ptr,
333 callback: iox2_node_list_callback,
334 callback_ctx: iox2_callback_context,
335) -> c_int {
336 debug_assert!(!config_ptr.is_null());
337
338 let config = &*config_ptr;
339
340 let list_result = match service_type {
341 iox2_service_type_e::IPC => Node::<ipc::Service>::list(config, |node_state| {
342 iox2_node_list_impl(&node_state, callback, callback_ctx)
343 }),
344 iox2_service_type_e::LOCAL => Node::<local::Service>::list(config, |node_state| {
345 iox2_node_list_impl(&node_state, callback, callback_ctx)
346 }),
347 };
348
349 match list_result {
350 Ok(_) => IOX2_OK,
351 Err(e) => e.into_c_int(),
352 }
353}
354
355#[no_mangle]
371pub unsafe extern "C" fn iox2_node_service_builder(
372 node_handle: iox2_node_h_ref,
373 service_builder_struct_ptr: *mut iox2_service_builder_t,
374 service_name_ptr: iox2_service_name_ptr,
375) -> iox2_service_builder_h {
376 node_handle.assert_non_null();
377 debug_assert!(!service_name_ptr.is_null());
378
379 let mut service_builder_struct_ptr = service_builder_struct_ptr;
380 fn no_op(_: *mut iox2_service_builder_t) {}
381 let mut deleter: fn(*mut iox2_service_builder_t) = no_op;
382 if service_builder_struct_ptr.is_null() {
383 service_builder_struct_ptr = iox2_service_builder_t::alloc();
384 deleter = iox2_service_builder_t::dealloc;
385 }
386 debug_assert!(!service_builder_struct_ptr.is_null());
387
388 let node = &mut *node_handle.as_type();
389 match node.service_type {
390 iox2_service_type_e::IPC => {
391 let service_builder = node.value.as_ref().ipc.service_builder(&*service_name_ptr);
392 (*service_builder_struct_ptr).init(
393 node.service_type,
394 ServiceBuilderUnion::new_ipc_base(service_builder),
395 deleter,
396 );
397 }
398 iox2_service_type_e::LOCAL => {
399 let service_builder = node
400 .value
401 .as_ref()
402 .local
403 .service_builder(&*service_name_ptr);
404 (*service_builder_struct_ptr).init(
405 node.service_type,
406 ServiceBuilderUnion::new_local_base(service_builder),
407 deleter,
408 );
409 }
410 };
411
412 (*service_builder_struct_ptr).as_handle()
413}
414
415#[no_mangle]
426pub unsafe extern "C" fn iox2_node_drop(node_handle: iox2_node_h) {
427 node_handle.assert_non_null();
428
429 let node = &mut *node_handle.as_type();
430
431 match node.service_type {
432 iox2_service_type_e::IPC => {
433 ManuallyDrop::drop(&mut node.value.as_mut().ipc);
434 }
435 iox2_service_type_e::LOCAL => {
436 ManuallyDrop::drop(&mut node.value.as_mut().local);
437 }
438 }
439 (node.deleter)(node);
440}
441
442