You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
yuurei/src/web/mod.rs

107 lines
2.0 KiB

//! Handle web serving and managing state of web clients
use super::*;
use std::{
sync::Arc,
};
use hyper::{
service::{
make_service_fn,
service_fn,
},
server::{
Server,
conn::AddrStream,
},
Request,
Response,
Body,
};
use futures::{
TryStreamExt as _,
};
use cidr::{
Cidr,
};
pub mod error;
pub mod route;
#[derive(Debug)]
pub struct State
{
config: config::Config,
}
impl State
{
pub fn new(config: config::Config) -> Self
{
Self{
config
}
}
}
impl Default for State
{
#[inline]
fn default() -> Self
{
Self{config: config::get().clone()}
}
}
fn mask_contains(mask: &[cidr::IpCidr], value: &std::net::IpAddr) -> bool
{
for mask in mask.iter()
{
if mask.contains(value) {
return true;
}
}
false
}
async fn handle_conn(state: Arc<State>, req: Request<Body>) -> Result<Response<Body>, error::Error>
{
//TODO: Create client, route, and such
Ok(Response::new("Hi".into()))
}
pub async fn serve(state: State) -> Result<(), eyre::Report>
{
let state = Arc::new(state);
let service = make_service_fn(|conn: &AddrStream| {
let state = Arc::clone(&state);
let remote_addr = conn.remote_addr();
let remote_ip = remote_addr.ip();
let denied = mask_contains(&state.config.deny_mask[..], &remote_ip);
let allowed = mask_contains(&state.config.accept_mask[..], &remote_ip);
async move {
if denied {
Err(error::Error::Denied(remote_addr, true).warn())
} else if allowed || state.config.accept_default {
trace!("Accepted conn: {}", remote_addr);
Ok(service_fn(move |req: Request<Body>| {
handle_conn(Arc::clone(&state), req)
}))
} else {
Err(error::Error::Denied(remote_addr,false).info())
}
}
});
let server = Server::bind(&state.config.listen).serve(service)
.with_graceful_shutdown(async {
tokio::signal::ctrl_c().await.expect("Failed to catch SIGINT");
info!("Going down for shutdown now!");
});
server.await?;
Ok(())
}