diff options
Diffstat (limited to 'datastore-leveldb/src/main.cpp')
-rw-r--r-- | datastore-leveldb/src/main.cpp | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/datastore-leveldb/src/main.cpp b/datastore-leveldb/src/main.cpp new file mode 100644 index 0000000..4fd95df --- /dev/null +++ b/datastore-leveldb/src/main.cpp @@ -0,0 +1,123 @@ +extern "C" { +#include "server_eh.h" +#include <unistd.h> +#include <signal.h> +#include <ev.h> +#include <string.h> +#include <netinet/in.h> +#include <sys/sendfile.h> +#include <sys/stat.h> +#include <fcntl.h> +} + +#include <iostream> + +#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, "<pre>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); +} |