Skip to content

Commit

Permalink
Add barebone HTTP server example
Browse files Browse the repository at this point in the history
  • Loading branch information
uNetworkingAB committed Aug 5, 2018
1 parent 1b19930 commit 842a22d
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 1 deletion.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
default:
gcc -O3 -o echo_server -s -Isrc src/*.c src/eventing/*.c examples/echo_server.c -lssl -lcrypto
gcc -DLIBUS_NO_SSL -O3 -o echo_server -s -Isrc src/*.c src/eventing/*.c examples/echo_server.c
gcc -DLIBUS_NO_SSL -O3 -o http_server -s -Isrc src/*.c src/eventing/*.c examples/http_server.c
112 changes: 112 additions & 0 deletions examples/http_server.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/* This is a barebone keep-alive HTTP server */

#include <libusockets.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct http_socket {
/* How far we have streamed our response */
int offset;
};

struct http_context {
/* The shared response */
char *response;
int length;
};

/* We don't need any of these */
void on_wakeup(struct us_loop *loop) {

}

void on_pre(struct us_loop *loop) {

}

/* This is not HTTP POST, it is merely an event emitted post loop iteration */
void on_post(struct us_loop *loop) {

}

void on_http_socket_writable(struct us_socket *s) {
struct http_socket *http_socket = (struct http_socket *) us_socket_ext(s);
struct http_context *http_context = (struct http_context *) us_socket_context_ext(us_socket_get_context(s));

/* Stream whatever is remaining of the response */
http_socket->offset += us_socket_write(s, http_context->response + http_socket->offset, http_context->length - http_socket->offset, 0);
}

void on_http_socket_close(struct us_socket *s) {
printf("Client disconnected\n");
}

void on_http_socket_end(struct us_socket *s) {
/* HTTP does not support half-closed sockets */
us_socket_shutdown(s);
us_socket_close(s);
}

void on_http_socket_data(struct us_socket *s, char *data, int length) {
/* Get socket extension and the socket's context's extension */
struct http_socket *http_socket = (struct http_socket *) us_socket_ext(s);
struct http_context *http_context = (struct http_context *) us_socket_context_ext(us_socket_get_context(s));

/* We treat all data events as a request */
http_socket->offset = us_socket_write(s, http_context->response, http_context->length, 0);

/* Reset idle timer */
us_socket_timeout(s, 30);
}

void on_http_socket_open(struct us_socket *s) {
struct http_socket *http_socket = (struct http_socket *) us_socket_ext(s);

/* Reset offset */
http_socket->offset = 0;

/* Timeout idle HTTP connections */
us_socket_timeout(s, 30);

printf("Client connected\n");
}

void on_http_socket_timeout(struct us_socket *s) {
/* Close idle HTTP sockets */
us_socket_close(s);
}

int main() {
/* Create the event loop */
struct us_loop *loop = us_create_loop(1, on_wakeup, on_pre, on_post, 0);

/* Create a socket context for HTTP */
struct us_socket_context *http_context = us_create_socket_context(loop, sizeof(struct http_context));

/* Generate the shared response */
const char body[] = "<html><body><h1>Why hello there!</h1></body></html>";

struct http_context *http_context_ext = (struct http_context *) us_socket_context_ext(http_context);
http_context_ext->response = (char *) malloc(128 + sizeof(body) - 1);
http_context_ext->length = snprintf(http_context_ext->response, 128 + sizeof(body) - 1, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s", sizeof(body) - 1, body);

/* Set up event handlers */
us_socket_context_on_open(http_context, on_http_socket_open);
us_socket_context_on_data(http_context, on_http_socket_data);
us_socket_context_on_writable(http_context, on_http_socket_writable);
us_socket_context_on_close(http_context, on_http_socket_close);
us_socket_context_on_timeout(http_context, on_http_socket_timeout);
us_socket_context_on_end(http_context, on_http_socket_end);

/* Start serving HTTP connections */
struct us_listen_socket *listen_socket = us_socket_context_listen(http_context, 0, 3000, 0, sizeof(struct http_socket));

if (listen_socket) {
printf("Listening on port 3000...\n");
us_loop_run(loop);
} else {
printf("Failed to listen!\n");
}
}

0 comments on commit 842a22d

Please sign in to comment.