tdengine 0.1.2

game server for Rust
Documentation
use std::collections::HashMap;
use std::thread;
use std::net::TcpStream;

use std::io::prelude::*;
use time;
use std::sync::Arc;
use td_rthreadpool::ReentrantMutex;
use tiny_http::{Server, Response, Request};
use {ThreadUtils, LuaEngine};

#[allow(dead_code)]
struct ServerRequest {
    request: Request,
    time: u32,
}

impl ServerRequest {
    pub fn new(request: Request) -> ServerRequest {
        ServerRequest {
            request: request,
            time: (time::precise_time_ns() / 1_000_000) as u32,
        }
    }
}

pub struct HttpMgr {
    requests: HashMap<u32, ServerRequest>,
    mutex: Arc<ReentrantMutex<u32>>,
}

static HTTP_POOL_NAME: &'static str = "http";
static mut el: *mut HttpMgr = 0 as *mut _;
impl HttpMgr {
    pub fn instance() -> &'static mut HttpMgr {
        unsafe {
            if el == 0 as *mut _ {
                el = Box::into_raw(Box::new(HttpMgr::new()));
            }
            &mut *el
        }
    }

    pub fn new() -> HttpMgr {
        ThreadUtils::instance().create_pool(HTTP_POOL_NAME.to_string(), 10);
        HttpMgr {
            requests: HashMap::new(),
            mutex: Arc::new(ReentrantMutex::new(0)),
        }
    }

    pub fn new_request_receive(&mut self, mut request: Request) {
        let mut data = self.mutex.lock().unwrap();
        if *data > u32::max_value() - 1000 {
            *data = 0;
        }
        *data += 1;

        let mut body = String::new();
        let _ = request.as_reader().read_to_string(&mut body);
        LuaEngine::instance().apply_args_func("http_server_msg_recv".to_string(),
                                              vec![data.to_string(),
                                                   request.url().to_string(),
                                                   body,
                                                   format!("{}", request.remote_addr())]);
        self.requests.insert(*data, ServerRequest::new(request));

    }

    pub fn http_server_respone(&mut self, cookie: u32, content: String) {
        let _data = self.mutex.lock().unwrap();
        let request = unwrap_or!(self.requests.remove(&cookie), return);
        let pool = ThreadUtils::instance().get_pool(&HTTP_POOL_NAME.to_string());
        pool.execute(move || {
            let _ = request.request.respond(Response::from_string(&*content));
        });
    }

    pub fn http_get_request(&mut self, cookie: u32, addr: String, url: String) {
        let pool = ThreadUtils::instance().get_pool(&HTTP_POOL_NAME.to_string());
        pool.execute(move || {
            let failed_cookie = cookie;
            let failed_fn = move || {
                LuaEngine::instance().apply_args_func(
                    "http_client_msg_respone".to_string(),
                    vec![failed_cookie.to_string(), "false".to_string()]
                    );
            };

            let mut stream = unwrap_or!(TcpStream::connect(&*addr).ok(), {failed_fn(); return} );
            unwrap_or!(stream.write(b"GET / HTTP/1.1\r\nContent-Type: text/plain; charset=utf8\r\n").ok(), return failed_fn());
            let ip_port: Vec<&str> = addr.split(':').collect();
            let host = if ip_port.len() == 0 { &*addr } else { ip_port[0] };
            let content = format!("Host: {}\r\nContent-Length: {}\r\n\r\n{}", host, url.len(), url);
            unwrap_or!(stream.write(content.as_bytes()).ok(), return failed_fn());
            unwrap_or!(stream.flush().ok(), return failed_fn());

            let mut result : Vec<u8> = vec![];
            let mut bytes = [0u8; 1024];
            let mut content_length = 0;
            let mut header_len = 0;
            loop {
                let size = unwrap_or!(stream.read(&mut bytes).ok(), return failed_fn());
                if size == 0 {
                    break;
                }

                if content_length == 0 {
                    let content = String::from_utf8_lossy(&result);
                    if let Some(_) = content.find("\r\n\r\n") {
                        let header_content: Vec<&str> = content.split("\r\n\r\n").collect();
                        header_len = header_content[0].len() + 4;
                        let header_str : Vec<&str> = header_content[0].split("\r\n").collect();
                        for it in header_str {
                            let values: Vec<&str> = it.split(": ").collect();
                            if values.len() > 1 && values[0] == "Content-Length" {
                                content_length = unwrap_or!(values[1].parse::<usize>().ok(), return failed_fn());
                            }
                        }
                        if content_length == 0 {
                            break;
                        }
                    }
                }
                result.extend_from_slice(&bytes[..size]);
                if content_length + header_len >= result.len() {
                    break;
                }
            }
            if content_length == 0 {
                return failed_fn();
            }
            LuaEngine::instance().apply_args_func(
                "http_client_msg_respone".to_string(),
                vec![cookie.to_string(), "true".to_string(), String::from_utf8_lossy(&result).to_string()]);
        });
    }

    pub fn start_listen(&mut self, url: String) -> bool {
        thread::spawn(move || {
            let server = Server::http(&*url).unwrap();

            for request in server.incoming_requests() {
                println!("received request! method: {:?}, url: {:?}, headers: {:?}",
                         request.method(),
                         request.url(),
                         request.headers());

                HttpMgr::instance().new_request_receive(request);
            }
        });
        true
    }
}