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
|
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);
}
|