1 use crate::config::*;
2 use crate::conn::DTLSConn;
3 use crate::content::ContentType;
4 use crate::error::Result;
5 use crate::record_layer::record_layer_header::RecordLayerHeader;
6 use crate::record_layer::unpack_datagram;
7
8 use async_trait::async_trait;
9 use std::future::Future;
10 use std::io::BufReader;
11 use std::net::SocketAddr;
12 use std::pin::Pin;
13 use std::sync::Arc;
14 use tokio::net::ToSocketAddrs;
15 use util::{conn::conn_udp_listener::*, conn::*};
16
17 /// Listen creates a DTLS listener
listen<A: 'static + ToSocketAddrs>(laddr: A, config: Config) -> Result<impl Listener>18 pub async fn listen<A: 'static + ToSocketAddrs>(laddr: A, config: Config) -> Result<impl Listener> {
19 validate_config(false, &config)?;
20
21 let mut lc = ListenConfig {
22 accept_filter: Some(Box::new(
23 |packet: &[u8]| -> Pin<Box<dyn Future<Output = bool> + Send + 'static>> {
24 let pkts = match unpack_datagram(packet) {
25 Ok(pkts) => {
26 if pkts.is_empty() {
27 return Box::pin(async { false });
28 }
29 pkts
30 }
31 Err(_) => return Box::pin(async { false }),
32 };
33
34 let mut reader = BufReader::new(pkts[0].as_slice());
35 match RecordLayerHeader::unmarshal(&mut reader) {
36 Ok(h) => {
37 let content_type = h.content_type;
38 Box::pin(async move { content_type == ContentType::Handshake })
39 }
40 Err(_) => Box::pin(async { false }),
41 }
42 },
43 )),
44 ..Default::default()
45 };
46
47 let parent = Arc::new(lc.listen(laddr).await?);
48 Ok(DTLSListener { parent, config })
49 }
50
51 /// DTLSListener represents a DTLS listener
52 pub struct DTLSListener {
53 parent: Arc<dyn Listener + Send + Sync>,
54 config: Config,
55 }
56
57 impl DTLSListener {
58 /// creates a DTLS listener which accepts connections from an inner Listener.
new(parent: Arc<dyn Listener + Send + Sync>, config: Config) -> Result<Self>59 pub fn new(parent: Arc<dyn Listener + Send + Sync>, config: Config) -> Result<Self> {
60 validate_config(false, &config)?;
61
62 Ok(DTLSListener { parent, config })
63 }
64 }
65
66 type UtilResult<T> = std::result::Result<T, util::Error>;
67
68 #[async_trait]
69 impl Listener for DTLSListener {
70 /// Accept waits for and returns the next connection to the listener.
71 /// You have to either close or read on all connection that are created.
72 /// Connection handshake will timeout using ConnectContextMaker in the Config.
73 /// If you want to specify the timeout duration, set ConnectContextMaker.
accept(&self) -> UtilResult<(Arc<dyn Conn + Send + Sync>, SocketAddr)>74 async fn accept(&self) -> UtilResult<(Arc<dyn Conn + Send + Sync>, SocketAddr)> {
75 let (conn, raddr) = self.parent.accept().await?;
76 let dtls_conn = DTLSConn::new(conn, self.config.clone(), false, None)
77 .await
78 .map_err(util::Error::from_std)?;
79 Ok((Arc::new(dtls_conn), raddr))
80 }
81
82 /// Close closes the listener.
83 /// Any blocked Accept operations will be unblocked and return errors.
84 /// Already Accepted connections are not closed.
close(&self) -> UtilResult<()>85 async fn close(&self) -> UtilResult<()> {
86 self.parent.close().await
87 }
88
89 /// Addr returns the listener's network address.
addr(&self) -> UtilResult<SocketAddr>90 async fn addr(&self) -> UtilResult<SocketAddr> {
91 self.parent.addr().await
92 }
93 }
94