1use crate::error::{CfsError, OsalError, Result};
4use crate::ffi;
5use crate::os::id::OsalId;
6use crate::cstring;
7use crate::string_from_c_buf;
8use crate::status::check;
9use core::fmt::Write;
10use core::future::Future;
11use core::mem::MaybeUninit;
12use core::task::Poll;
13use heapless::String;
14
15#[cfg(not(nos3_cfe))]
16use crate::os::time::OsTime;
17
18#[derive(Clone)]
20#[repr(transparent)]
21pub struct SocketAddr(ffi::OS_SockAddr_t);
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25#[repr(u32)]
26pub enum SocketShutdownMode {
27 Read = ffi::OS_SocketShutdownMode_t_OS_SocketShutdownMode_SHUT_READ,
29 Write = ffi::OS_SocketShutdownMode_t_OS_SocketShutdownMode_SHUT_WRITE,
31 ReadWrite = ffi::OS_SocketShutdownMode_t_OS_SocketShutdownMode_SHUT_READWRITE,
33}
34
35impl SocketAddr {
36 pub fn new_ipv4(ip_addr: &str, port: u16) -> Result<Self> {
38 let mut addr_uninit = MaybeUninit::uninit();
39
40 check(unsafe {
42 ffi::OS_SocketAddrInit(addr_uninit.as_mut_ptr(), SocketDomain::IPv4.into())
43 })?;
44
45 let c_ip = cstring::<{ ffi::OS_MAX_PATH_LEN as usize }>(ip_addr)?;
47 check(unsafe {
48 ffi::OS_SocketAddrFromString(addr_uninit.as_mut_ptr(), c_ip.as_ptr())
49 })?;
50
51 check(unsafe { ffi::OS_SocketAddrSetPort(addr_uninit.as_mut_ptr(), port) })?;
53
54 Ok(Self(unsafe { addr_uninit.assume_init() }))
55 }
56
57 pub fn port(&self) -> Result<u16> {
59 let mut port = MaybeUninit::uninit();
60 check(unsafe { ffi::OS_SocketAddrGetPort(port.as_mut_ptr(), &self.0) })?;
61 Ok(unsafe { port.assume_init() })
62 }
63
64 pub fn to_string(&self) -> Result<String<{ ffi::OS_MAX_PATH_LEN as usize }>> {
66 let mut buffer = [0u8; { ffi::OS_MAX_PATH_LEN as usize }];
67 check(unsafe {
68 ffi::OS_SocketAddrToString(
69 buffer.as_mut_ptr() as *mut libc::c_char,
70 buffer.len(),
71 &self.0,
72 )
73 })?;
74 let len = buffer.iter().position(|&b| b == 0).unwrap_or(buffer.len());
75 let vec = heapless::Vec::from_slice(&buffer[..len]).map_err(|_| CfsError::Osal(OsalError::NameTooLong))?;
76 let s = String::from_utf8(vec).map_err(|_| CfsError::InvalidString)?;
77 Ok(s)
78 }
79}
80
81impl TryFrom<core::net::SocketAddr> for SocketAddr {
82 type Error = CfsError;
83
84 fn try_from(addr: core::net::SocketAddr) -> Result<Self> {
85 let mut addr_uninit = MaybeUninit::uninit();
86
87 let domain = match addr {
88 core::net::SocketAddr::V4(_) => SocketDomain::IPv4,
89 core::net::SocketAddr::V6(_) => SocketDomain::IPv6,
90 };
91
92 check(unsafe { ffi::OS_SocketAddrInit(addr_uninit.as_mut_ptr(), domain.into()) })?;
93
94 let mut ip_buf: String<{ ffi::OS_MAX_PATH_LEN as usize }> = String::new();
96 write!(ip_buf, "{}", addr.ip()).map_err(|_| CfsError::Osal(OsalError::NameTooLong))?;
97 let c_ip = cstring::<{ ffi::OS_MAX_PATH_LEN as usize }>(&ip_buf)?;
98
99 check(unsafe {
100 ffi::OS_SocketAddrFromString(addr_uninit.as_mut_ptr(), c_ip.as_ptr())
101 })?;
102
103 check(unsafe { ffi::OS_SocketAddrSetPort(addr_uninit.as_mut_ptr(), addr.port()) })?;
104
105 Ok(Self(unsafe { addr_uninit.assume_init() }))
106 }
107}
108
109#[derive(Debug)]
111#[repr(transparent)]
112pub struct Socket(ffi::osal_id_t);
113
114impl Drop for Socket {
115 fn drop(&mut self) {
116 if self.0 != 0 {
117 let _ = unsafe { ffi::OS_close(self.0) };
118 }
119 }
120}
121
122impl Socket {
123 pub fn bind_address(&self, addr: &SocketAddr) -> Result<()> {
125 check(unsafe { ffi::OS_SocketBindAddress(self.0, &addr.0) })?;
126 Ok(())
127 }
128}
129
130#[derive(Debug)]
132#[repr(transparent)]
133pub struct UdpSocket(Socket);
134
135#[derive(Debug, Clone, Copy, PartialEq, Eq)]
137pub enum Timeout {
138 Pend,
140 Poll,
142 Milliseconds(i32),
144}
145
146impl From<Timeout> for i32 {
147 fn from(timeout: Timeout) -> Self {
148 match timeout {
149 Timeout::Pend => ffi::OS_PEND,
150 Timeout::Poll => ffi::OS_CHECK as i32,
151 Timeout::Milliseconds(ms) => ms,
152 }
153 }
154}
155
156impl UdpSocket {
157 pub fn id(&self) -> OsalId {
160 OsalId((self.0).0)
161 }
162
163 pub fn bind(addr: SocketAddr) -> Result<UdpSocket> {
165 let mut sock_id = MaybeUninit::uninit();
166 check(unsafe {
167 ffi::OS_SocketOpen(
168 sock_id.as_mut_ptr(),
169 SocketDomain::IPv4.into(),
170 ffi::OS_SocketType_t_OS_SocketType_DATAGRAM,
171 )
172 })?;
173 let sock_id = unsafe { sock_id.assume_init() };
174
175 check(unsafe { ffi::OS_SocketBind(sock_id, &addr.0) })?;
176
177 Ok(UdpSocket(Socket(sock_id)))
178 }
179
180 pub fn recv_from<'a>(
182 &self,
183 buf: &'a mut [u8],
184 timeout: Timeout,
185 ) -> Result<(usize, SocketAddr)> {
186 let mut remote_addr_uninit = MaybeUninit::<ffi::OS_SockAddr_t>::uninit();
187
188 let num_bytes = unsafe {
189 ffi::OS_SocketRecvFrom(
190 (self.0).0,
191 buf.as_mut_ptr() as *mut _,
192 buf.len(),
193 remote_addr_uninit.as_mut_ptr(),
194 timeout.into(),
195 )
196 };
197
198 if num_bytes < 0 {
199 Err(CfsError::from(num_bytes))
200 } else {
201 let remote_addr = unsafe { remote_addr_uninit.assume_init() };
202 Ok((num_bytes as usize, SocketAddr(remote_addr)))
203 }
204 }
205
206 pub fn send_to(&self, buf: &[u8], target: &SocketAddr) -> Result<usize> {
208 let num_bytes = unsafe {
209 ffi::OS_SocketSendTo((self.0).0, buf.as_ptr() as *const _, buf.len(), &target.0)
210 };
211 if num_bytes < 0 {
212 Err(CfsError::from(num_bytes))
213 } else {
214 Ok(num_bytes as usize)
215 }
216 }
217
218 #[cfg(not(nos3_cfe))]
220 pub fn recv_from_abs<'a>(
221 &self,
222 buf: &'a mut [u8],
223 abstime: OsTime,
224 ) -> Result<(usize, SocketAddr)> {
225 let mut remote_addr_uninit = MaybeUninit::<ffi::OS_SockAddr_t>::uninit();
226 let num_bytes = unsafe {
227 ffi::OS_SocketRecvFromAbs(
228 (self.0).0,
229 buf.as_mut_ptr() as *mut _,
230 buf.len(),
231 remote_addr_uninit.as_mut_ptr(),
232 abstime.0,
233 )
234 };
235
236 if num_bytes < 0 {
237 Err(CfsError::from(num_bytes))
238 } else {
239 let remote_addr = SocketAddr(unsafe { remote_addr_uninit.assume_init() });
240 Ok((num_bytes as usize, remote_addr))
241 }
242 }
243}
244
245#[derive(Debug)]
247#[repr(transparent)]
248pub struct TcpListener(Socket);
249
250pub enum SocketDomain {
252 IPv4,
254 IPv6,
256}
257
258impl Into<ffi::OS_SocketDomain_t> for SocketDomain {
259 fn into(self) -> ffi::OS_SocketDomain_t {
260 match self {
261 SocketDomain::IPv4 => ffi::OS_SocketDomain_t_OS_SocketDomain_INET,
262 SocketDomain::IPv6 => ffi::OS_SocketDomain_t_OS_SocketDomain_INET6,
263 }
264 }
265}
266
267impl TcpListener {
268 pub fn bind(addr: SocketAddr) -> Result<Self> {
270 let mut sock_id = MaybeUninit::uninit();
271 check(unsafe {
272 ffi::OS_SocketOpen(
273 sock_id.as_mut_ptr(),
274 SocketDomain::IPv4.into(),
275 ffi::OS_SocketType_t_OS_SocketType_STREAM,
276 )
277 })?;
278 let sock_id = unsafe { sock_id.assume_init() };
279
280 check(unsafe { ffi::OS_SocketBind(sock_id, &addr.0) })?;
281
282 Ok(TcpListener(Socket(sock_id)))
283 }
284
285 pub fn accept(&self, timeout: Timeout) -> Result<(TcpStream, SocketAddr)> {
288 let mut remote_addr_uninit = MaybeUninit::<ffi::OS_SockAddr_t>::uninit();
289 let mut conn_sock_id = MaybeUninit::uninit();
290 check(unsafe {
291 ffi::OS_SocketAccept(
292 (self.0).0,
293 conn_sock_id.as_mut_ptr(),
294 remote_addr_uninit.as_mut_ptr(),
295 timeout.into(),
296 )
297 })?;
298
299 let stream = TcpStream(Socket(unsafe { conn_sock_id.assume_init() }));
300 let remote_addr = SocketAddr(unsafe { remote_addr_uninit.assume_init() });
301 Ok((stream, remote_addr))
302 }
303
304 pub fn listen(&self) -> Result<()> {
308 check(unsafe { ffi::OS_SocketListen(self.0 .0) })?;
309 Ok(())
310 }
311}
312
313#[derive(Debug)]
315#[repr(transparent)]
316pub struct TcpStream(Socket);
317
318impl TcpStream {
319 pub fn connect(addr: SocketAddr, domain: SocketDomain) -> Result<Self> {
321 let mut sock_id = MaybeUninit::uninit();
322 check(unsafe {
323 ffi::OS_SocketOpen(
324 sock_id.as_mut_ptr(),
325 domain.into(),
326 ffi::OS_SocketType_t_OS_SocketType_STREAM,
327 )
328 })?;
329 let sock_id = unsafe { sock_id.assume_init() };
330
331 check(unsafe { ffi::OS_SocketConnect(sock_id, &addr.0, ffi::OS_PEND as i32) })?;
332
333 Ok(TcpStream(Socket(sock_id)))
334 }
335
336 pub fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
338 let bytes_read = unsafe { ffi::OS_read(self.0 .0, buf.as_mut_ptr() as *mut _, buf.len()) };
339 if bytes_read < 0 {
340 Err(CfsError::from(bytes_read))
341 } else {
342 Ok(bytes_read as usize)
343 }
344 }
345
346 pub fn write(&mut self, buf: &[u8]) -> Result<usize> {
348 let bytes_written =
349 unsafe { ffi::OS_write(self.0 .0, buf.as_ptr() as *const _, buf.len()) };
350 if bytes_written < 0 {
351 Err(CfsError::from(bytes_written))
352 } else {
353 Ok(bytes_written as usize)
354 }
355 }
356
357 #[cfg(not(nos3_cfe))]
359 pub fn accept_abs(&self, abstime: OsTime) -> Result<(TcpStream, SocketAddr)> {
360 let mut remote_addr_uninit = MaybeUninit::<ffi::OS_SockAddr_t>::uninit();
361 let mut conn_sock_id = MaybeUninit::uninit();
362 check(unsafe {
363 ffi::OS_SocketAcceptAbs(
364 self.0 .0,
365 conn_sock_id.as_mut_ptr(),
366 remote_addr_uninit.as_mut_ptr(),
367 abstime.0,
368 )
369 })?;
370
371 let stream = TcpStream(Socket(unsafe { conn_sock_id.assume_init() }));
372 let remote_addr = SocketAddr(unsafe { remote_addr_uninit.assume_init() });
373 Ok((stream, remote_addr))
374 }
375
376 #[cfg(not(nos3_cfe))]
378 pub fn connect_abs(addr: SocketAddr, domain: SocketDomain, abstime: OsTime) -> Result<Self> {
379 let mut sock_id = MaybeUninit::uninit();
380 check(unsafe {
381 ffi::OS_SocketOpen(
382 sock_id.as_mut_ptr(),
383 domain.into(),
384 ffi::OS_SocketType_t_OS_SocketType_STREAM,
385 )
386 })?;
387 let sock_id = unsafe { sock_id.assume_init() };
388
389 check(unsafe { ffi::OS_SocketConnectAbs(sock_id, &addr.0, abstime.0) })?;
390
391 Ok(TcpStream(Socket(sock_id)))
392 }
393
394 pub fn shutdown(&self, how: SocketShutdownMode) -> Result<()> {
396 check(unsafe { ffi::OS_SocketShutdown(self.0 .0, how as ffi::OS_SocketShutdownMode_t) })?;
397 Ok(())
398 }
399}
400
401pub fn get_network_id() -> i32 {
403 unsafe { ffi::OS_NetworkGetID() }
404}
405
406pub fn get_host_name() -> Result<String<{ ffi::OS_MAX_PATH_LEN as usize }>> {
408 let mut buffer = [0u8; { ffi::OS_MAX_PATH_LEN as usize }];
409 check(unsafe {
410 ffi::OS_NetworkGetHostName(buffer.as_mut_ptr() as *mut libc::c_char, buffer.len())
411 })?;
412 let len = buffer.iter().position(|&b| b == 0).unwrap_or(buffer.len());
413 let vec = heapless::Vec::from_slice(&buffer[..len]).map_err(|_| CfsError::Osal(OsalError::NameTooLong))?;
414 let s = String::from_utf8(vec).map_err(|_| CfsError::InvalidString)?;
415 Ok(s)
416}
417
418#[derive(Debug, Clone, Copy)]
420pub struct FdSet(ffi::OS_FdSet);
421
422impl FdSet {
423 pub fn new() -> Self {
425 let mut set = MaybeUninit::uninit();
426 unsafe { ffi::OS_SelectFdZero(set.as_mut_ptr()) };
428 Self(unsafe { set.assume_init() })
429 }
430
431 pub fn zero(&mut self) {
433 let _ = unsafe { ffi::OS_SelectFdZero(&mut self.0) };
434 }
435
436 pub fn add(&mut self, id: OsalId) {
438 let _ = unsafe { ffi::OS_SelectFdAdd(&mut self.0, id.0) };
439 }
440
441 pub fn clear(&mut self, id: OsalId) {
443 let _ = unsafe { ffi::OS_SelectFdClear(&mut self.0, id.0) };
444 }
445
446 pub fn is_set(&self, id: OsalId) -> bool {
448 unsafe { ffi::OS_SelectFdIsSet(&self.0, id.0) }
449 }
450}
451
452impl Default for FdSet {
453 fn default() -> Self {
454 Self::new()
455 }
456}
457
458pub fn select_single(id: OsalId, state: &mut u32, timeout_ms: i32) -> Result<()> {
460 check(unsafe { ffi::OS_SelectSingle(id.0, state, timeout_ms) })?;
461 Ok(())
462}
463
464#[cfg(not(nos3_cfe))]
466pub fn select_single_abs(id: OsalId, state: &mut u32, abstime: OsTime) -> Result<()> {
467 check(unsafe { ffi::OS_SelectSingleAbs(id.0, state, abstime.0) })?;
468 Ok(())
469}
470
471pub fn select_multiple(
473 read_set: Option<&mut FdSet>,
474 write_set: Option<&mut FdSet>,
475 timeout_ms: i32,
476) -> Result<()> {
477 let read_ptr = read_set.map_or(core::ptr::null_mut(), |s| &mut s.0);
478 let write_ptr = write_set.map_or(core::ptr::null_mut(), |s| &mut s.0);
479 check(unsafe { ffi::OS_SelectMultiple(read_ptr, write_ptr, timeout_ms) })?;
480 Ok(())
481}
482
483#[cfg(not(nos3_cfe))]
485pub fn select_multiple_abs(
486 read_set: Option<&mut FdSet>,
487 write_set: Option<&mut FdSet>,
488 abstime: OsTime,
489) -> Result<()> {
490 let read_ptr = read_set.map_or(core::ptr::null_mut(), |s| &mut s.0);
491 let write_ptr = write_set.map_or(core::ptr::null_mut(), |s| &mut s.0);
492 check(unsafe { ffi::OS_SelectMultipleAbs(read_ptr, write_ptr, abstime.0) })?;
493 Ok(())
494}
495
496#[derive(Debug, Clone)]
498pub struct SocketProp {
499 pub name: String<{ ffi::OS_MAX_API_NAME as usize }>,
501 pub creator: OsalId,
503}
504
505pub fn get_socket_id_by_name(name: &str) -> Result<OsalId> {
507 let c_name = cstring::<{ ffi::OS_MAX_API_NAME as usize }>(name)?;
508 let mut sock_id = MaybeUninit::uninit();
509 check(unsafe { ffi::OS_SocketGetIdByName(sock_id.as_mut_ptr(), c_name.as_ptr()) })?;
510 Ok(OsalId(unsafe { sock_id.assume_init() }))
511}
512
513pub fn get_socket_info(sock_id: OsalId) -> Result<SocketProp> {
515 let mut prop = MaybeUninit::<ffi::OS_socket_prop_t>::uninit();
516 check(unsafe { ffi::OS_SocketGetInfo(sock_id.0, prop.as_mut_ptr()) })?;
517 let prop = unsafe { prop.assume_init() };
518
519 Ok(SocketProp {
520 name: string_from_c_buf(&prop.name)?,
521 creator: OsalId(prop.creator),
522 })
523}
524
525impl UdpSocket {
526 pub fn recv<'a>(
528 &'a self,
529 buf: &'a mut [u8],
530 ) -> impl Future<Output = Result<(usize, SocketAddr)>> + use<'a> {
531 core::future::poll_fn(|cx| {
532 let recv_future = self.recv_from(buf, Timeout::Poll);
533 match recv_future {
534 Err(CfsError::Osal(OsalError::Timeout | OsalError::QueueEmpty)) => {
535 crate::runtime::reactor::register_read(cx.waker(), self.id());
536 Poll::Pending
537 }
538 Ok(result) => Poll::Ready(Ok(result)),
539 Err(e) => Poll::Ready(Err(e)),
540 }
541 })
542 }
543
544 pub fn send<'a>(
546 &'a self,
547 buf: &'a [u8],
548 target: &'a SocketAddr,
549 ) -> impl Future<Output = Result<usize>> + use<'a> {
550 core::future::poll_fn(|cx| {
551 match self.send_to(buf, target) {
552 Err(CfsError::Osal(OsalError::Timeout | OsalError::QueueEmpty)) => {
553 crate::runtime::reactor::register_write(cx.waker(), self.id());
554 Poll::Pending
555 }
556 Ok(result) => Poll::Ready(Ok(result)),
557 Err(e) => Poll::Ready(Err(e)),
558 }
559 })
560 }
561}