distant_net/server/builder/
tcp.rs

1use std::io;
2use std::net::IpAddr;
3
4use distant_auth::Verifier;
5use serde::de::DeserializeOwned;
6use serde::Serialize;
7
8use crate::common::{PortRange, TcpListener, Version};
9use crate::server::{Server, ServerConfig, ServerHandler, TcpServerRef};
10
11pub struct TcpServerBuilder<T>(Server<T>);
12
13impl<T> Server<T> {
14    /// Consume [`Server`] and produce a builder for a TCP variant.
15    pub fn into_tcp_builder(self) -> TcpServerBuilder<T> {
16        TcpServerBuilder(self)
17    }
18}
19
20impl Default for TcpServerBuilder<()> {
21    fn default() -> Self {
22        Self(Server::new())
23    }
24}
25
26impl<T> TcpServerBuilder<T> {
27    pub fn config(self, config: ServerConfig) -> Self {
28        Self(self.0.config(config))
29    }
30
31    pub fn handler<U>(self, handler: U) -> TcpServerBuilder<U> {
32        TcpServerBuilder(self.0.handler(handler))
33    }
34
35    pub fn verifier(self, verifier: Verifier) -> Self {
36        Self(self.0.verifier(verifier))
37    }
38
39    pub fn version(self, version: Version) -> Self {
40        Self(self.0.version(version))
41    }
42}
43
44impl<T> TcpServerBuilder<T>
45where
46    T: ServerHandler + Sync + 'static,
47    T::Request: DeserializeOwned + Send + Sync + 'static,
48    T::Response: Serialize + Send + 'static,
49{
50    pub async fn start<P>(self, addr: IpAddr, port: P) -> io::Result<TcpServerRef>
51    where
52        P: Into<PortRange> + Send,
53    {
54        let listener = TcpListener::bind(addr, port).await?;
55        let port = listener.port();
56        let inner = self.0.start(listener)?;
57        Ok(TcpServerRef { addr, port, inner })
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use std::net::{Ipv6Addr, SocketAddr};
64
65    use async_trait::async_trait;
66    use distant_auth::DummyAuthHandler;
67    use test_log::test;
68
69    use super::*;
70    use crate::client::Client;
71    use crate::common::Request;
72    use crate::server::RequestCtx;
73
74    pub struct TestServerHandler;
75
76    #[async_trait]
77    impl ServerHandler for TestServerHandler {
78        type Request = String;
79        type Response = String;
80
81        async fn on_request(&self, ctx: RequestCtx<Self::Request, Self::Response>) {
82            // Echo back what we received
83            ctx.reply.send(ctx.request.payload.to_string()).unwrap();
84        }
85    }
86
87    #[test(tokio::test)]
88    async fn should_invoke_handler_upon_receiving_a_request() {
89        let server = TcpServerBuilder::default()
90            .handler(TestServerHandler)
91            .verifier(Verifier::none())
92            .start(IpAddr::V6(Ipv6Addr::LOCALHOST), 0)
93            .await
94            .expect("Failed to start TCP server");
95
96        let mut client: Client<String, String> =
97            Client::tcp(SocketAddr::from((server.ip_addr(), server.port())))
98                .auth_handler(DummyAuthHandler)
99                .connect()
100                .await
101                .expect("Client failed to connect");
102
103        let response = client
104            .send(Request::new("hello".to_string()))
105            .await
106            .expect("Failed to send message");
107        assert_eq!(response.payload, "hello");
108    }
109}