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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use std::net::{TcpListener, TcpStream};
use std::thread;
use std::io::{Write};
use std::sync::{Arc};
use crate::handler::Handler;
use crate::headers::Headers;
use crate::http_message::{HttpMessage, read_message_from_wire, MessageError, RequestOptions, Response, write_message_to_wire};
use crate::http_message::Body::{BodyString};

pub struct Server {
    pub port: u16,
    // options: ServerOptions,
}

pub struct ServerOptions {
    pub threadpool_size: usize,
    pub headers_size: usize,
    pub trailers_size: usize,
}

impl Server where {
    pub fn new(port: u16) -> Server {
        Server {
            port,
            // options: options.unwrap_or(ServerOptions {
            //     headers_size: 16384,
            //     trailers_size: 16384,
            //     threadpool_size: 10,
            // })
        }
    }

    pub fn start<F, H>(&mut self, fun: F, close_on_finish: bool)
        where F: Fn() -> Result<H, String> + Send + Sync + 'static, H: Handler {
        let listener = self.listen();
        let handler = Arc::new(fun);

        if close_on_finish {
            thread::spawn(|| {
                Self::handle_tcp_stream(listener, handler)
            });
        } else {
            Self::handle_tcp_stream(listener, handler);
        };
    }

    fn handle_tcp_stream<F, H>(listener: TcpListener, handler: Arc<F>)
        where F: Fn() -> Result<H, String> + Send + Sync + 'static,
              H: Handler {
        for stream in listener.incoming() {
            let h = handler.clone();
            thread::spawn(move || {
                Self::handle_request(h.clone(), stream.unwrap());
            });
        }
    }

    fn handle_request<F, H>(handler: Arc<F>, mut stream: TcpStream)
        where F: Fn() -> Result<H, String> + Send + Sync + 'static, H: Handler {
        let mut reader: &mut [u8] = &mut [0; 4096];
        let mut chunks_writer = Vec::with_capacity(1048576);
        let mut compress_writer = Vec::with_capacity(1048576);
        let mut start_line_writer = Vec::with_capacity(16384);
        let mut headers_writer = Vec::with_capacity(16384);
        let mut trailers_writer = Vec::with_capacity(16384);

        let result = read_message_from_wire(
            stream.try_clone().unwrap(),
            &mut reader,
            &mut start_line_writer,
            &mut headers_writer,
            &mut chunks_writer,
            &mut compress_writer,
            &mut trailers_writer,
        );

        match result {
            Err(MessageError::HeadersTooBig(msg))
            | Err(MessageError::TrailersTooBig(msg))
            | Err(MessageError::InvalidContentLength(msg))
            | Err(MessageError::StartLineTooBig(msg))
            | Err(MessageError::InvalidBoundaryDigit(msg))
            => {
                let response = Response::bad_request(Headers::empty(), BodyString(msg.as_str()));
                write_message_to_wire(&mut stream, HttpMessage::Response(response), RequestOptions::default());
            }
            Err(MessageError::NoContentLengthOrTransferEncoding(msg)) => {
                let response = Response::length_required(Headers::empty(), BodyString(msg.as_str()));
                write_message_to_wire(&mut stream, HttpMessage::Response(response), RequestOptions::default());
            }
            Ok(HttpMessage::Request(request)) => {
                let options = RequestOptions::from(&(request.headers));
                let mut h = handler().unwrap();
                h.handle(request, |response| {
                    write_message_to_wire(&mut stream, HttpMessage::Response(response), options);
                });
            }
            Ok(HttpMessage::Response(response)) => {
                write_message_to_wire(&mut stream, HttpMessage::Response(response), RequestOptions::default());
            }
        };

        stream.flush().unwrap();
    }

    fn listen(&mut self) -> TcpListener {
        let addr = format!("0.0.0.0:{}", self.port);
        let listener = TcpListener::bind(addr).unwrap();
        self.port = listener.local_addr().unwrap().port();
        listener
    }
}