rocket/listener/
tcp.rs

1//! TCP listener.
2//!
3//! # Configuration
4//!
5//! Reads the following configuration parameters:
6//!
7//! | parameter | type         | default     | note                            |
8//! |-----------|--------------|-------------|---------------------------------|
9//! | `address` | [`Endpoint`] | `127.0.0.1` | must be `tcp:ip`                |
10//! | `port`    | `u16`        | `8000`      | replaces the port in `address ` |
11
12use std::io;
13use std::net::{Ipv4Addr, SocketAddr};
14
15use either::{Either, Left, Right};
16
17#[doc(inline)]
18pub use tokio::net::{TcpListener, TcpStream};
19
20use crate::{Ignite, Rocket};
21use crate::listener::{Bind, Connection, Endpoint, Listener};
22
23impl Bind for TcpListener {
24    type Error = Either<figment::Error, io::Error>;
25
26    async fn bind(rocket: &Rocket<Ignite>) -> Result<Self, Self::Error> {
27        let endpoint = Self::bind_endpoint(rocket)?;
28        let addr = endpoint.tcp()
29            .ok_or_else(|| io::Error::other("internal error: invalid endpoint"))
30            .map_err(Right)?;
31
32        Self::bind(addr).await.map_err(Right)
33    }
34
35    fn bind_endpoint(rocket: &Rocket<Ignite>) -> Result<Endpoint, Self::Error> {
36        let figment = rocket.figment();
37        let mut address = Endpoint::fetch(figment, "tcp", "address", |e| {
38            let default = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 8000);
39            e.map(|e| e.tcp()).unwrap_or(Some(default))
40        }).map_err(Left)?;
41
42        if figment.contains("port") {
43            let port = figment.extract_inner("port").map_err(Left)?;
44            address.set_port(port);
45        }
46
47        Ok(Endpoint::Tcp(address))
48    }
49}
50
51impl Listener for TcpListener {
52    type Accept = Self::Connection;
53
54    type Connection = TcpStream;
55
56    async fn accept(&self) -> io::Result<Self::Accept> {
57        let conn = self.accept().await?.0;
58        let _ = conn.set_nodelay(true);
59        let _ = conn.set_linger(None);
60        Ok(conn)
61    }
62
63    async fn connect(&self, conn: Self::Connection) -> io::Result<Self::Connection> {
64        Ok(conn)
65    }
66
67    fn endpoint(&self) -> io::Result<Endpoint> {
68        self.local_addr().map(Endpoint::Tcp)
69    }
70}
71
72impl Connection for TcpStream {
73    fn endpoint(&self) -> io::Result<Endpoint> {
74        self.peer_addr().map(Endpoint::Tcp)
75    }
76}