use crate::{http::HttpServer, virtual_host::VirtualHostImpl};
use compio::signal::ctrl_c;
use log::{error, info};
use std::{collections::HashMap, sync::Arc};
use vetis::{
errors::{ListenerError, StartError, VetisError, VirtualHostError},
server::{Server, ServerConfig},
virtual_host::{VirtualHost, VirtualHostConfig},
VetisResult, VetisRwLock, VetisServer, VetisVirtualHosts,
};
#[derive(Default)]
pub struct Vetis {
config: ServerConfig,
virtual_hosts: VetisVirtualHosts<VirtualHostImpl>,
instance: Option<HttpServer>,
}
impl Vetis {
pub fn new(config: ServerConfig) -> Vetis {
Vetis { config, virtual_hosts: Arc::new(VetisRwLock::new(HashMap::new())), instance: None }
}
}
impl VetisServer for Vetis {
type VirtualHost = VirtualHostImpl;
type VirtualHostConfig = VirtualHostConfig;
async fn add_virtual_host(&mut self, virtual_host: Self::VirtualHost) {
let key = (Arc::from(virtual_host.hostname()), virtual_host.port());
self.virtual_hosts
.write()
.await
.insert(key, virtual_host);
}
async fn remove_virtual_host(&mut self, hostname: &str, port: u16) {
let key = (Arc::from(hostname), port);
self.virtual_hosts
.write()
.await
.remove(&key);
}
fn virtual_hosts(&self) -> &VetisVirtualHosts<Self::VirtualHost> {
&self.virtual_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
.instance
.is_some()
{
error!("Server is already running");
return Err(VetisError::Start(StartError::AlreadyRunning));
}
if self
.config
.listeners()
.is_empty()
{
error!("You must add at least one listener");
return Err(VetisError::Listener(ListenerError::NoListeners));
}
if self
.virtual_hosts
.read()
.await
.is_empty()
{
error!("You must add at least one virtual host");
return Err(VetisError::VirtualHost(VirtualHostError::NoVirtualHosts));
}
let mut server = HttpServer::new(self.config.clone());
server.set_virtual_hosts(
self.virtual_hosts
.clone(),
);
server
.start()
.await?;
self.instance = Some(server);
Ok(())
}
async fn stop(&mut self) -> VetisResult<()> {
if let Some(instance) = &mut self.instance {
instance
.stop()
.await?;
} else {
return Err(VetisError::NoInstances);
}
Ok(())
}
async fn reload(
&mut self,
new_config: ServerConfig,
_new_virtual_hosts: Vec<Self::VirtualHostConfig>,
) -> VetisResult<()> {
if self.config() != &new_config {
self.config = new_config;
self.stop().await?;
self.start().await?;
}
Ok(())
}
}