use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; use std::net::{SocketAddr, TcpListener}; use std::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, gem_root: PathBuf, addrs: Vec, } impl ServerConfig { pub fn new() -> ServerConfig { ServerConfig { default_host: Url::parse("gemini://localhost").unwrap(), gem_root: PathBuf::from(""), addrs: Vec::new(), } } pub fn set_default_host(&mut self, default_host: String) { let mut url = Url::parse("gemini://default").unwrap(); match url.set_host(Some(default_host.as_str())) { Ok(_) => {} Err(e) => panic!(e), }; self.default_host = url; } pub fn set_gem_root(&mut self, gem_root: String) { self.gem_root = PathBuf::from(gem_root); } pub fn add_addr(&mut self, addr: String) { self.addrs.push(match addr.parse() { Ok(addr) => addr, Err(e) => panic!(e), }); } } pub struct Server { acceptor: std::sync::Arc, config: ServerConfig, } impl Server { pub fn new(config: &ServerConfig) -> Server { Server { acceptor: Server::build_acceptor(), config: config.clone(), } } 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()); } 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(); handler::handle_request(&config, stream); }); } Err(_) => { /* connection failed */ } } } } }