From ecb32b205c76430ebe56259a1b502477bfce1983 Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 16 Mar 2021 22:02:31 +0200 Subject: [PATCH] Rewrite URL handling + add example --- .gitignore | 4 +- Cargo.lock | 1 + Cargo.toml | 1 + data/pages/example | 6 - example/Cargo.lock | 480 +++++++++++++++++++++++++++++++++++++++++++ example/Cargo.toml | 9 + example/identity.pfx | Bin 0 -> 4181 bytes example/src/main.rs | 12 ++ mkidentity.sh | 15 -- src/lib.rs | 6 + src/main.rs | 121 ----------- src/proto.rs | 49 +++++ src/server.rs | 123 +++++++++++ 13 files changed, 682 insertions(+), 145 deletions(-) delete mode 100644 data/pages/example create mode 100644 example/Cargo.lock create mode 100644 example/Cargo.toml create mode 100644 example/identity.pfx create mode 100644 example/src/main.rs delete mode 100755 mkidentity.sh create mode 100644 src/lib.rs delete mode 100644 src/main.rs create mode 100644 src/proto.rs create mode 100644 src/server.rs diff --git a/.gitignore b/.gitignore index 652a9f0..eb5a316 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1 @@ -/target -/data/*.pem -/data/*.pfx +target diff --git a/Cargo.lock b/Cargo.lock index d9d0561..fba911a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,6 +4,7 @@ name = "algem" version = "0.1.0" dependencies = [ + "log", "native-tls", "url", ] diff --git a/Cargo.toml b/Cargo.toml index c87b177..b566dbe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,4 @@ edition = "2018" [dependencies] native-tls = "*" url = "*" +log = "*" diff --git a/data/pages/example b/data/pages/example deleted file mode 100644 index 02046b4..0000000 --- a/data/pages/example +++ /dev/null @@ -1,6 +0,0 @@ -Hello - -=> gemini://gemini.circumlunar.space Gemini Project -=> /index This page -=> /other/page Other page -=> relative Relative page diff --git a/example/Cargo.lock b/example/Cargo.lock new file mode 100644 index 0000000..59231d7 --- /dev/null +++ b/example/Cargo.lock @@ -0,0 +1,480 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +dependencies = [ + "memchr", +] + +[[package]] +name = "algem" +version = "0.1.0" +dependencies = [ + "log", + "native-tls", + "url", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "cc" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "core-foundation" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" + +[[package]] +name = "env_logger" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "example" +version = "0.1.0" +dependencies = [ + "algem", + "env_logger", +] + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding", +] + +[[package]] +name = "getrandom" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hermit-abi" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +dependencies = [ + "libc", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "idna" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "538c092e5586f4cdd7dd8078c4a79220e3e168880218124dcbce860f0ea938c6" + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" + +[[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + +[[package]] +name = "native-tls" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "once_cell" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" + +[[package]] +name = "openssl" +version = "0.10.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a61075b62a23fef5a29815de7536d940aa35ce96d18ce0cc5076272db678a577" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-sys", +] + +[[package]] +name = "openssl-probe" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" + +[[package]] +name = "openssl-sys" +version = "0.9.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "313752393519e876837e09e1fa183ddef0be7735868dced3196f4472d536277f" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "pkg-config" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" + +[[package]] +name = "rand" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "schannel" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +dependencies = [ + "lazy_static", + "winapi", +] + +[[package]] +name = "security-framework" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d493c5f39e02dfb062cd8f33301f90f9b13b650e8c1b1d0fd75c19dd64bff69d" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee48cdde5ed250b0d3252818f646e174ab414036edb884dde62d80a3ac6082d" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +dependencies = [ + "cfg-if", + "libc", + "rand", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "tinyvec" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +dependencies = [ + "matches", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b" +dependencies = [ + "form_urlencoded", + "idna", + "matches", + "percent-encoding", +] + +[[package]] +name = "vcpkg" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/example/Cargo.toml b/example/Cargo.toml new file mode 100644 index 0000000..ec6cc97 --- /dev/null +++ b/example/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "example" +version = "0.1.0" +authors = ["Mark "] +edition = "2018" + +[dependencies] +algem = { path = "../" } +env_logger = "*" diff --git a/example/identity.pfx b/example/identity.pfx new file mode 100644 index 0000000000000000000000000000000000000000..36ceaa54f786ad9357cd5a00efb9b0cd6d23c606 GIT binary patch literal 4181 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 VrhYR4B(xNbg%+FKZT|D6{Riqu+&cgO literal 0 HcmV?d00001 diff --git a/example/src/main.rs b/example/src/main.rs new file mode 100644 index 0000000..2bbeac1 --- /dev/null +++ b/example/src/main.rs @@ -0,0 +1,12 @@ +use algem::{server, ServerConfig}; + +fn main() { + let config = ServerConfig { + bind_address: "0.0.0.0:1965".to_string(), + identity_file: "identity.pfx".to_string(), + thread_count: 4 + }; + env_logger::init(); + + server::run(&config); +} diff --git a/mkidentity.sh b/mkidentity.sh deleted file mode 100755 index 6651cdf..0000000 --- a/mkidentity.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -openssl req \ - -x509 \ - -nodes \ - -newkey rsa:4096 \ - -keyout data/key.pem \ - -out data/cert.pem \ - -days 365 - -openssl pkcs12 \ - -export \ - -out data/identity.pfx \ - -inkey data/key.pem \ - -in data/cert.pem diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..b9e13c3 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,6 @@ +pub mod proto; +pub mod server; +mod pool; + +pub use proto::*; +pub use server::ServerConfig; diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index 8851eda..0000000 --- a/src/main.rs +++ /dev/null @@ -1,121 +0,0 @@ -use native_tls::{Identity, TlsAcceptor}; -use std::fs::File; -use std::io::{self, Read, Write}; -use std::net::TcpListener; -use std::path::Path; -use url::Url; - -mod pool; -use pool::ThreadPool; - -fn read_line(s: &mut String, stream: &mut T) -> Result<(), io::Error> { - let mut byte = [0; 1]; - s.clear(); - loop { - stream.read_exact(&mut byte)?; - if byte[0] == b'\r' { - continue; - } - if byte[0] == b'\n' { - break; - } - s.push(byte[0] as char); - } - Ok(()) -} - -enum ResponseError { - // TODO handle malformed URLs - // TODO handle malformed paths - FileError(String, io::Error), - SocketError(io::Error), -} - -fn handle_stream(stream: &mut S) -> Result { - let mut line = String::new(); - read_line(&mut line, stream).map_err(|e| ResponseError::SocketError(e))?; - let url = Url::parse(&line).unwrap(); - let path = String::from("data/pages/") + url.path(); - let path = Path::new(&path); - - match File::open(path) { - Ok(mut file) => { - let mut buf = [0; 4096]; - // TODO ability to serve different kinds of objects? - stream - .write_all(b"20 text/gemini; charset=utf8\r\n") - .map_err(|e| ResponseError::SocketError(e))?; - - loop { - let count = file - .read(&mut buf) - .map_err(|e| ResponseError::FileError(path.to_str().unwrap().to_string(), e))?; - if count == 0 { - break; - } - stream - .write(&buf[0..count]) - .map_err(|e| ResponseError::SocketError(e))?; - } - - Ok(line) - } - Err(err) => { - // TODO better errors - stream - .write_fmt(format_args!("40 {:?}\r\n", err)) - .map_err(|e| ResponseError::SocketError(e))?; - Err(ResponseError::FileError(path.to_str().unwrap().to_string(), err)) - } - } -} - -fn main() { - let mut der = vec![]; - let mut file = File::open("data/identity.pfx").unwrap(); - file.read_to_end(&mut der).unwrap(); - let identity = Identity::from_pkcs12(&der, "").unwrap(); - - let pool = ThreadPool::new(4); - - let listener = TcpListener::bind("0.0.0.0:1965").unwrap(); - let acceptor = TlsAcceptor::new(identity).unwrap(); - - for stream in listener.incoming() { - match stream { - Ok(stream) => { - let peer = stream.peer_addr().unwrap(); - let mut stream = match acceptor.accept(stream) { - Ok(r) => r, - Err(e) => { - eprintln!("TLS handshake failed: {}", e); - continue; - } - }; - - pool.execute(move || { - eprint!("{} ", peer.ip()); - match handle_stream(&mut stream) { - Err(err) => { - match err { - ResponseError::FileError(path, err) => { - eprintln!("ERR {}: {:?}", path, err); - }, - ResponseError::SocketError(err) => { - eprintln!("ERR SOCK {:?}", err); - }, - } - }, - Ok(req) => { - println!(" OK {}", req); - } - } - }); - } - Err(e) => { - eprintln!("accept() failed: {}", e); - break; - } - } - } -} diff --git a/src/proto.rs b/src/proto.rs new file mode 100644 index 0000000..e36ab54 --- /dev/null +++ b/src/proto.rs @@ -0,0 +1,49 @@ +use std::fmt; + +pub enum ResponseBody { + File(String, String), + GeminiText(String) +} + +#[derive(Clone)] +pub enum ErrorCode { + Input = 10, + SensitiveInput = 11, + RedirectTemporary = 30, + RedirectPermanent = 31, + TemporaryFailure = 40, + ServerUnavailable = 41, + CgiError = 42, + ProxyError = 43, + SlowDown = 44, + PermanentFailure = 50, + NotFound = 51, + Gone = 52, + ProxyRequestRefused = 53, + BadRequest = 59, + // TODO certificate something +} + +pub struct Error { + code: ErrorCode, + meta: Option +} + +impl Error { + pub fn new(code: ErrorCode, meta: Option<&str>) -> Error { + Error { + code, + meta: meta.map(str::to_string) + } + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.code.clone() as u32)?; + if let Some(meta) = self.meta.as_ref() { + write!(f, " {}", meta)?; + } + Ok(()) + } +} diff --git a/src/server.rs b/src/server.rs new file mode 100644 index 0000000..e405355 --- /dev/null +++ b/src/server.rs @@ -0,0 +1,123 @@ +use native_tls::{Identity, TlsAcceptor}; +use std::fs::File; +use std::io::{self, Read, Write}; +use std::net::{SocketAddr, TcpListener}; +use url::Url; + +use log::{warn, info, error}; +use crate::proto::{self, ErrorCode, ResponseBody}; +use crate::pool::ThreadPool; + +pub struct ServerConfig { + pub thread_count: usize, + pub identity_file: String, + pub bind_address: String, +} + +fn read_line(s: &mut String, stream: &mut T) -> Result<(), io::Error> { + let mut byte = [0; 1]; + s.clear(); + loop { + stream.read_exact(&mut byte)?; + if byte[0] == b'\r' { + continue; + } + if byte[0] == b'\n' { + break; + } + s.push(byte[0] as char); + } + Ok(()) +} + +fn read_request(stream: &mut impl Read) -> Result { + let mut line = String::new(); + if read_line(&mut line, stream).is_err() { + return Err(proto::Error::new( + ErrorCode::BadRequest, + Some("Bad Request") + )); + } + match Url::parse(&line) { + Ok(url) => Ok(url), + Err(_) => Err(proto::Error::new( + ErrorCode::BadRequest, + Some("Malformed URL"), + )), + } +} + +fn send_response_body(stream: &mut impl Write, response: ResponseBody) -> Result<(), io::Error> { + match response { + ResponseBody::GeminiText(data) => { + write!(stream, "20 text/gemini; charset=utf8\r\n{}", data) + }, + ResponseBody::File(_, _) => todo!() + } +} + +fn handle_request(_peer: SocketAddr, url: Url) -> Result { + // TODO url logic + if url.path() == "/ping" { + return Ok(ResponseBody::GeminiText("pong".to_string())); + } + Err(proto::Error::new(ErrorCode::NotFound, Some(url.path()))) +} + +fn handle_stream(peer: SocketAddr, stream: &mut S) { + let url = match read_request(stream) { + // TODO fix duplicate code here? + Ok(url) => url, + Err(err) => { + let _ = writeln!(stream, "{}\r\n", err); + error!("{} {}", peer, err); + return; + } + }; + match handle_request(peer, url.clone()) { + Ok(response) => { + let _ = send_response_body(stream, response); + info!("{} {} 20", peer, url); + }, + Err(err) => { + let _ = writeln!(stream, "{}\r\n", err); + error!("{} {} {}", peer, url, err); + } + }; +} + +// TODO Result +pub fn run(config: &ServerConfig) { + info!("Listening to gemini requests on {}", &config.bind_address); + let mut der = vec![]; + let mut file = File::open(&config.identity_file).unwrap(); + file.read_to_end(&mut der).unwrap(); + let identity = Identity::from_pkcs12(&der, "").unwrap(); + + let listener = TcpListener::bind(&config.bind_address).unwrap(); + let acceptor = TlsAcceptor::new(identity).unwrap(); + let pool = ThreadPool::new(config.thread_count); + + for stream in listener.incoming() { + match stream { + Ok(stream) => { + let peer = stream.peer_addr().unwrap(); + let mut stream = match acceptor.accept(stream) { + Ok(r) => r, + Err(e) => { + warn!("TLS handshake failed: {}", e); + continue; + } + }; + + pool.execute(move || { + handle_stream(peer, &mut stream); + }); + } + Err(e) => { + error!("accept() failed: {}", e); + break; + } + } + } +}