#include "log.h"
#include "shmget.h"
+
+struct {
+ int port;
+ char *iface;
+ char *host;
+ char *origin;
+ char *idxfile;
+} cfg = {
+ 8837,
+ "*",
+ "localhost",
+ "http://localhost",
+ "index.html",
+};
+
static volatile int force_quit;
static void handle_signal(int sig) {
static void respond(int fd, const char *req, int code) {
char buf[4096];
- char origin[256] = "http://localhost";
- char host[256] = "localhost";
+ char origin[256];
+ char host[256];
const char *s;
+
switch (code) {
case r_json:
case r_index:
- s = strstr(req, "Origin:");
- if (s){
+ if ( NULL != (s = strstr(req, "Origin: ")) ) {
s += 8; //strlen("Origin: ");
const char *e = strstr(s, "\r\n");
strncpy(origin, s, e-s);
}
- s = strstr(req, "Host:");
- if (s){
+ else
+ strcpy(origin, cfg.origin);
+
+ if ( NULL != (s = strstr(req, "Host: ")) ) {
s += 6;//strlen("Host: ");
const char *e = strstr(s, "\r\n");
strncpy(host, s, e-s);
}
+ else
+ strcpy(host, cfg.host);
- write(fd, buf, sprintf (buf, "HTTP/1.1 200 OK\r\n"));
- write(fd, buf, sprintf (buf, "Host: %s\r\n", host));
if (r_json == code){
- write(fd, buf, sprintf (buf, "Access-Control-Allow-Origin: %s\r\n", origin));
- write(fd, buf, sprintf (buf, "Content-type: text/json\r\n"));
- write(fd, buf, sprintf (buf, "Connection: close\r\n\r\n"));
+ write(fd, buf, sprintf(buf, "HTTP/1.1 200 OK\r\n"));
+ write(fd, buf, sprintf(buf, "Host: %s\r\n", host));
+ write(fd, buf, sprintf(buf, "Access-Control-Allow-Origin: %s\r\n", origin));
+ write(fd, buf, sprintf(buf, "Content-type: text/json\r\n"));
+ write(fd, buf, sprintf(buf, "Connection: close\r\n\r\n"));
write_telejson(fd);
- } else {
+ }
+ else {
struct file_info_t fi;
- if (0 == fserv_open_server("index.html", &fi)){
- write(fd, buf, sprintf (buf, "Content-type: text/html\r\n"));
- write(fd, buf, sprintf (buf, "Connection: close\r\n\r\n"));
+ if (0 == fserv_open_server(cfg.idxfile, &fi)){
+ write(fd, buf, sprintf(buf, "HTTP/1.1 200 OK\r\n"));
+ write(fd, buf, sprintf(buf, "Host: %s\r\n", host));
+ write(fd, buf, sprintf(buf, "Content-type: text/html\r\n"));
+ write(fd, buf, sprintf(buf, "Connection: close\r\n\r\n"));
fserv_sendfile(fd, &fi);
fserv_close(&fi);
- } else {
- write(fd, buf, sprintf (buf, "Content-type: text/plain\r\n"));
- write(fd, buf, sprintf (buf, "Connection: close\r\n\r\n"));
- write(fd, buf, sprintf (buf, "Tough luck"));
}
+ else
+ goto SEND_404;
}
break;
case r_none:
- write(fd, buf, sprintf (buf, "HTTP/1.1 404 Not Found\r\n"));
- write(fd, buf, sprintf (buf, "Host: localhost\r\n"));
- write(fd, buf, sprintf (buf, "Content-type: text/plain\r\n"));
- write(fd, buf, sprintf (buf, "Connection: close\r\n\r\n"));
- write(fd, buf, sprintf (buf, "Fuck you 404!"));
+ SEND_404:
+ write(fd, buf, sprintf(buf, "HTTP/1.1 404 Not Found\r\n"));
+ write(fd, buf, sprintf(buf, "Host: localhost\r\n"));
+ write(fd, buf, sprintf(buf, "Content-type: text/plain\r\n"));
+ write(fd, buf, sprintf(buf, "Connection: close\r\n\r\n"));
+ write(fd, buf, sprintf(buf, "404 Not Found"));
break;
default:
- write(fd, buf, sprintf (buf, "HTTP/1.1 500 Internal Server Error\r\n"));
- write(fd, buf, sprintf (buf, "Host: localhost\r\n"));
- write(fd, buf, sprintf (buf, "Content-type: text/plain\r\n"));
- write(fd, buf, sprintf (buf, "Connection: close\r\n\r\n"));
- write(fd, buf, sprintf (buf, "Fuck you 500!"));
+ write(fd, buf, sprintf(buf, "HTTP/1.1 500 Internal Server Error\r\n"));
+ write(fd, buf, sprintf(buf, "Host: localhost\r\n"));
+ write(fd, buf, sprintf(buf, "Content-type: text/plain\r\n"));
+ write(fd, buf, sprintf(buf, "Connection: close\r\n\r\n"));
+ write(fd, buf, sprintf(buf, "500 Internal Server Error"));
break;
}
}
-static int receive(int fd, int timeout) {
+static int rcv_request(int sock, char *buf, size_t size, int timeout) {
+ int res = -1;
+ size_t total = 0;
+ ssize_t bread = 0;
struct pollfd pe;
- int res;
- pe.fd = fd;
- char buf[2048];
- int bread, total;
- total = 0;
- *buf = 0;
+ pe.fd = sock;
do {
pe.events = POLLIN;
pe.revents = 0;
res = poll(&pe, 1, timeout);
if ( 0 < res && pe.revents == POLLIN ) {
errno = 0;
- bread = read(fd, buf + total, sizeof buf - total);
+ bread = read(sock, buf + total, size - total);
if ( 0 > bread ) {
switch (errno) {
case EAGAIN:
}
else {
total += bread;
- buf[total] = 0;
- if ( strstr(buf, "\r\n\r\n" ) ) {
- fprintf (stderr, "%s", buf);
- if (0 == strncmp(buf, "GET /json HTTP", 10))
- respond(fd, buf, r_json);
- else if (0 == strncmp(buf, "GET / HTTP", 10))
- respond(fd, buf, r_index);
- else
- respond(fd, NULL, r_none);
- *buf = 0;
+ if ( strstr(buf, "\r\n\r\n" ) )
res = 0;
- }
}
}
timeout = 200;
} while ( 1 == res && pe.revents == POLLIN && !force_quit );
+ buf[total] = 0;
return res;
}
static void *handle_conn( void *p ) {
int sock = *(int*)p;
- int err;
+ char buf[2048];
DPRINT( "sock: %d\n", sock );
- do {
- err = receive(sock, 1000);
- } while ( 0 < err && !force_quit );
+ if ( 0 == rcv_request(sock, buf, sizeof buf, 1000) ) {
+ DPRINT( "request:\n%s", buf);
+ if (0 == strncmp(buf, "GET /json HTTP", 10))
+ respond(sock, buf, r_json);
+ else if (0 == strncmp(buf, "GET / HTTP", 10))
+ respond(sock, buf, r_index);
+ else
+ respond(sock, NULL, r_none);
+ }
net_close( sock );
- return p;
+ free( p );
+ return NULL;
}
static int serve_http(void) {
int as, ss;
+ int *ps;
pthread_t tid;
pthread_attr_t attr;
- ss = net_open_server( 8837, "*" );
+ ss = net_open_server( cfg.port, cfg.iface );
if ( ss < 0 ) {
EPRINT( "net_open_server failed!\n" );
return -1;
}
while ( !force_quit ) {
- if ( (as = net_accept( ss )) > 0 ) {
+ if ( 0 < (as = net_accept( ss )) && NULL != (ps = malloc( sizeof *ps )) ) {
+ *ps = as;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- pthread_create(&tid, &attr, handle_conn, &as);
- usleep (100);
+ pthread_create(&tid, &attr, handle_conn, ps);
}
}
return 0;
}
+static int config( int argc, char *argv[] ) {
+ int opt;
+ const char *ostr = "+b:h:i:o:p:";
+
+ while ( -1 != ( opt = getopt( argc, argv, ostr ) ) ) {
+ switch ( opt ) {
+ case 'b':
+ cfg.iface = optarg;
+ break;
+ case 'h':
+ cfg.host = optarg;
+ break;
+ case 'i':
+ cfg.idxfile = optarg;
+ break;
+ case 'o':
+ cfg.origin = optarg;
+ break;
+ case 'p':
+ cfg.port = strtol(optarg, NULL, 10);
+ break;
+ case ':':
+ EPRINT( "Missing argument for option '%c'\n", optopt );
+ return -1;
+ break;
+ case '?':
+ default:
+ EPRINT( "Unrecognized option '%c'\n", optopt );
+ return -1;
+ break;
+ }
+ }
+ return 0;
+}
+
int main(int argc, char *argv[]) {
signal(SIGTERM, handle_signal);
signal(SIGINT, handle_signal);
+ if ( 0 != config( argc, argv ) )
+ exit( EXIT_FAILURE);
+
if ( 0 != init_shm() )
exit( EXIT_FAILURE);
exit( EXIT_FAILURE);
exit( EXIT_SUCCESS );
- (void)argc; (void)argv;
}