diff --git a/Cargo.lock b/Cargo.lock index 94689e8..3a623e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -149,15 +149,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445" +checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" [[package]] name = "futures-macro" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89f17b21645bc4ed773c69af9c9a0effd4a3f1a3876eadd453469f8854e7fdd" +checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" dependencies = [ "proc-macro2", "quote", @@ -166,15 +166,15 @@ dependencies = [ [[package]] name = "futures-task" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dabf1872aaab32c886832f2276d2f5399887e2bd613698a02359e4ea83f8de12" +checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" [[package]] name = "futures-util" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e" +checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" dependencies = [ "futures-core", "futures-macro", @@ -272,9 +272,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.109" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98a04dce437184842841303488f70d0188c5f51437d2a834dc097eafa909a01" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" [[package]] name = "lock_api" @@ -404,9 +404,9 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ "hermit-abi", "libc", @@ -423,9 +423,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" [[package]] name = "opaque-debug" @@ -478,9 +478,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "proc-macro2" -version = "1.0.32" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" +checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1" dependencies = [ "unicode-xid", ] @@ -566,15 +566,15 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.130" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008" [[package]] name = "serde_derive" -version = "1.0.130" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276" dependencies = [ "proc-macro2", "quote", @@ -605,9 +605,9 @@ dependencies = [ [[package]] name = "simple_logger" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "205596cf77a15774e5601c5ef759f4211ac381c0855a1f1d5e24a46f60f93e9a" +checksum = "45b60258a35dc3cb8a16890b8fd6723349bfa458d7960e25e633f1b1c19d7b5e" dependencies = [ "atty", "colored", @@ -636,9 +636,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "syn" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +checksum = "23a1dfb999630e338648c83e91c59a4e9fb7620f520c3194b6b89e276f2f1959" dependencies = [ "proc-macro2", "quote", @@ -699,11 +699,10 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e992e41e0d2fb9f755b37446f20900f64446ef54874f40a60c78f021ac6144" +checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" dependencies = [ - "autocfg", "bytes", "libc", "memchr", @@ -719,9 +718,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9efc1aba077437943f7515666aa2b882dfabfbfdf89c819ea75a8d6e9eaba5e" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2", "quote", @@ -730,9 +729,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.23.1" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4baa378e417d780beff82bf54ceb0d195193ea6a00c14e22359e7f39456b5689" +checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" dependencies = [ "rustls", "tokio", diff --git a/Cargo.toml b/Cargo.toml index f4d27da..3a05058 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,22 +14,22 @@ license = "MIT" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -tokio = { version = "1.14", features = [ "full" ] } +tokio = { version = "1.15", features = [ "full" ] } rustls-pemfile = "0.2.1" -futures-util = "0.3.18" +futures-util = "0.3.19" toml = "0.5.8" -serde = "1.0.130" -serde_derive = "1.0.130" +serde = "1.0.132" +serde_derive = "1.0.132" url = "2.2.2" new_mime_guess = "3.0.2" mime = "0.3.16" log = "0.4.14" -simple_logger = "1.15" +simple_logger = "1.16" sha2 = "0.9.8" x509-parser = "0.12" [dependencies.tokio-rustls] -version = "0.23.1" +version = "0.23.2" optional = false features = ["dangerous_configuration"] diff --git a/src/con_handler.rs b/src/con_handler.rs index cb2e60c..a0f1cd8 100644 --- a/src/con_handler.rs +++ b/src/con_handler.rs @@ -41,7 +41,6 @@ async fn get_binary(mut con: conn::Connection, path: PathBuf, meta: String) -> i let len = { let buf = reader.fill_buf().await?; con.send_raw(buf).await?; - tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; buf.len() }; if len == 0 { @@ -57,12 +56,7 @@ async fn get_binary(mut con: conn::Connection, path: PathBuf, meta: String) -> i Ok(()) } -async fn get_content(path: PathBuf, u: &url::Url) -> Result { - let meta = tokio::fs::metadata(&path).await?; - if meta.is_file() { - return Ok(tokio::fs::read_to_string(path).await?); - } - +async fn gen_dir_list(path: PathBuf, u: &url::Url) -> Result { let mut dirs: Vec = Vec::new(); let mut files: Vec = Vec::new(); @@ -201,12 +195,13 @@ pub async fn handle_connection(mut con: conn::Connection, url: url::Url) -> Resu #[cfg(feature = "proxy")] match &con.srv.server.proxy { - Some(pr) => match url.path_segments().map(|c| c.collect::>()) { - Some(s) => if let Some(p) = pr.get(s[0]) { + Some(pr) => { + if let Some(s) = url.path_segments().map(|c| c.collect::>()) { + if let Some(p) = pr.get(s[0]) { revproxy::proxy(p.to_string(), url, con).await?; return Ok(()); - }, - None => {} + } + } }, None => {} } @@ -313,18 +308,35 @@ pub async fn handle_connection(mut con: conn::Connection, url: url::Url) -> Resu } let mut mime = get_mime(&path); - if mime == "text/gemini" && con.srv.server.lang.is_some() { - mime += &("; lang=".to_string() + &con.srv.server.lang.to_owned().unwrap()); - } - if !mime.starts_with("text/") { - logger::logger(con.peer_addr, Status::Success, url.as_str()); - get_binary(con, path, mime).await?; - return Ok(()); - } - let content = get_content(path, &url).await?; - con.send_body(Status::Success, Some(&mime), Some(content)) + if meta.is_file() { + if mime == "text/gemini" && con.srv.server.lang.is_some() { + mime += &("; lang=".to_string() + &con.srv.server.lang.to_owned().unwrap()); + } + if !mime.starts_with("text/") { + logger::logger(con.peer_addr, Status::Success, url.as_str()); + get_binary(con, path, mime).await?; + return Ok(()); + } + match fs::read_to_string(path).await { + Ok(c) => { + con.send_body(Status::Success, Some(&mime), Some(c)) + .await?; + logger::logger(con.peer_addr, Status::Success, url.as_str()); + } + Err(e) => { + println!("{}", e); + con.send_status(Status::NotFound, None) + .await?; + logger::logger(con.peer_addr, Status::NotFound, url.as_str()); + } + } + + } else { + let dir = gen_dir_list(path, &url).await?; + con.send_body(Status::Success, Some(&mime), Some(dir)) .await?; - logger::logger(con.peer_addr, Status::Success, url.as_str()); + logger::logger(con.peer_addr, Status::Success, url.as_str()); + } Ok(()) } diff --git a/src/config.rs b/src/config.rs index 3ccb1ad..c06aa5c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -4,7 +4,10 @@ use crate::lib::errors; use std::collections::HashMap; use std::env; use std::path; +use std::net; +use std::net::ToSocketAddrs; use tokio::fs; +use tokio::io; type Result = std::result::Result>; @@ -12,7 +15,7 @@ type Result = std::result::Result, pub host: Option, - pub interface: Option>, + pub interface: Option>, pub log: Option, pub server: Vec, } @@ -65,7 +68,7 @@ impl Config { } let fd = fs::read_to_string(p).await.unwrap(); - let config: Config = match toml::from_str(&fd) { + let mut config: Config = match toml::from_str(&fd) { Ok(c) => c, Err(e) => return Err(Box::new(e)), }; @@ -86,8 +89,18 @@ impl Config { "You need to specify either host/port or interface".into(), ))); } else if config.host.is_some() && config.port.is_some() { + let mut addr: Vec = Vec::new(); + addr.push( + format!("{}:{}", &config.host.to_owned().unwrap(), &config.port.unwrap()) + .to_socket_addrs()? + .next() + .ok_or_else(|| io::Error::from(io::ErrorKind::AddrNotAvailable))?, + ); + config.interface = Some(addr); return Ok(config); - } else if config.interface.is_some() { + } else if let Some(ref mut i) = config.interface { + i.sort_by(|a, b| a.port().cmp(&b.port())); + i.dedup(); return Ok(config); } Err(Box::new(errors::GemError( diff --git a/src/lib/server.rs b/src/lib/server.rs index 00a3121..29545b3 100644 --- a/src/lib/server.rs +++ b/src/lib/server.rs @@ -4,7 +4,6 @@ use tokio::net::TcpListener; use tokio_rustls::server::TlsStream; use tokio_rustls::TlsAcceptor; -//use futures_util::future::TryFutureExt; use std::collections::HashMap; use std::future::Future; use std::io; @@ -71,12 +70,10 @@ impl Server { pub async fn serve( self, cmap: HashMap, - default: String, handler: impl Handler + 'static + Copy, ) -> Result { for listen in self.listener { let cmap = cmap.clone(); - let default = default.clone(); let listen = Arc::new(listen); let acceptor = Arc::new(self.acceptor.clone()); @@ -86,8 +83,7 @@ impl Server { let local_addr = stream.local_addr().unwrap(); let acceptor = acceptor.clone(); let cmap = cmap.clone(); - let default = default.clone(); - let mut handler = handler.clone(); + let mut handler = handler; tokio::spawn(async move { let mut stream = match acceptor.accept(stream).await { @@ -105,7 +101,7 @@ impl Server { let srv = match cmap.get(sni) { Some(h) => h, - None => cmap.get(&default).unwrap(), + None => return Ok(()) as io::Result<()>, } .to_owned(); @@ -138,7 +134,7 @@ impl Server { } } -pub async fn get_request(mut con: conn::Connection) -> Result<(conn::Connection, url::Url)> { +async fn get_request(mut con: conn::Connection) -> Result<(conn::Connection, url::Url)> { let mut buffer = [0; 1024]; let len = match tokio::time::timeout( tokio::time::Duration::from_secs(5), diff --git a/src/lib/status.rs b/src/lib/status.rs index 3a8a03c..43d888b 100644 --- a/src/lib/status.rs +++ b/src/lib/status.rs @@ -28,7 +28,7 @@ pub enum Status { } impl Status { - pub fn to_str(&self) -> &str { + pub fn to_str(self) -> &'static str { match self { Status::Input => "Input", Status::Success => "Success", diff --git a/src/main.rs b/src/main.rs index ece75c0..92b1582 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,6 @@ #[macro_use] extern crate serde_derive; -use std::io; -use std::net::ToSocketAddrs; - #[cfg(any(feature = "cgi", feature = "scgi"))] mod cgi; mod con_handler; @@ -33,40 +30,17 @@ async fn main() -> errors::Result { logger::init(&cfg.log)?; let cmap = cfg.to_map(); - let default = &cfg.server[0].hostname; println!("Serving {} vhosts", cfg.server.len()); let mut addr: Vec = Vec::new(); - if cfg.host.is_some() && cfg.port.is_some() { - addr.push( - format!("{}:{}", &cfg.host.to_owned().unwrap(), &cfg.port.unwrap()) - .to_socket_addrs()? - .next() - .ok_or_else(|| io::Error::from(io::ErrorKind::AddrNotAvailable))?, - ); - } else { - match &cfg.interface { - Some(i) => { - for iface in i { - addr.push( - iface - .to_socket_addrs()? - .next() - .ok_or_else(|| io::Error::from(io::ErrorKind::AddrNotAvailable))?, - ); - } - } - None => {} - } + if let Some(i) = &cfg.interface { + addr.append(&mut i.to_owned()); } - addr.sort_by(|a, b| a.port().cmp(&b.port())); - addr.dedup(); - let server = server::Server::bind(addr, tls_acceptor_conf, cfg.clone()).await?; + let server = server::Server::bind(addr, tls_acceptor_conf, cfg).await?; if let Err(e) = server .serve( cmap, - default.to_string(), server::force_boxed(con_handler::handle_connection), ) .await