1use ipnet::IpNet;
2use quinn::Connection;
3use std::time::Duration;
4use tokio::time::timeout;
5
6use quincy::{
7 auth::{
8 stream::{AuthMessage, AuthStreamBuilder, AuthStreamMode},
9 ServerAuthenticator,
10 },
11 error::AuthError,
12 Result,
13};
14
15pub struct AuthServer {
17 authenticator: Box<dyn ServerAuthenticator>,
18 server_address: IpNet,
19 auth_timeout: Duration,
20}
21
22impl AuthServer {
23 pub fn new(
25 authenticator: Box<dyn ServerAuthenticator>,
26 server_address: IpNet,
27 auth_timeout: Duration,
28 ) -> Self {
29 Self {
30 authenticator,
31 server_address,
32 auth_timeout,
33 }
34 }
35
36 pub async fn handle_authentication(&self, connection: &Connection) -> Result<(String, IpNet)> {
51 let auth_stream_builder = AuthStreamBuilder::new(AuthStreamMode::Server);
52 let mut auth_stream = auth_stream_builder
53 .connect(connection, self.auth_timeout)
54 .await?;
55
56 let message = timeout(self.auth_timeout, auth_stream.recv_message())
57 .await
58 .map_err(|_| AuthError::Timeout)??;
59
60 let auth_result = match message {
61 AuthMessage::Authenticate { payload } => {
62 let (username, client_address) =
63 self.authenticator.authenticate_user(payload).await?;
64
65 auth_stream
66 .send_message(AuthMessage::Authenticated {
67 client_address,
68 server_address: self.server_address,
69 })
70 .await?;
71
72 (username, client_address)
73 }
74 _ => {
75 let _ = auth_stream.send_message(AuthMessage::Failed).await;
77 return Err(AuthError::InvalidPayload.into());
78 }
79 };
80
81 auth_stream.close()?;
82
83 Ok(auth_result)
84 }
85}