set up basic HTTP server based on libevent
author() <nilclass@riseup.net>
Fri, 31 May 2013 01:06:26 +0000 (03:06 +0200)
committer() <nilclass@riseup.net>
Fri, 31 May 2013 01:06:26 +0000 (03:06 +0200)
Makefile [new file with mode: 0644]
src/common.c [new file with mode: 0644]
src/main.c [new file with mode: 0644]
src/rs-serve.h [new file with mode: 0644]
src/storage.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..e613fd0
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,24 @@
+CFLAGS=${shell pkg-config libevent --cflags}
+LDFLAGS=${shell pkg-config libevent --libs}
+
+OBJECTS=src/main.o src/common.o src/storage.o
+
+default: all
+
+all: rs-serve
+
+rs-serve: $(OBJECTS)
+       @echo "[LD] $@"
+       @$(CC) -o $@ $(OBJECTS) $(LDFLAGS)
+
+%.o: %.c
+       @echo "[CC] $@"
+       @$(CC) -c $< -o $@ $(CFLAGS)
+
+clean:
+       @echo "[CLEAN]"
+       @rm -f rs-serve
+       @rm -f $(OBJECTS)
+       @rm -f *~ src/*~
+
+.PHONY: default all clean
\ No newline at end of file
diff --git a/src/common.c b/src/common.c
new file mode 100644 (file)
index 0000000..1c81826
--- /dev/null
@@ -0,0 +1,34 @@
+
+#include "rs-serve.h"
+
+char *time_now() {
+  static char timestamp[100]; // FIXME: not threadsafe!
+  time_t t = time(NULL);
+  struct tm *tmp = localtime(&t);
+  strftime(timestamp, 99, "%F %T %z", tmp);
+  return timestamp;
+}
+
+void log_starting(const char *address, int port) {
+  if(! address) {
+    address = "0.0.0.0";
+  }
+  printf("[%s] Server listening on %s:%d\n", time_now(), address, port);
+}
+
+void log_request(struct evhttp_request *request) {
+  char *method;
+  switch(evhttp_request_get_command(request)) {
+  case EVHTTP_REQ_GET: method = "GET"; break;
+  case EVHTTP_REQ_POST: method = "POST"; break;
+  case EVHTTP_REQ_HEAD: method = "HEAD"; break;
+  case EVHTTP_REQ_PUT: method = "PUT"; break;
+  case EVHTTP_REQ_OPTIONS: method = "OPTIONS"; break;
+  case EVHTTP_REQ_DELETE: method = "DELETE"; break;
+  default: method = "(unknown)"; break;
+  }
+  
+  printf("[%s] %s %s -> %d\n", time_now(), method,
+         evhttp_request_get_uri(request),
+         evhttp_request_get_response_code(request));
+} 
diff --git a/src/main.c b/src/main.c
new file mode 100644 (file)
index 0000000..79e7259
--- /dev/null
@@ -0,0 +1,62 @@
+
+#include "rs-serve.h"
+
+#define RS_ADDRESS NULL
+#define RS_PORT 8181
+#define RS_ALLOWED_METHODS EVHTTP_REQ_OPTIONS | EVHTTP_REQ_HEAD | EVHTTP_REQ_GET |\
+  EVHTTP_REQ_PUT | EVHTTP_REQ_DELETE
+
+
+static void fatal_error_callback(int err) {
+  fprintf(stderr, "A fatal error occured (code: %d)\nExiting.\n", err);
+  exit(EXIT_FAILURE);
+}
+
+static void handle_request_callback(struct evhttp_request *request, void *ctx) {
+  switch(evhttp_request_get_command(request)) {
+  case EVHTTP_REQ_OPTIONS:
+    storage_options(request);
+    break;
+  case EVHTTP_REQ_GET:
+    storage_get(request);
+    break;
+  case EVHTTP_REQ_PUT:
+    storage_put(request);
+    break;
+  case EVHTTP_REQ_DELETE:
+    storage_delete(request);
+    break;
+  case EVHTTP_REQ_HEAD:
+    storage_head(request);
+    break;
+  }
+
+  log_request(request);
+}
+
+int main(int argc, char **argv) {
+  event_set_fatal_callback(fatal_error_callback);
+  event_enable_debug_mode();
+
+  struct event_base *base = event_base_new();
+
+  if(! base) {
+    perror("Failed to create event base");
+    return 1;
+  }
+
+  struct evhttp *server = evhttp_new(base);
+
+  if(! server) {
+    perror("Failed to create server");
+    return 2;
+  }
+
+  evhttp_bind_socket(server, RS_ADDRESS, RS_PORT);
+  evhttp_set_allowed_methods(server, RS_ALLOWED_METHODS);
+  evhttp_set_gencb(server, handle_request_callback, NULL);
+
+  log_starting(RS_ADDRESS, RS_PORT);
+
+  return event_base_dispatch(base);
+}
diff --git a/src/rs-serve.h b/src/rs-serve.h
new file mode 100644 (file)
index 0000000..da59f7f
--- /dev/null
@@ -0,0 +1,29 @@
+
+#ifndef RS_SERVE_H
+#define RS_SERVE_H
+
+// standard headers
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+// libevent headers
+#include <event2/event.h>
+#include <event2/http.h>
+
+/* COMMON */
+
+void log_starting(const char *address, int port);
+void log_request(struct evhttp_request *request);
+
+/* STORAGE */
+
+void storage_options(struct evhttp_request *request);
+void storage_get(struct evhttp_request *request);
+void storage_put(struct evhttp_request *request);
+void storage_delete(struct evhttp_request *request);
+void storage_head(struct evhttp_request *request);
+
+#endif
diff --git a/src/storage.c b/src/storage.c
new file mode 100644 (file)
index 0000000..698adf3
--- /dev/null
@@ -0,0 +1,23 @@
+
+#include "rs-serve.h"
+
+
+void storage_options(struct evhttp_request *request) {
+  evhttp_send_reply(request, HTTP_OK, NULL, NULL);
+}
+
+void storage_get(struct evhttp_request *request) {
+  evhttp_send_reply(request, HTTP_OK, NULL, NULL);
+}
+
+void storage_put(struct evhttp_request *request) {
+  evhttp_send_reply(request, HTTP_OK, NULL, NULL);
+}
+
+void storage_delete(struct evhttp_request *request) {
+  evhttp_send_reply(request, HTTP_OK, NULL, NULL);
+}
+
+void storage_head(struct evhttp_request *request) {
+  evhttp_send_reply(request, HTTP_OK, NULL, NULL);
+}