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 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}