1 use crate::tls::TlsConnectionMetadata;
3 use async_std::net::{SocketAddr, TcpListener, ToSocketAddrs};
4 use async_std::pin::Pin;
5 use async_std::task::{Context, Poll};
6 use async_tls::TlsAcceptor;
7 use futures::{Stream, StreamExt};
10 /// Listens on a bound socket for incoming TLS connections to be handled as independent
13 /// Implements the [`Stream`] trait to asynchronously accept incoming TLS connections.
20 /// let mut server = TlsListener::bind("127.0.0.1:3456", config.into()).await?;
22 /// // wait for a connection to come in and be accepted
23 /// while let Some(mut conn) = server.next().await {
24 /// // do something with connection
28 pub struct TlsListener {
29 local_addrs: SocketAddr,
30 listener: TcpListener,
31 acceptor: TlsAcceptor,
35 /// Creates a [`TlsListener`] by binding to an IP address and port and listens for incoming TLS
36 /// connections that have successfully been accepted.
43 /// let mut server = TlsListener::bind("127.0.0.1:3456", config.into()).await?;
45 pub async fn bind<A: ToSocketAddrs + std::fmt::Display>(
47 acceptor: TlsAcceptor,
48 ) -> anyhow::Result<Self> {
49 let listener = TcpListener::bind(ip_addrs).await?;
50 info!("Started TLS server at {}", listener.local_addr()?);
53 local_addrs: listener.local_addr()?,
59 /// Creates a [`Connection`] for the next `accept`ed TCP connection at the bound socket.
66 /// let mut server = TlsListener::bind("127.0.0.1:3456", config.into()).await?;
67 /// while let Some(mut conn) = server.next().await {
68 /// // do something with connection
71 pub async fn accept(&self) -> anyhow::Result<Connection> {
72 let (tcp_stream, peer_addr) = self.listener.accept().await?;
73 debug!("Received connection attempt from {}", peer_addr);
75 match self.acceptor.accept(tcp_stream).await {
77 debug!("Completed TLS handshake with {}", peer_addr);
78 Ok(Connection::from(TlsConnectionMetadata::Listener {
79 local_addr: self.local_addrs.clone(),
86 warn!("Could not encrypt connection with TLS from {}", peer_addr);
87 Err(anyhow::Error::new(e))
93 impl Stream for TlsListener {
94 type Item = Connection;
96 fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
97 match futures::executor::block_on(self.listener.incoming().next()) {
98 Some(Ok(tcp_stream)) => {
99 let peer_addr = tcp_stream
101 .expect("Could not retrieve peer IP address");
102 debug!("Received connection attempt from {}", peer_addr);
104 match futures::executor::block_on(self.acceptor.accept(tcp_stream)) {
106 debug!("Completed TLS handshake with {}", peer_addr);
107 Poll::Ready(Some(Connection::from(TlsConnectionMetadata::Listener {
108 local_addr: self.local_addrs.clone(),
115 warn!("Could not encrypt connection with TLS from {}", peer_addr);
123 "Encountered error when trying to accept new connection {}",
129 None => Poll::Ready(None),