Changed main to only look at the config once instead of per connection
This commit is contained in:
@@ -22,22 +22,42 @@ pub struct Server {
|
|||||||
pub usrdir: Option<bool>,
|
pub usrdir: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ServerCfg {
|
||||||
|
pub hostname: String,
|
||||||
|
pub dir: String,
|
||||||
|
pub key: String,
|
||||||
|
pub cert: String,
|
||||||
|
pub cgi: String,
|
||||||
|
pub usrdir: bool,
|
||||||
|
pub port: i32,
|
||||||
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn new(file: &Path) -> Result<Config, Error> {
|
pub fn new(file: &Path) -> Result<Config, Error> {
|
||||||
let fd = std::fs::read_to_string(file).unwrap();
|
let fd = std::fs::read_to_string(file).unwrap();
|
||||||
let config: Config = toml::from_str(&fd).unwrap();
|
let config: Config = toml::from_str(&fd).unwrap();
|
||||||
return Ok(config);
|
return Ok(config);
|
||||||
}
|
}
|
||||||
pub fn to_map(&self) -> HashMap<String, Server> {
|
pub fn to_map(&self) -> HashMap<String, ServerCfg> {
|
||||||
let mut map = HashMap::new();
|
let mut map = HashMap::new();
|
||||||
for srv in &self.server {
|
for srv in &self.server {
|
||||||
map.insert(srv.hostname.clone(), Server {
|
let cgi = match srv.cgi.to_owned() {
|
||||||
|
Some(c) => c,
|
||||||
|
None => "".to_string(),
|
||||||
|
};
|
||||||
|
let usrdir = match srv.usrdir {
|
||||||
|
Some(u) => u,
|
||||||
|
None => false,
|
||||||
|
};
|
||||||
|
map.insert(srv.hostname.clone(), ServerCfg {
|
||||||
hostname: srv.hostname.clone(),
|
hostname: srv.hostname.clone(),
|
||||||
dir: srv.dir.clone(),
|
dir: srv.dir.clone(),
|
||||||
key: srv.key.clone(),
|
key: srv.key.clone(),
|
||||||
cert: srv.cert.clone(),
|
cert: srv.cert.clone(),
|
||||||
cgi: srv.cgi.clone(),
|
cgi: cgi,
|
||||||
usrdir: srv.usrdir.clone(),
|
usrdir: usrdir,
|
||||||
|
port: self.port.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
map
|
map
|
||||||
|
|||||||
@@ -9,10 +9,6 @@ use crate::status;
|
|||||||
pub struct Connection {
|
pub struct Connection {
|
||||||
pub stream: TlsStream<TcpStream>,
|
pub stream: TlsStream<TcpStream>,
|
||||||
pub peer_addr: SocketAddr,
|
pub peer_addr: SocketAddr,
|
||||||
pub hostname: String,
|
|
||||||
pub dir: String,
|
|
||||||
pub cgi: String,
|
|
||||||
pub usrdir: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Connection {
|
impl Connection {
|
||||||
|
|||||||
66
src/main.rs
66
src/main.rs
@@ -98,7 +98,8 @@ fn get_content(path: PathBuf, u: url::Url) -> Result<String, io::Error> {
|
|||||||
return Ok(list);
|
return Ok(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_connection(mut con: conn::Connection) -> Result<(), io::Error> {
|
// TODO Rewrite this monster.
|
||||||
|
async fn handle_connection(mut con: conn::Connection, srv: &config::ServerCfg) -> Result<(), io::Error> {
|
||||||
let now: DateTime<Utc> = Utc::now();
|
let now: DateTime<Utc> = Utc::now();
|
||||||
println!("{} New Connection: {}", now, con.peer_addr);
|
println!("{} New Connection: {}", now, con.peer_addr);
|
||||||
let mut buffer = [0; 1024];
|
let mut buffer = [0; 1024];
|
||||||
@@ -123,7 +124,7 @@ async fn handle_connection(mut con: conn::Connection) -> Result<(), io::Error> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if Some(con.hostname.as_str()) != url.host_str() {
|
if Some(srv.hostname.as_str()) != url.host_str() {
|
||||||
con.send_status(status::Status::ProxyRequestRefused, "Url doesn't match certificate!").await?;
|
con.send_status(status::Status::ProxyRequestRefused, "Url doesn't match certificate!").await?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -146,7 +147,7 @@ async fn handle_connection(mut con: conn::Connection) -> Result<(), io::Error> {
|
|||||||
|
|
||||||
let mut path = PathBuf::new();
|
let mut path = PathBuf::new();
|
||||||
|
|
||||||
if url.path().starts_with("/~") && con.usrdir == true{
|
if url.path().starts_with("/~") && srv.usrdir == true{
|
||||||
let usr = url.path().trim_start_matches("/~");
|
let usr = url.path().trim_start_matches("/~");
|
||||||
let usr: Vec<&str> = usr.splitn(2, "/").collect();
|
let usr: Vec<&str> = usr.splitn(2, "/").collect();
|
||||||
path.push("/home/");
|
path.push("/home/");
|
||||||
@@ -156,7 +157,7 @@ async fn handle_connection(mut con: conn::Connection) -> Result<(), io::Error> {
|
|||||||
path.push(format!("{}/{}/",usr[0], "public_gemini"));
|
path.push(format!("{}/{}/",usr[0], "public_gemini"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
path.push(&con.dir);
|
path.push(&srv.dir);
|
||||||
if url.path() != "" || url.path() != "/" {
|
if url.path() != "" || url.path() != "/" {
|
||||||
path.push(url.path().trim_start_matches("/"));
|
path.push(url.path().trim_start_matches("/"));
|
||||||
}
|
}
|
||||||
@@ -171,6 +172,8 @@ async fn handle_connection(mut con: conn::Connection) -> Result<(), io::Error> {
|
|||||||
let mut meta = fs::metadata(&path).expect("Unable to read metadata");
|
let mut meta = fs::metadata(&path).expect("Unable to read metadata");
|
||||||
let mut perm = meta.permissions();
|
let mut perm = meta.permissions();
|
||||||
|
|
||||||
|
// TODO fix me
|
||||||
|
// This block is terrible
|
||||||
if meta.is_dir() {
|
if meta.is_dir() {
|
||||||
if !url.path().ends_with("/") {
|
if !url.path().ends_with("/") {
|
||||||
con.send_status(
|
con.send_status(
|
||||||
@@ -184,11 +187,18 @@ async fn handle_connection(mut con: conn::Connection) -> Result<(), io::Error> {
|
|||||||
path.push("index.gemini");
|
path.push("index.gemini");
|
||||||
meta = fs::metadata(&path).expect("Unable to read metadata");
|
meta = fs::metadata(&path).expect("Unable to read metadata");
|
||||||
perm = meta.permissions();
|
perm = meta.permissions();
|
||||||
|
if perm.mode() & 0o0444 != 0o444 {
|
||||||
|
let mut p = path.clone();
|
||||||
|
p.pop();
|
||||||
|
path.push(format!("{}/",p.display()));
|
||||||
|
meta = fs::metadata(&path).expect("Unable to read metadata");
|
||||||
|
perm = meta.permissions();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add timeout
|
// TODO add timeout
|
||||||
if con.cgi.trim_end_matches("/") == path.parent().unwrap().to_str().unwrap() {
|
if srv.cgi.trim_end_matches("/") == path.parent().unwrap().to_str().unwrap() {
|
||||||
if perm.mode() & 0o0111 == 0o0111 {
|
if perm.mode() & 0o0111 == 0o0111 {
|
||||||
cgi::cgi(con, path, url).await?;
|
cgi::cgi(con, path, url).await?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -233,6 +243,7 @@ fn main() -> io::Result<()> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let cfg = config::Config::new(&p)?;
|
let cfg = config::Config::new(&p)?;
|
||||||
|
let cmap = cfg.to_map();
|
||||||
println!("Serving {} vhosts", cfg.server.len());
|
println!("Serving {} vhosts", cfg.server.len());
|
||||||
|
|
||||||
let addr = format!("{}:{}", cfg.host, cfg.port);
|
let addr = format!("{}:{}", cfg.host, cfg.port);
|
||||||
@@ -255,40 +266,31 @@ fn main() -> io::Result<()> {
|
|||||||
loop {
|
loop {
|
||||||
let (stream, peer_addr) = listener.accept().await?;
|
let (stream, peer_addr) = listener.accept().await?;
|
||||||
let acceptor = acceptor.clone();
|
let acceptor = acceptor.clone();
|
||||||
let cfg = cfg.clone();
|
let cmap = cmap.clone();
|
||||||
|
|
||||||
let fut = async move {
|
let fut = async move {
|
||||||
let mut stream = acceptor.accept(stream).await?;
|
let mut stream = acceptor.accept(stream).await?;
|
||||||
let (_, sni) = TlsStream::get_mut(&mut stream);
|
let (_, sni) = TlsStream::get_mut(&mut stream);
|
||||||
let sni = sni.get_sni_hostname();
|
let sni = match sni.get_sni_hostname() {
|
||||||
let mut dir = String::new();
|
Some(s) => s,
|
||||||
let mut cgi = String::new();
|
None => return Ok(()),
|
||||||
let mut hostname = String::new();
|
};
|
||||||
let mut usrdir: bool = false;
|
|
||||||
|
let srv = match cmap.get(sni) {
|
||||||
for server in &cfg.server {
|
Some(h) => h,
|
||||||
if Some(server.hostname.as_str()) == sni {
|
None => {
|
||||||
hostname = sni.unwrap().to_string();
|
// I'm not sure this will actually get called?
|
||||||
dir = server.dir.to_string();
|
stream.write_all(b"59\tNotFound!\r\n").await?;
|
||||||
if server.cgi.is_some() {
|
stream.flush().await?;
|
||||||
cgi = server.cgi.as_ref().unwrap().to_string();
|
return Ok(());
|
||||||
}
|
},
|
||||||
if server.usrdir.is_some() {
|
};
|
||||||
usrdir = server.usrdir.unwrap();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let con = conn::Connection {
|
let con = conn::Connection {
|
||||||
stream,
|
stream,
|
||||||
peer_addr,
|
peer_addr,
|
||||||
hostname,
|
|
||||||
dir,
|
|
||||||
cgi,
|
|
||||||
usrdir,
|
|
||||||
};
|
};
|
||||||
handle_connection(con).await?;
|
handle_connection(con, srv).await?;
|
||||||
|
|
||||||
Ok(()) as io::Result<()>
|
Ok(()) as io::Result<()>
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user