use std::io; use std::path::Path; use distant_core_auth::Verifier; use serde::de::DeserializeOwned; use serde::Serialize; use crate::common::{UnixSocketListener, Version}; use crate::server::{Server, ServerConfig, ServerHandler, UnixSocketServerRef}; pub struct UnixSocketServerBuilder(Server); impl Server { /// Consume [`Server`] and produce a builder for a Unix socket variant. pub fn into_unix_socket_builder(self) -> UnixSocketServerBuilder { UnixSocketServerBuilder(self) } } impl Default for UnixSocketServerBuilder<()> { fn default() -> Self { Self(Server::new()) } } impl UnixSocketServerBuilder { pub fn config(self, config: ServerConfig) -> Self { Self(self.0.config(config)) } pub fn handler(self, handler: U) -> UnixSocketServerBuilder { UnixSocketServerBuilder(self.0.handler(handler)) } pub fn verifier(self, verifier: Verifier) -> Self { Self(self.0.verifier(verifier)) } pub fn version(self, version: Version) -> Self { Self(self.0.version(version)) } } impl UnixSocketServerBuilder where T: ServerHandler + Sync + 'static, T::Request: DeserializeOwned + Send + Sync + 'static, T::Response: Serialize + Send + 'static, { pub async fn start

(self, path: P) -> io::Result where P: AsRef + Send, { let path = path.as_ref(); let listener = UnixSocketListener::bind(path).await?; let path = listener.path().to_path_buf(); let inner = self.0.start(listener)?; Ok(UnixSocketServerRef { path, inner }) } } #[cfg(test)] mod tests { use async_trait::async_trait; use distant_core_auth::DummyAuthHandler; use tempfile::NamedTempFile; use test_log::test; use super::*; use crate::client::Client; use crate::common::Request; use crate::server::RequestCtx; pub struct TestServerHandler; #[async_trait] impl ServerHandler for TestServerHandler { type Request = String; type Response = String; async fn on_request(&self, ctx: RequestCtx) { // Echo back what we received ctx.reply.send(ctx.request.payload.to_string()).unwrap(); } } #[test(tokio::test)] async fn should_invoke_handler_upon_receiving_a_request() { // Generate a socket path and delete the file after so there is nothing there let path = NamedTempFile::new() .expect("Failed to create socket file") .path() .to_path_buf(); let server = UnixSocketServerBuilder::default() .handler(TestServerHandler) .verifier(Verifier::none()) .start(path) .await .expect("Failed to start Unix socket server"); let mut client: Client = Client::unix_socket(server.path()) .auth_handler(DummyAuthHandler) .connect() .await .expect("Client failed to connect"); let response = client .send(Request::new("hello".to_string())) .await .expect("Failed to send message"); assert_eq!(response.payload, "hello"); } }