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}