xref: /webrtc/dtls/src/listener.rs (revision ffe74184)
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