summaryrefslogtreecommitdiff
path: root/src/server/mod.rs
blob: 696a3a5387bfa63bc304d77d3ebb9b35963bc5ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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<SocketAddr>,
}

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<SslAcceptor>,
    config: ServerConfig,
}

impl Server {
    pub fn new(config: &ServerConfig) -> Server {
        Server {
            acceptor: Server::build_acceptor(),
            config: config.clone(),
        }
    }

    fn build_acceptor() -> std::sync::Arc<SslAcceptor> {
        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 */ }
            }
        }
    }
}