use super::service::AsyncService;
use crate::r#async::Messages;
use crate::shared::protocol::client_hello;
use crate::Result;
use std::sync::Arc;
use tokio::net::TcpListener;
use tokio_rustls::rustls::ServerConfig;
use tokio_rustls::TlsAcceptor;
const DEFAULT_PORT: u16 = 1122;
#[derive(Debug, Clone)]
pub struct AsyncServer<ServiceT: AsyncService> {
service: ServiceT,
config: ServerConfig,
}
impl<ServiceT: AsyncService> AsyncServer<ServiceT>
where
ServiceT: Send + Sync + 'static,
{
pub fn new(service: ServiceT, config: ServerConfig) -> Self {
Self {
service,
config,
}
}
pub async fn serve(self) -> Result<()> {
self.serve_port(DEFAULT_PORT).await
}
pub async fn serve_port(self, port: u16) -> Result<()> {
let listener = TcpListener::bind(format!("[::]:{}", port)).await?;
let tls_acceptor = TlsAcceptor::from(Arc::new(self.config.clone()));
let service_fullname = std::any::type_name::<ServiceT>();
let service_name = service_fullname
.split("::")
.last()
.unwrap_or(service_fullname);
println!(
"Graphical Shell server running {} is listening on {}",
service_name,
listener.local_addr()?
);
loop {
let (stream, addr) = listener.accept().await?;
let tls_acceptor = tls_acceptor.clone();
let service = self.service.clone();
tokio::spawn(async move {
let tls_stream = tls_acceptor.accept(stream).await.unwrap();
let messages = Messages::new(tls_stream);
if let Err(e) = Self::handle_client(service, messages, addr).await {
log::error!("Service error {}: {}", addr, e);
}
println!("- Client disconnected from {}", addr);
});
}
}
async fn handle_client(service: ServiceT, mut messages: Messages, addr: std::net::SocketAddr) -> Result<()> {
let client = crate::shared::r#async::handshake_server(
&mut messages,
&[crate::shared::PROTOCOL_VERSION],
service.server_hello(),
service.auth_verifier(),
)
.await?;
let os: client_hello::Os = client.os.try_into().unwrap_or(client_hello::Os::Unknown);
let monitors = client.monitors.len();
log::info!(
"+ Client connected running {:?} {} with {} monitor(s) on {}",
os,
client.os_version,
monitors,
addr.port()
);
service.main(messages).await?;
Ok(())
}
}