nrf_modem/
dtls_socket.rs

1use crate::{
2    dns,
3    error::Error,
4    socket::{Socket, SocketFamily, SocketOption, SocketProtocol, SocketType, SplitSocketHandle},
5    CancellationToken, CipherSuite, PeerVerification,
6};
7
8use core::net::SocketAddr;
9
10pub struct DtlsSocket {
11    inner: Socket,
12}
13
14macro_rules! impl_receive_from {
15    () => {
16        pub async fn receive_from<'buf>(
17            &self,
18            buf: &'buf mut [u8],
19        ) -> Result<(&'buf mut [u8], SocketAddr), Error> {
20            self.receive_from_with_cancellation(buf, &Default::default())
21                .await
22        }
23
24        pub async fn receive_from_with_cancellation<'buf>(
25            &self,
26            buf: &'buf mut [u8],
27            token: &CancellationToken,
28        ) -> Result<(&'buf mut [u8], SocketAddr), Error> {
29            let (received_len, addr) = self
30                .socket()
31                .receive_from_with_cancellation(buf, token)
32                .await?;
33            Ok((&mut buf[..received_len], addr))
34        }
35    };
36}
37
38macro_rules! impl_send {
39    () => {
40        pub async fn send(&self, buf: &[u8]) -> Result<(), Error> {
41            self.send_with_cancellation(buf, &Default::default()).await
42        }
43
44        pub async fn send_with_cancellation(
45            &self,
46            buf: &[u8],
47            token: &CancellationToken,
48        ) -> Result<(), Error> {
49            self.socket()
50                .write_with_cancellation(buf, token)
51                .await
52                .map(|_| ())
53        }
54    };
55}
56
57impl DtlsSocket {
58    pub async fn connect(
59        hostname: &str,
60        port: u16,
61        peer_verify: PeerVerification,
62        security_tags: &[u32],
63        ciphers: Option<&[CipherSuite]>,
64    ) -> Result<Self, Error> {
65        Self::connect_with_cancellation(
66            hostname,
67            port,
68            peer_verify,
69            security_tags,
70            ciphers,
71            &Default::default(),
72        )
73        .await
74    }
75
76    pub async fn connect_with_cancellation(
77        hostname: &str,
78        port: u16,
79        peer_verify: PeerVerification,
80        security_tags: &[u32],
81        ciphers: Option<&[CipherSuite]>,
82
83        token: &CancellationToken,
84    ) -> Result<Self, Error> {
85        if security_tags.is_empty() {
86            return Err(Error::NoSecurityTag);
87        }
88
89        let inner = Socket::create(
90            SocketFamily::Ipv4,
91            SocketType::Datagram,
92            SocketProtocol::DTls1v2,
93        )
94        .await?;
95        inner.set_option(SocketOption::TlsPeerVerify(peer_verify.as_integer()))?;
96        inner.set_option(SocketOption::TlsSessionCache(0))?;
97        inner.set_option(SocketOption::TlsTagList(security_tags))?;
98        inner.set_option(SocketOption::TlsHostName(hostname))?;
99        if let Some(ciphers) = ciphers {
100            inner.set_option(SocketOption::TlsCipherSuiteList(unsafe {
101                core::slice::from_raw_parts(ciphers.as_ptr() as *const i32, ciphers.len())
102            }))?;
103        }
104
105        token.as_result()?;
106
107        let ip = dns::get_host_by_name_with_cancellation(hostname, token).await?;
108        let addr = SocketAddr::from((ip, port));
109
110        unsafe {
111            inner.connect_with_cancellation(addr, token).await?;
112        }
113
114        Ok(DtlsSocket { inner })
115    }
116
117    pub fn as_raw_fd(&self) -> i32 {
118        self.inner.as_raw_fd()
119    }
120
121    fn socket(&self) -> &Socket {
122        &self.inner
123    }
124
125    pub async fn split_owned(self) -> Result<(OwnedDtlsReceiveSocket, OwnedDtlsSendSocket), Error> {
126        let (read_split, write_split) = self.inner.split().await?;
127
128        Ok((
129            OwnedDtlsReceiveSocket { socket: read_split },
130            OwnedDtlsSendSocket {
131                socket: write_split,
132            },
133        ))
134    }
135
136    pub fn split(&self) -> (DtlsReceiveSocket<'_>, DtlsSendSocket<'_>) {
137        (
138            DtlsReceiveSocket { socket: self },
139            DtlsSendSocket { socket: self },
140        )
141    }
142
143    impl_receive_from!();
144    impl_send!();
145
146    /// Deactivates the socket and the LTE link.
147    /// A normal drop will do the same thing, but blocking.
148    pub async fn deactivate(self) -> Result<(), Error> {
149        self.inner.deactivate().await?;
150        Ok(())
151    }
152}
153
154pub struct DtlsReceiveSocket<'a> {
155    socket: &'a DtlsSocket,
156}
157
158impl DtlsReceiveSocket<'_> {
159    fn socket(&self) -> &Socket {
160        &self.socket.inner
161    }
162
163    impl_receive_from!();
164}
165
166pub struct DtlsSendSocket<'a> {
167    socket: &'a DtlsSocket,
168}
169
170impl DtlsSendSocket<'_> {
171    fn socket(&self) -> &Socket {
172        &self.socket.inner
173    }
174
175    impl_send!();
176}
177
178pub struct OwnedDtlsReceiveSocket {
179    socket: SplitSocketHandle,
180}
181
182impl OwnedDtlsReceiveSocket {
183    fn socket(&self) -> &Socket {
184        &self.socket
185    }
186
187    impl_receive_from!();
188}
189
190pub struct OwnedDtlsSendSocket {
191    socket: SplitSocketHandle,
192}
193
194impl OwnedDtlsSendSocket {
195    fn socket(&self) -> &Socket {
196        &self.socket
197    }
198
199    impl_send!();
200}