s2n_quic/
server.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{connection::Connection, provider::*};
5use core::{
6    fmt,
7    task::{Context, Poll},
8};
9use s2n_quic_transport::endpoint::handle::Acceptor;
10
11mod builder;
12mod providers;
13
14pub use builder::*;
15pub use providers::*;
16pub use s2n_quic_core::application::ServerName as Name;
17
18/// A QUIC server endpoint, capable of accepting connections
19pub struct Server {
20    acceptor: Acceptor,
21    local_addr: s2n_quic_core::inet::SocketAddress,
22}
23
24impl fmt::Debug for Server {
25    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26        f.debug_struct("Server")
27            .field("local_addr", &self.local_addr().ok())
28            .finish()
29    }
30}
31
32impl Server {
33    /// Returns a [`Builder`] which is able to configure the [`Server`] components.
34    ///
35    /// # Examples
36    ///
37    /// ```rust,no_run
38    /// # use std::{error::Error, path::Path};
39    /// # use s2n_quic::Server;
40    /// #
41    /// # fn main() -> Result<(), Box<dyn Error>> {
42    /// let server = Server::builder()
43    ///     .with_tls((Path::new("./certs/cert.pem"), Path::new("./certs/key.pem")))?
44    ///     .with_io("127.0.0.1:443")?
45    ///     .start()?;
46    /// #
47    /// #    Ok(())
48    /// # }
49    /// ```
50    pub fn builder() -> Builder<impl ServerProviders> {
51        Builder::default()
52    }
53
54    /// Accepts a new incoming [`Connection`] from this [`Server`].
55    ///
56    /// This function will yield once a new QUIC connection is established. When established,
57    /// the corresponding [`Connection`] will be returned.
58    ///
59    /// # Examples
60    ///
61    /// ```rust,no_run
62    /// # use std::{error::Error, path::Path};
63    /// # use s2n_quic::Server;
64    /// #
65    /// # #[tokio::main]
66    /// # async fn main() -> Result<(), Box<dyn Error>> {
67    /// let mut server = Server::builder()
68    ///     .with_tls((Path::new("./certs/cert.pem"), Path::new("./certs/key.pem")))?
69    ///     .with_io("127.0.0.1:443")?
70    ///     .start()?;
71    ///
72    /// match server.accept().await {
73    ///     Some(connection) => {
74    ///         println!("new connection: {:?}", connection.remote_addr());
75    ///     }
76    ///     None => println!("server closed"),
77    /// }
78    /// #    Ok(())
79    /// # }
80    /// ```
81    pub async fn accept(&mut self) -> Option<Connection> {
82        futures::future::poll_fn(|cx| self.poll_accept(cx)).await
83    }
84
85    /// Attempts to accept a new incoming [`Connection`] from this [`Server`].
86    ///
87    /// # Return value
88    ///
89    /// This function returns:
90    ///
91    /// - `Poll::Pending` if no new connections have been established.
92    /// - `Poll::Ready(Some(connection))` once a new connection has been established.
93    ///   This function can be called again to try and accept new connections.
94    /// - `Poll::Ready(None)` the attempt failed because the server has closed. Once
95    ///   None is returned, this function should not be called again.
96    pub fn poll_accept(&mut self, cx: &mut Context) -> Poll<Option<Connection>> {
97        s2n_quic_core::task::waker::debug_assert_contract(cx, |cx| {
98            match self.acceptor.poll_accept(cx) {
99                Poll::Ready(Some(connection)) => Poll::Ready(Some(Connection::new(connection))),
100                Poll::Ready(None) => Poll::Ready(None),
101                Poll::Pending => Poll::Pending,
102            }
103        })
104    }
105
106    /// Returns the local address that this listener is bound to.
107    ///
108    /// This can be useful, for example, when binding to port `0` to figure out which
109    /// port was actually bound.
110    ///
111    /// # Examples
112    ///
113    /// ```rust,no_run
114    /// # use std::{error::Error, path::Path};
115    /// # use s2n_quic::Server;
116    /// #
117    /// # fn main() -> Result<(), Box<dyn Error>> {
118    /// let server = Server::builder()
119    ///     .with_tls((Path::new("./certs/cert.pem"), Path::new("./certs/key.pem")))?
120    ///     .with_io("127.0.0.1:443")?
121    ///     .start()?;
122    ///
123    /// let local_addr = server.local_addr()?;
124    ///
125    /// #    Ok(())
126    /// # }
127    /// ```
128    pub fn local_addr(&self) -> Result<std::net::SocketAddr, std::io::Error> {
129        Ok(self.local_addr.into())
130    }
131}
132
133impl futures::stream::Stream for Server {
134    type Item = Connection;
135
136    fn poll_next(
137        mut self: core::pin::Pin<&mut Self>,
138        cx: &mut core::task::Context<'_>,
139    ) -> core::task::Poll<Option<Self::Item>> {
140        self.poll_accept(cx)
141    }
142}