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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! The module contains a simple HTTP/2 server implementation.

use http::{Response, HttpResult, HttpError, HttpScheme, Header, StreamId};
use http::transport::TransportStream;
use http::connection::{HttpConnection, EndStream, SendStatus};
use http::session::{DefaultSessionState, SessionState, Stream};
use http::server::ServerConnection;

/// The struct represents a fully received request.
pub struct ServerRequest<'a> {
    pub stream_id: StreamId,
    pub headers: &'a [Header],
    pub body: &'a [u8],
}

/// The struct implements a simple HTTP/2 server that allows users to register a request handler (a
/// callback taking a `ServerRequest` and returning a `Response`) which is run on all received
/// requests.
///
/// The `handle_next` method needs to be called regularly in order to have the server process
/// received frames, as well as send out the responses.
///
/// This is an exceedingly simple implementation of an HTTP/2 server and is mostly an example of
/// how the `solicit::http` API can be used to make one.
///
/// # Examples
///
/// ```no_run
/// extern crate solicit;
/// use std::str;
/// use std::net::{TcpListener, TcpStream};
/// use std::thread;
///
/// use solicit::server::SimpleServer;
///
/// use solicit::http::Response;
///
/// fn main() {
///     fn handle_client(stream: TcpStream) {
///         let mut server = SimpleServer::new(stream, |req| {
///             println!("Received request:");
///             for header in req.headers.iter() {
///                 println!("  {}: {}",
///                 str::from_utf8(&header.0).unwrap(),
///                 str::from_utf8(&header.1).unwrap());
///             }
///             println!("Body:\n{}", str::from_utf8(&req.body).unwrap());
///
///             // Return a dummy response for every request
///             Response {
///                 headers: vec![
///                     (b":status".to_vec(), b"200".to_vec()),
///                     (b"x-solicit".to_vec(), b"Hello, World!".to_vec()),
///                 ],
///                 body: vec![65],
///                 stream_id: req.stream_id,
///            }
///         }).unwrap();
///         while let Ok(_) = server.handle_next() {}
///         println!("Server done (client disconnected)");
///     }
///
///     let listener = TcpListener::bind("127.0.0.1:8080").unwrap();
///     for stream in listener.incoming() {
///         let stream = stream.unwrap();
///         thread::spawn(move || {
///             handle_client(stream)
///         });
///     }
/// }
/// ```
pub struct SimpleServer<TS, H> where TS: TransportStream, H: FnMut(ServerRequest) -> Response {
    conn: ServerConnection<TS, TS>,
    handler: H,
}

impl<TS, H> SimpleServer<TS, H>
        where TS: TransportStream, H: FnMut(ServerRequest) -> Response {
    /// Creates a new `SimpleServer` that will use the given `TransportStream` to communicate to
    /// the client. Assumes that the stream is fully uninitialized -- no preface sent or read yet.
    pub fn new(mut stream: TS, handler: H) -> HttpResult<SimpleServer<TS, H>> {
        // First assert that the preface is received
        let mut preface = [0; 24];
        stream.read_exact(&mut preface).unwrap();
        if &preface != b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" {
            return Err(HttpError::UnableToConnect);
        }

        let conn = HttpConnection::<TS, TS>::with_stream(stream, HttpScheme::Http);
        let mut server = SimpleServer {
            conn: ServerConnection::with_connection(conn, DefaultSessionState::new()),
            handler: handler,
        };

        // Initialize the connection -- send own settings and process the peer's
        try!(server.conn.init());

        // Set up done
        Ok(server)
    }

    /// Handles the next incoming frame, blocking to receive it if nothing is available on the
    /// underlying stream.
    ///
    /// Handling the frame can trigger the handler callback. Any responses returned by the handler
    /// are immediately flushed out to the client (blocking the call until it's done).
    pub fn handle_next(&mut self) -> HttpResult<()> {
        try!(self.conn.handle_next_frame());
        let responses = try!(self.handle_requests());
        try!(self.prepare_responses(responses));
        try!(self.flush_streams());
        try!(self.reap_streams());

        Ok(())
    }

    /// Invokes the request handler for each fully received request. Collects all the responses
    /// into the returned `Vec`.
    fn handle_requests(&mut self) -> HttpResult<Vec<Response>> {
        let handler = &mut self.handler;
        Ok(self.conn.state.iter().filter(|s| s.is_closed_remote()).map(|stream| {
            let req = ServerRequest {
                stream_id: stream.stream_id,
                headers: stream.headers.as_ref().unwrap(),
                body: &stream.body,
            };
            handler(req)
        }).collect())
    }

    /// Prepares the streams for each of the given responses. Headers for each response are
    /// immediately sent and the data staged into the streams' outgoing buffer.
    fn prepare_responses(&mut self, responses: Vec<Response>) -> HttpResult<()> {
        for response in responses.into_iter() {
            try!(self.conn.start_response(
                    response.headers,
                    response.stream_id,
                    EndStream::No));
            let mut stream = self.conn.state.get_stream_mut(response.stream_id).unwrap();
            stream.set_full_data(response.body);
        }

        Ok(())
    }

    /// Flushes the outgoing buffers of all streams.
    #[inline]
    fn flush_streams(&mut self) -> HttpResult<()> {
        while let SendStatus::Sent = try!(self.conn.send_next_data()) {}

        Ok(())
    }

    /// Removes closed streams from the connection state.
    #[inline]
    fn reap_streams(&mut self) -> HttpResult<()> {
        // Moves the streams out of the state and then drops them
        let _ = self.conn.state.get_closed();
        Ok(())
    }
}