use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod, SslStream}; use std::collections::HashMap; use std::net::{SocketAddr, TcpListener, TcpStream}; use std::path::{Path, PathBuf}; use std::sync::Arc; use std::thread; use std::vec::Vec; use url::Url; pub mod handler; pub mod response; #[derive(Clone)] pub struct ServerConfig { default_host: Url, www_root: PathBuf, addrs: Vec, } impl ServerConfig { pub fn new(default_host: String, www_root: String) -> ServerConfig { let mut url = Url::parse("gemini://default").unwrap(); url.set_host(Some(default_host.as_str())); ServerConfig { default_host: url, www_root: PathBuf::from(www_root), addrs: Vec::new(), } } pub fn add_addr(&mut self, addr: String) { self.addrs.push(addr.parse().unwrap()); } } pub struct Server { acceptor: std::sync::Arc, config: ServerConfig, } impl Server { pub fn new(config: &ServerConfig) -> Server { Server { acceptor: build_acceptor(), config: config.clone(), } } pub fn serve(&self) { let listener = TcpListener::bind(&self.config.addrs[..]).unwrap(); for stream in listener.incoming() { match stream { Ok(stream) => { let acceptor = self.acceptor.clone(); let config = self.config.clone(); thread::spawn(move || { let stream = acceptor.accept(stream).unwrap(); handle_client(&config, stream); }); } Err(e) => { /* connection failed */ } } } } } fn handle_client(config: &ServerConfig, mut stream: SslStream) { let mut buffer = [0; 1026]; stream.ssl_read(&mut buffer); let request = String::from_utf8(buffer.to_vec()).unwrap(); let location = match Url::parse(&request) { Ok(url) => url, Err(e) => config.default_host.join(&request).unwrap(), }; handler::handle(config, location, &mut stream); } fn build_acceptor() -> std::sync::Arc { let mut acceptor = SslAcceptor::mozilla_intermediate_v5(SslMethod::tls()).unwrap(); acceptor .set_private_key_file("doc/key.pem", SslFiletype::PEM) .unwrap(); acceptor.set_certificate_chain_file("doc/cert.pem").unwrap(); acceptor.check_private_key().unwrap(); return Arc::new(acceptor.build()); }