extern "C" { #include "server_eh.h" #include #include #include #include #include #include #include #include } #include #include "leveldb/db.h" #include "leveldb/comparator.h" // see http_parser.h // char DELETE = 0; // char GET = 1; // char HEAD = 2; // char POST = 3; // char PUT = 4; static inline void send_file(const char *path, int fd_out) { int fd_in; struct stat stat_buf; fd_in = open(path, O_RDONLY); fstat(fd_in, &stat_buf); sendfile(fd_out, fd_in, 0, stat_buf.st_size); close(fd_in); } static inline void http_ok(int fd, const char *content_type) { #define write_const(fd, text) \ write(fd, text, strlen(text)); write_const(fd, "HTTP/1.1 200 OK\r\nContent-Type: "); write_const(fd, content_type); write_const(fd, "\r\n\r\n"); #undef write_const } static inline void http_fail(int fd) { write(fd, "HTTP/1.1 501 FAIL\r\n\r\n",25); } void handle_request(struct http_request *request, int fd) { #define write_const(fd, text) \ write(fd, text, strlen(text)); if (request->url == NULL) { // happens only under high load std::cerr << "url is null" << std::endl; http_fail(fd); close(fd); return; } std::string url(request->url); if (url == "/") { http_ok(fd, "text/html; charset=UTF-8"); send_file("index.html", fd); } else if (url.find("/api/put") == 0) { http_ok(fd, "text/html; charset=UTF-8"); std::cout << "put" << std::endl; } else if (url.find("/debug") == 0) { http_ok(fd, "text/html; charset=UTF-8"); struct http_header *header = request->headers; write_const(fd, "
Headers:\n");
        while (header != NULL) {
            write_const(fd, header->name);
            write_const(fd, ": ");
            write_const(fd, header->value);
            write_const(fd, "\n");
            header = header->next;
        }
        if (request->flags & F_HREQ_KEEPALIVE) {
             write_const(fd, "\nis keepalive.\n");
        }
        write_const(fd, "\r\n\r\n");
    } else {
        http_fail(fd);
    }
    close(fd);
#undef write_const
}

static struct http_server server;

void sigint_handler(int s) {
    struct ev_loop *loop = server.loop;
    ev_io_stop(EV_A_ server.ev_accept);
    exit(0);
}

int main(int argc, char **argv) {
    // configure server structures and desired listen address
    struct sockaddr_in listen_addr;
    memset(&listen_addr, 0, sizeof(listen_addr));
    listen_addr.sin_family = AF_INET;
    listen_addr.sin_addr.s_addr = INADDR_ANY;
    listen_addr.sin_port = htons(5000);
    server.listen_addr = &listen_addr;
    server.handle_request = handle_request;

    // ignore SIGPIPE
    struct sigaction on_sigpipe;
    on_sigpipe.sa_handler = SIG_IGN;
    sigemptyset(&on_sigpipe.sa_mask);
    sigaction(SIGPIPE, &on_sigpipe, NULL);

    // handle C-c
    struct sigaction on_sigint;
    on_sigint.sa_handler = sigint_handler;
    sigemptyset(&on_sigint.sa_mask);
    on_sigint.sa_flags = 0;
    sigaction(SIGINT, &on_sigint, NULL);

    // start the server
    return http_server_loop(&server);
}