use crate::{host::HostImpl, listener::ServerListener};
use compio::signal::ctrl_c;
#[cfg(any(feature = "http1", feature = "http2"))]
use http::Version;
use log::{error, info};
use std::{collections::HashMap, sync::Arc};
use vetis::{
errors::{HostError, ListenerError, VetisError},
host::{Host, HostConfig},
listener::Listener as _,
server::ServerConfig,
VetisHosts, VetisResult, VetisRwLock, VetisServer,
};
#[derive(Default)]
pub struct Vetis {
config: ServerConfig,
hosts: VetisHosts<HostImpl>,
listeners: Vec<ServerListener>,
}
impl Vetis {
pub fn new(config: ServerConfig) -> Vetis {
Vetis { config, hosts: Arc::new(VetisRwLock::new(HashMap::new())), listeners: Vec::new() }
}
}
impl VetisServer for Vetis {
type Host = HostImpl;
type HostConfig = HostConfig;
async fn add_host(&mut self, host: Self::Host) {
self.hosts
.write()
.await
.insert(Arc::from(host.hostname()), host);
}
async fn remove_host(&mut self, hostname: &str) {
self.hosts
.write()
.await
.remove(&Arc::from(hostname));
}
fn hosts(&self) -> &VetisHosts<Self::Host> {
&self.hosts
}
fn config(&self) -> &ServerConfig {
&self.config
}
async fn run(&mut self) -> VetisResult<()> {
self.start().await?;
for listener in self
.config
.listeners()
{
info!("Server listening on port {}:{}", listener.interface(), listener.port());
}
let _ = ctrl_c().await;
info!("\nStopping server...");
self.stop().await?;
Ok(())
}
async fn start(&mut self) -> VetisResult<()> {
if self
.config
.listeners()
.is_empty()
{
error!("You must add at least one listener");
return Err(VetisError::Listener(ListenerError::NoListeners));
}
if self
.hosts
.read()
.await
.is_empty()
{
error!("You must add at least one virtual host");
return Err(VetisError::Host(HostError::NoHosts));
}
for listener_config in self
.config
.listeners()
{
#[cfg(any(feature = "http1", feature = "http2"))]
if listener_config
.protos()
.iter()
.any(|proto| *proto == Version::HTTP_11 || *proto == Version::HTTP_2)
{
use crate::listener::tcp::TcpListener;
use vetis::listener::Listener as _;
let mut listener: ServerListener = TcpListener::new(listener_config.clone()).into();
listener.set_hosts(self.hosts.clone());
listener
.listen()
.await?;
self.listeners
.push(listener);
}
#[cfg(feature = "http3")]
if listener_config
.protos()
.contains(&Version::HTTP_3)
{
use crate::listener::udp::UdpListener;
use vetis::listener::Listener as _;
let mut listener: ServerListener = UdpListener::new(listener_config.clone()).into();
listener.set_hosts(self.hosts.clone());
listener
.listen()
.await?;
self.listeners
.push(listener);
}
}
Ok(())
}
async fn stop(&mut self) -> VetisResult<()> {
for listener in &mut self.listeners {
listener
.stop()
.await?
}
Ok(())
}
async fn reload(
&mut self,
_new_config: ServerConfig,
_new_hosts: Vec<Self::HostConfig>,
) -> VetisResult<()> {
Ok(())
}
}