1use crate::{
2 error::Error, ffi::get_last_error, ip::NrfSockAddr, lte_link::LteLink, CancellationToken,
3};
4use core::net::SocketAddr;
5use core::{
6 cell::RefCell,
7 ops::{BitOr, BitOrAssign, Deref, Neg},
8 sync::atomic::{AtomicU8, Ordering},
9 task::{Poll, Waker},
10};
11use critical_section::Mutex;
12use num_enum::{IntoPrimitive, TryFromPrimitive};
13
14const WAKER_SLOTS: usize = (nrfxlib_sys::NRF_MODEM_MAX_SOCKET_COUNT * 2) as usize;
17const WAKER_INIT: Option<(Waker, i32, SocketDirection)> = None;
18#[allow(clippy::type_complexity)]
19static SOCKET_WAKERS: Mutex<RefCell<[Option<(Waker, i32, SocketDirection)>; WAKER_SLOTS]>> =
20 Mutex::new(RefCell::new([WAKER_INIT; WAKER_SLOTS]));
21
22fn wake_sockets(socket_fd: i32, socket_dir: SocketDirection) {
23 critical_section::with(|cs| {
24 SOCKET_WAKERS
25 .borrow_ref_mut(cs)
26 .iter_mut()
27 .filter(|slot| {
28 if let Some((_, fd, dir)) = slot {
29 *fd == socket_fd && dir.same_direction(socket_dir)
30 } else {
31 false
32 }
33 })
34 .for_each(|slot| {
35 let (waker, _, _) = slot.take().unwrap();
36 waker.wake();
37 });
38 });
39}
40
41fn register_socket_waker(waker: Waker, socket_fd: i32, socket_dir: SocketDirection) {
42 critical_section::with(|cs| {
43 let mut wakers = SOCKET_WAKERS.borrow_ref_mut(cs);
45
46 let empty_waker = wakers.iter_mut().find(|waker| {
48 waker.is_none()
49 || waker.as_ref().map(|(_, fd, dir)| (*fd, *dir)) == Some((socket_fd, socket_dir))
50 });
51
52 if let Some(empty_waker) = empty_waker {
53 *empty_waker = Some((waker, socket_fd, socket_dir));
55 } else {
56 wakers
59 .first_mut()
60 .unwrap()
61 .replace((waker, socket_fd, socket_dir))
62 .unwrap()
63 .0
64 .wake();
65 }
66 });
67}
68
69unsafe extern "C" fn socket_poll_callback(pollfd: *mut nrfxlib_sys::nrf_pollfd) {
70 let pollfd = *pollfd;
71
72 let mut direction = SocketDirection::Neither;
73
74 if pollfd.revents as u32 & nrfxlib_sys::NRF_POLLIN != 0 {
75 direction |= SocketDirection::In;
76 }
77
78 if pollfd.revents as u32 & nrfxlib_sys::NRF_POLLOUT != 0 {
79 direction |= SocketDirection::Out;
80 }
81
82 if pollfd.revents as u32
83 & (nrfxlib_sys::NRF_POLLERR | nrfxlib_sys::NRF_POLLHUP | nrfxlib_sys::NRF_POLLNVAL)
84 != 0
85 {
86 direction |= SocketDirection::Either;
87 }
88
89 #[cfg(feature = "defmt")]
90 defmt::trace!(
91 "Socket poll callback. fd: {}, revents: {:X}, direction: {}",
92 pollfd.fd,
93 pollfd.revents,
94 direction
95 );
96
97 wake_sockets(pollfd.fd, direction);
98}
99
100#[derive(Clone, Copy, Debug, PartialEq, Eq)]
102#[cfg_attr(feature = "defmt", derive(defmt::Format))]
103enum SocketDirection {
104 Neither,
106 In,
108 Out,
110 Either,
112}
113
114impl BitOrAssign for SocketDirection {
115 fn bitor_assign(&mut self, rhs: Self) {
116 *self = *self | rhs;
117 }
118}
119
120impl BitOr for SocketDirection {
121 type Output = SocketDirection;
122
123 fn bitor(self, rhs: Self) -> Self::Output {
124 match (self, rhs) {
125 (SocketDirection::Neither, rhs) => rhs,
126 (lhs, SocketDirection::Neither) => lhs,
127 (SocketDirection::In, SocketDirection::In) => SocketDirection::In,
128 (SocketDirection::Out, SocketDirection::Out) => SocketDirection::Out,
129 (SocketDirection::In, SocketDirection::Out) => SocketDirection::Either,
130 (SocketDirection::Out, SocketDirection::In) => SocketDirection::Either,
131 (SocketDirection::Either, _) => SocketDirection::Either,
132 (_, SocketDirection::Either) => SocketDirection::Either,
133 }
134 }
135}
136
137impl SocketDirection {
138 fn same_direction(&self, other: Self) -> bool {
139 match (self, other) {
140 (SocketDirection::Neither, _) => false,
141 (_, SocketDirection::Neither) => false,
142 (SocketDirection::In, SocketDirection::In) => true,
143 (SocketDirection::Out, SocketDirection::Out) => true,
144 (SocketDirection::In, SocketDirection::Out) => false,
145 (SocketDirection::Out, SocketDirection::In) => false,
146 (_, SocketDirection::Either) => true,
147 (SocketDirection::Either, _) => true,
148 }
149 }
150}
151
152#[derive(Debug)]
154#[cfg_attr(feature = "defmt", derive(defmt::Format))]
155pub struct Socket {
156 fd: i32,
158 family: SocketFamily,
160 link: Option<LteLink>,
163 split: bool,
165}
166
167impl Socket {
168 pub async fn create(
170 family: SocketFamily,
171 s_type: SocketType,
172 protocol: SocketProtocol,
173 ) -> Result<Self, Error> {
174 #[cfg(feature = "defmt")]
175 defmt::debug!(
176 "Creating socket with family: {}, type: {}, protocol: {}",
177 family as u32 as i32,
178 s_type as u32 as i32,
179 protocol as u32 as i32
180 );
181
182 if unsafe { !nrfxlib_sys::nrf_modem_is_initialized() } {
183 return Err(Error::ModemNotInitialized);
184 }
185
186 let link = LteLink::new().await?;
188
189 let fd = unsafe {
191 nrfxlib_sys::nrf_socket(
192 family as u32 as i32,
193 s_type as u32 as i32,
194 protocol as u32 as i32,
195 )
196 };
197
198 if fd == -1 {
200 return Err(Error::NrfError(get_last_error()));
201 }
202
203 unsafe {
205 let result = nrfxlib_sys::nrf_fcntl(
206 fd,
207 nrfxlib_sys::NRF_F_SETFL as _,
208 nrfxlib_sys::NRF_O_NONBLOCK as _,
209 );
210
211 if result == -1 {
212 return Err(Error::NrfError(get_last_error()));
213 }
214 }
215
216 let poll_callback = nrfxlib_sys::nrf_modem_pollcb {
218 callback: Some(socket_poll_callback),
219 events: (nrfxlib_sys::NRF_POLLIN | nrfxlib_sys::NRF_POLLOUT) as _, oneshot: false,
221 };
222
223 unsafe {
224 let result = nrfxlib_sys::nrf_setsockopt(
225 fd,
226 nrfxlib_sys::NRF_SOL_SOCKET as _,
227 nrfxlib_sys::NRF_SO_POLLCB as _,
228 (&poll_callback as *const nrfxlib_sys::nrf_modem_pollcb).cast(),
229 core::mem::size_of::<nrfxlib_sys::nrf_modem_pollcb>() as u32,
230 );
231
232 if result == -1 {
233 return Err(Error::NrfError(get_last_error()));
234 }
235 }
236
237 Ok(Socket {
238 fd,
239 family,
240 link: Some(link),
241 split: false,
242 })
243 }
244
245 pub fn as_raw_fd(&self) -> i32 {
247 self.fd
248 }
249
250 pub async fn split(mut self) -> Result<(SplitSocketHandle, SplitSocketHandle), Error> {
251 let index = SplitSocketHandle::get_new_spot();
252 self.split = true;
253
254 Ok((
255 SplitSocketHandle {
256 inner: Some(Socket {
257 fd: self.fd,
258 family: self.family,
259 link: Some(LteLink::new().await?),
260 split: true,
261 }),
262 index,
263 },
264 SplitSocketHandle {
265 inner: Some(self),
266 index,
267 },
268 ))
269 }
270
271 pub async unsafe fn connect(
279 &self,
280 address: SocketAddr,
281 token: &CancellationToken,
282 ) -> Result<(), Error> {
283 #[cfg(feature = "defmt")]
284 defmt::debug!(
285 "Connecting socket {} to {:?}",
286 self.fd,
287 defmt::Debug2Format(&address)
288 );
289
290 token.bind_to_current_task().await;
291
292 self.link
295 .as_ref()
296 .unwrap()
297 .wait_for_link_with_cancellation(token)
298 .await?;
299
300 core::future::poll_fn(|cx| {
301 #[cfg(feature = "defmt")]
302 defmt::trace!("Connecting socket {}", self.fd);
303
304 if token.is_cancelled() {
305 return Poll::Ready(Err(Error::OperationCancelled));
306 }
307
308 let address = NrfSockAddr::from(address);
310
311 register_socket_waker(cx.waker().clone(), self.fd, SocketDirection::Either);
312
313 let mut connect_result = unsafe {
315 nrfxlib_sys::nrf_connect(self.fd, address.as_ptr(), address.size() as u32)
316 } as isize;
317
318 const NRF_EINPROGRESS: isize = nrfxlib_sys::NRF_EINPROGRESS as isize;
319 const NRF_EALREADY: isize = nrfxlib_sys::NRF_EALREADY as isize;
320 const NRF_EISCONN: isize = nrfxlib_sys::NRF_EISCONN as isize;
321
322 if connect_result == -1 {
323 connect_result = get_last_error();
324 }
325
326 #[cfg(feature = "defmt")]
327 defmt::trace!("Connect result {}", connect_result);
328
329 match connect_result {
330 0 => Poll::Ready(Ok(())),
332 NRF_EISCONN => Poll::Ready(Ok(())),
334 NRF_EINPROGRESS | NRF_EALREADY => Poll::Pending,
336 error => Poll::Ready(Err(Error::NrfError(error))),
338 }
339 })
340 .await?;
341
342 Ok(())
343 }
344
345 pub async unsafe fn bind(
353 &self,
354 address: SocketAddr,
355 token: &CancellationToken,
356 ) -> Result<(), Error> {
357 #[cfg(feature = "defmt")]
358 defmt::debug!(
359 "Binding socket {} to {:?}",
360 self.fd,
361 defmt::Debug2Format(&address)
362 );
363
364 token.bind_to_current_task().await;
365
366 self.link
369 .as_ref()
370 .unwrap()
371 .wait_for_link_with_cancellation(token)
372 .await?;
373
374 core::future::poll_fn(|cx| {
375 #[cfg(feature = "defmt")]
376 defmt::trace!("Binding socket {}", self.fd);
377
378 if token.is_cancelled() {
379 return Poll::Ready(Err(Error::OperationCancelled));
380 }
381
382 let address = NrfSockAddr::from(address);
384
385 register_socket_waker(cx.waker().clone(), self.fd, SocketDirection::Either);
386
387 let mut bind_result =
389 unsafe { nrfxlib_sys::nrf_bind(self.fd, address.as_ptr(), address.size() as u32) }
390 as isize;
391
392 const NRF_EINPROGRESS: isize = nrfxlib_sys::NRF_EINPROGRESS as isize;
393 const NRF_EALREADY: isize = nrfxlib_sys::NRF_EALREADY as isize;
394 const NRF_EISCONN: isize = nrfxlib_sys::NRF_EISCONN as isize;
395
396 if bind_result == -1 {
397 bind_result = get_last_error();
398 }
399
400 #[cfg(feature = "defmt")]
401 defmt::trace!("Bind result {}", bind_result);
402
403 match bind_result {
404 0 => Poll::Ready(Ok(())),
406 NRF_EISCONN => Poll::Ready(Ok(())),
408 NRF_EINPROGRESS | NRF_EALREADY => Poll::Pending,
410 error => Poll::Ready(Err(Error::NrfError(error))),
412 }
413 })
414 .await?;
415
416 Ok(())
417 }
418
419 pub async fn write(&self, buffer: &[u8], token: &CancellationToken) -> Result<usize, Error> {
421 token.bind_to_current_task().await;
422
423 core::future::poll_fn(|cx| {
424 #[cfg(feature = "defmt")]
425 defmt::trace!("Sending with socket {}", self.fd);
426
427 if token.is_cancelled() {
428 return Poll::Ready(Err(Error::OperationCancelled));
429 }
430
431 register_socket_waker(cx.waker().clone(), self.fd, SocketDirection::Out);
432
433 let mut send_result = unsafe {
434 nrfxlib_sys::nrf_send(self.fd, buffer.as_ptr() as *const _, buffer.len(), 0)
435 };
436
437 if send_result == -1 {
438 send_result = get_last_error().abs().neg();
439 }
440
441 #[cfg(feature = "defmt")]
442 defmt::trace!("Send result {}", send_result);
443
444 const NRF_EWOULDBLOCK: isize = -(nrfxlib_sys::NRF_EWOULDBLOCK as isize);
445 const NRF_ENOTCONN: isize = -(nrfxlib_sys::NRF_ENOTCONN as isize);
446
447 match send_result {
448 0 if !buffer.is_empty() => Poll::Ready(Err(Error::Disconnected)),
449 NRF_ENOTCONN => Poll::Ready(Err(Error::Disconnected)),
450 bytes_sent @ 0.. => Poll::Ready(Ok(bytes_sent as usize)),
451 NRF_EWOULDBLOCK => Poll::Pending,
452 error => Poll::Ready(Err(Error::NrfError(error))),
453 }
454 })
455 .await
456 }
457
458 pub async fn receive(
460 &self,
461 buffer: &mut [u8],
462 token: &CancellationToken,
463 ) -> Result<usize, Error> {
464 token.bind_to_current_task().await;
465
466 core::future::poll_fn(|cx| {
467 #[cfg(feature = "defmt")]
468 defmt::trace!("Receiving with socket {}", self.fd);
469
470 if token.is_cancelled() {
471 return Poll::Ready(Err(Error::OperationCancelled));
472 }
473
474 register_socket_waker(cx.waker().clone(), self.fd, SocketDirection::In);
475
476 let mut receive_result = unsafe {
477 nrfxlib_sys::nrf_recv(self.fd, buffer.as_mut_ptr() as *mut _, buffer.len(), 0)
478 };
479
480 if receive_result == -1 {
481 receive_result = get_last_error().abs().neg();
482 }
483
484 #[cfg(feature = "defmt")]
485 defmt::trace!("Receive result {}", receive_result);
486
487 const NRF_EWOULDBLOCK: isize = -(nrfxlib_sys::NRF_EWOULDBLOCK as isize);
488 const NRF_ENOTCONN: isize = -(nrfxlib_sys::NRF_ENOTCONN as isize);
489 const NRF_EMSGSIZE: isize = -(nrfxlib_sys::NRF_EMSGSIZE as isize);
490
491 match receive_result {
492 0 if !buffer.is_empty() => Poll::Ready(Err(Error::Disconnected)),
493 NRF_ENOTCONN => Poll::Ready(Err(Error::Disconnected)),
494 NRF_EMSGSIZE => Poll::Ready(Err(Error::TlsPacketTooBig)),
495 bytes_received @ 0.. => Poll::Ready(Ok(bytes_received as usize)),
496 NRF_EWOULDBLOCK => Poll::Pending,
497 error => Poll::Ready(Err(Error::NrfError(error))),
498 }
499 })
500 .await
501 }
502
503 pub async fn receive_from(
505 &self,
506 buffer: &mut [u8],
507 token: &CancellationToken,
508 ) -> Result<(usize, SocketAddr), Error> {
509 token.bind_to_current_task().await;
510
511 core::future::poll_fn(|cx| {
512 #[cfg(feature = "defmt")]
513 defmt::trace!("Receiving with socket {}", self.fd);
514
515 if token.is_cancelled() {
516 return Poll::Ready(Err(Error::OperationCancelled));
517 }
518
519 let mut socket_addr_store =
521 [0u8; core::mem::size_of::<nrfxlib_sys::nrf_sockaddr_in6>()];
522 let socket_addr_ptr = socket_addr_store.as_mut_ptr() as *mut nrfxlib_sys::nrf_sockaddr;
523 let mut socket_addr_len = socket_addr_store.len() as u32;
524
525 register_socket_waker(cx.waker().clone(), self.fd, SocketDirection::In);
526
527 let mut receive_result = unsafe {
528 nrfxlib_sys::nrf_recvfrom(
529 self.fd,
530 buffer.as_mut_ptr() as *mut _,
531 buffer.len(),
532 0,
533 socket_addr_ptr,
534 &mut socket_addr_len as *mut u32,
535 )
536 };
537
538 if receive_result == -1 {
539 receive_result = get_last_error().abs().neg();
540 }
541
542 #[cfg(feature = "defmt")]
543 defmt::trace!("Receive result {}", receive_result);
544
545 const NRF_EWOULDBLOCK: isize = -(nrfxlib_sys::NRF_EWOULDBLOCK as isize);
546 const NRF_ENOTCONN: isize = -(nrfxlib_sys::NRF_ENOTCONN as isize);
547
548 match receive_result {
549 0 if !buffer.is_empty() => Poll::Ready(Err(Error::Disconnected)),
550 NRF_ENOTCONN => Poll::Ready(Err(Error::Disconnected)),
551 bytes_received @ 0.. => Poll::Ready(Ok((bytes_received as usize, {
552 unsafe { (*socket_addr_ptr).sa_family = self.family as u16 }
553 NrfSockAddr::from(socket_addr_ptr as *const _).into()
554 }))),
555 NRF_EWOULDBLOCK => Poll::Pending,
556 error => Poll::Ready(Err(Error::NrfError(error))),
557 }
558 })
559 .await
560 }
561
562 pub async fn send_to(
564 &self,
565 buffer: &[u8],
566 address: SocketAddr,
567 token: &CancellationToken,
568 ) -> Result<usize, Error> {
569 token.bind_to_current_task().await;
570
571 core::future::poll_fn(|cx| {
572 #[cfg(feature = "defmt")]
573 defmt::trace!("Sending with socket {}", self.fd);
574
575 if token.is_cancelled() {
576 return Poll::Ready(Err(Error::OperationCancelled));
577 }
578
579 let addr = NrfSockAddr::from(address);
580
581 register_socket_waker(cx.waker().clone(), self.fd, SocketDirection::Out);
582
583 let mut send_result = unsafe {
584 nrfxlib_sys::nrf_sendto(
585 self.fd,
586 buffer.as_ptr() as *mut _,
587 buffer.len(),
588 0,
589 addr.as_ptr(),
590 addr.size() as u32,
591 )
592 };
593
594 if send_result == -1 {
595 send_result = get_last_error().abs().neg();
596 }
597
598 #[cfg(feature = "defmt")]
599 defmt::trace!("Sending result {}", send_result);
600
601 const NRF_EWOULDBLOCK: isize = -(nrfxlib_sys::NRF_EWOULDBLOCK as isize);
602 const NRF_ENOTCONN: isize = -(nrfxlib_sys::NRF_ENOTCONN as isize);
603
604 match send_result {
605 0 if !buffer.is_empty() => Poll::Ready(Err(Error::Disconnected)),
606 NRF_ENOTCONN => Poll::Ready(Err(Error::Disconnected)),
607 bytes_received @ 0.. => Poll::Ready(Ok(bytes_received as usize)),
608 NRF_EWOULDBLOCK => Poll::Pending,
609 error => Poll::Ready(Err(Error::NrfError(error))),
610 }
611 })
612 .await
613 }
614
615 pub fn set_option<'a>(&'a self, option: SocketOption<'a>) -> Result<(), SocketOptionError> {
616 let length = option.get_length();
617
618 let result = unsafe {
619 nrfxlib_sys::nrf_setsockopt(
620 self.fd,
621 nrfxlib_sys::NRF_SOL_SECURE.try_into().unwrap(),
622 option.get_name(),
623 option.get_value(),
624 length,
625 )
626 };
627
628 if result < 0 {
629 Err(result.into())
630 } else {
631 Ok(())
632 }
633 }
634
635 pub async fn deactivate(mut self) -> Result<(), Error> {
638 self.link.take().unwrap().deactivate().await?;
639 Ok(())
640 }
641}
642
643impl Drop for Socket {
644 fn drop(&mut self) {
645 if !self.split {
646 let e = unsafe { nrfxlib_sys::nrf_close(self.fd) };
647
648 if e == -1 {
649 panic!("{:?}", Error::NrfError(get_last_error()));
650 }
651 }
652 }
653}
654
655impl PartialEq for Socket {
656 fn eq(&self, other: &Self) -> bool {
657 self.fd == other.fd
658 }
659}
660impl Eq for Socket {}
661
662#[repr(u32)]
663#[derive(Debug, Clone, Copy, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
664#[cfg_attr(feature = "defmt", derive(defmt::Format))]
665pub enum SocketFamily {
666 Unspecified = nrfxlib_sys::NRF_AF_UNSPEC,
667 Ipv4 = nrfxlib_sys::NRF_AF_INET,
668 Ipv6 = nrfxlib_sys::NRF_AF_INET6,
669 Raw = nrfxlib_sys::NRF_AF_PACKET,
670}
671
672#[repr(u32)]
673#[derive(Debug, Clone, Copy, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
674#[cfg_attr(feature = "defmt", derive(defmt::Format))]
675pub enum SocketType {
676 Stream = nrfxlib_sys::NRF_SOCK_STREAM,
677 Datagram = nrfxlib_sys::NRF_SOCK_DGRAM,
678 Raw = nrfxlib_sys::NRF_SOCK_RAW,
679}
680
681#[repr(u32)]
682#[derive(Debug, Clone, Copy, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
683#[cfg_attr(feature = "defmt", derive(defmt::Format))]
684pub enum SocketProtocol {
685 IP = nrfxlib_sys::NRF_IPPROTO_IP,
686 Tcp = nrfxlib_sys::NRF_IPPROTO_TCP,
687 Udp = nrfxlib_sys::NRF_IPPROTO_UDP,
688 Ipv6 = nrfxlib_sys::NRF_IPPROTO_IPV6,
689 Raw = nrfxlib_sys::NRF_IPPROTO_RAW,
690 All = nrfxlib_sys::NRF_IPPROTO_ALL,
691 Tls1v2 = nrfxlib_sys::NRF_SPROTO_TLS1v2,
692 DTls1v2 = nrfxlib_sys::NRF_SPROTO_DTLS1v2,
693}
694
695#[allow(clippy::enum_variant_names)]
696#[derive(Debug)]
697pub enum SocketOption<'a> {
698 TlsHostName(&'a str),
699 TlsPeerVerify(i32),
700 TlsSessionCache(i32),
701 TlsTagList(&'a [nrfxlib_sys::nrf_sec_tag_t]),
702 TlsCipherSuiteList(&'a [i32]),
703}
704impl SocketOption<'_> {
705 pub(crate) fn get_name(&self) -> i32 {
706 match self {
707 SocketOption::TlsHostName(_) => nrfxlib_sys::NRF_SO_SEC_HOSTNAME as i32,
708 SocketOption::TlsPeerVerify(_) => nrfxlib_sys::NRF_SO_SEC_PEER_VERIFY as i32,
709 SocketOption::TlsSessionCache(_) => nrfxlib_sys::NRF_SO_SEC_SESSION_CACHE as i32,
710 SocketOption::TlsTagList(_) => nrfxlib_sys::NRF_SO_SEC_TAG_LIST as i32,
711 SocketOption::TlsCipherSuiteList(_) => nrfxlib_sys::NRF_SO_SEC_CIPHERSUITE_LIST as i32,
712 }
713 }
714
715 pub(crate) fn get_value(&self) -> *const core::ffi::c_void {
716 match self {
717 SocketOption::TlsHostName(s) => s.as_ptr() as *const core::ffi::c_void,
718 SocketOption::TlsPeerVerify(x) => x as *const _ as *const core::ffi::c_void,
719 SocketOption::TlsSessionCache(x) => x as *const _ as *const core::ffi::c_void,
720 SocketOption::TlsTagList(x) => x.as_ptr() as *const core::ffi::c_void,
721 SocketOption::TlsCipherSuiteList(x) => x.as_ptr() as *const core::ffi::c_void,
722 }
723 }
724
725 pub(crate) fn get_length(&self) -> u32 {
726 match self {
727 SocketOption::TlsHostName(s) => s.len() as u32,
728 SocketOption::TlsPeerVerify(x) => core::mem::size_of_val(x) as u32,
729 SocketOption::TlsSessionCache(x) => core::mem::size_of_val(x) as u32,
730 SocketOption::TlsTagList(x) => core::mem::size_of_val(*x) as u32,
731 SocketOption::TlsCipherSuiteList(x) => core::mem::size_of_val(*x) as u32,
732 }
733 }
734}
735
736#[derive(Debug, Copy, Clone)]
737pub enum PeerVerification {
738 Enabled,
739 Optional,
740 Disabled,
741}
742
743impl PeerVerification {
744 pub fn as_integer(self) -> i32 {
745 match self {
746 PeerVerification::Enabled => 2,
747 PeerVerification::Optional => 1,
748 PeerVerification::Disabled => 0,
749 }
750 }
751}
752
753#[repr(i32)]
755#[allow(non_camel_case_types)]
756#[derive(Debug, Copy, Clone)]
757pub enum CipherSuite {
758 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 =
759 nrfxlib_sys::NRF_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 as i32,
760 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA =
761 nrfxlib_sys::NRF_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA as i32,
762 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 =
763 nrfxlib_sys::NRF_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 as i32,
764 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA =
765 nrfxlib_sys::NRF_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA as i32,
766 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = nrfxlib_sys::NRF_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA as i32,
767 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 =
768 nrfxlib_sys::NRF_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 as i32,
769 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = nrfxlib_sys::NRF_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA as i32,
770 TLS_PSK_WITH_AES_256_CBC_SHA = nrfxlib_sys::NRF_TLS_PSK_WITH_AES_256_CBC_SHA as i32,
771 TLS_PSK_WITH_AES_128_CBC_SHA256 = nrfxlib_sys::NRF_TLS_PSK_WITH_AES_128_CBC_SHA256 as i32,
772 TLS_PSK_WITH_AES_128_CBC_SHA = nrfxlib_sys::NRF_TLS_PSK_WITH_AES_128_CBC_SHA as i32,
773 TLS_PSK_WITH_AES_128_CCM_8 = nrfxlib_sys::NRF_TLS_PSK_WITH_AES_128_CCM_8 as i32,
774 TLS_EMPTY_RENEGOTIATIONINFO_SCSV = nrfxlib_sys::NRF_TLS_EMPTY_RENEGOTIATIONINFO_SCSV as i32,
775 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 =
776 nrfxlib_sys::NRF_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 as i32,
777 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 =
778 nrfxlib_sys::NRF_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 as i32,
779 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 =
780 nrfxlib_sys::NRF_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 as i32,
781}
782
783#[derive(Debug, Clone)]
784#[cfg_attr(feature = "defmt", derive(defmt::Format))]
785pub enum SocketOptionError {
786 InvalidFileDescriptor,
788 TimeoutTooBig,
790 InvalidOption,
792 AlreadyConnected,
794 UnsupportedOption,
796 NotASocket,
798 OutOfMemory,
800 OutOfResources,
802}
803
804impl From<i32> for SocketOptionError {
805 fn from(errno: i32) -> Self {
806 match errno.unsigned_abs() {
807 nrfxlib_sys::NRF_EBADF => SocketOptionError::InvalidFileDescriptor,
808 nrfxlib_sys::NRF_EINVAL => SocketOptionError::InvalidOption,
809 nrfxlib_sys::NRF_EISCONN => SocketOptionError::AlreadyConnected,
810 nrfxlib_sys::NRF_ENOPROTOOPT => SocketOptionError::UnsupportedOption,
811 nrfxlib_sys::NRF_ENOTSOCK => SocketOptionError::NotASocket,
812 nrfxlib_sys::NRF_ENOMEM => SocketOptionError::OutOfMemory,
813 nrfxlib_sys::NRF_ENOBUFS => SocketOptionError::OutOfResources,
814 _ => panic!("Unknown error code: {}", errno),
815 }
816 }
817}
818
819#[allow(clippy::declare_interior_mutable_const)]
820const ATOMIC_U8_INIT: AtomicU8 = AtomicU8::new(0);
821static ACTIVE_SPLIT_SOCKETS: [AtomicU8; nrfxlib_sys::NRF_MODEM_MAX_SOCKET_COUNT as usize] =
822 [ATOMIC_U8_INIT; nrfxlib_sys::NRF_MODEM_MAX_SOCKET_COUNT as usize];
823
824pub struct SplitSocketHandle {
825 inner: Option<Socket>,
826 index: usize,
827}
828
829impl SplitSocketHandle {
830 pub async fn deactivate(mut self) -> Result<(), Error> {
831 let mut inner = self.inner.take().unwrap();
832
833 if ACTIVE_SPLIT_SOCKETS[self.index].fetch_sub(1, Ordering::SeqCst) == 1 {
834 inner.split = false;
836 }
837
838 inner.deactivate().await?;
839
840 Ok(())
841 }
842
843 fn get_new_spot() -> usize {
844 for (index, count) in ACTIVE_SPLIT_SOCKETS.iter().enumerate() {
845 if count
846 .compare_exchange(0, 2, Ordering::SeqCst, Ordering::SeqCst)
847 .is_ok()
848 {
849 return index;
850 }
851 }
852
853 unreachable!("It should not be possible to have more splits than the maximum socket count");
854 }
855}
856
857impl Deref for SplitSocketHandle {
858 type Target = Socket;
859
860 fn deref(&self) -> &Self::Target {
861 self.inner.as_ref().unwrap()
862 }
863}
864
865impl Drop for SplitSocketHandle {
866 fn drop(&mut self) {
867 if let Some(inner) = self.inner.as_mut() {
868 if ACTIVE_SPLIT_SOCKETS[self.index].fetch_sub(1, Ordering::SeqCst) == 1 {
869 inner.split = false;
871 }
872 }
873 }
874}