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.
107 lines
2.0 KiB
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(())
|
|
}
|