Skip to content

Commit 842a22d

Browse files
committed
Add barebone HTTP server example
1 parent 1b19930 commit 842a22d

File tree

2 files changed

+114
-1
lines changed

2 files changed

+114
-1
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
default:
2-
gcc -O3 -o echo_server -s -Isrc src/*.c src/eventing/*.c examples/echo_server.c -lssl -lcrypto
2+
gcc -DLIBUS_NO_SSL -O3 -o echo_server -s -Isrc src/*.c src/eventing/*.c examples/echo_server.c
3+
gcc -DLIBUS_NO_SSL -O3 -o http_server -s -Isrc src/*.c src/eventing/*.c examples/http_server.c

examples/http_server.c

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/* This is a barebone keep-alive HTTP server */
2+
3+
#include <libusockets.h>
4+
5+
#include <stdio.h>
6+
#include <stdlib.h>
7+
#include <string.h>
8+
9+
struct http_socket {
10+
/* How far we have streamed our response */
11+
int offset;
12+
};
13+
14+
struct http_context {
15+
/* The shared response */
16+
char *response;
17+
int length;
18+
};
19+
20+
/* We don't need any of these */
21+
void on_wakeup(struct us_loop *loop) {
22+
23+
}
24+
25+
void on_pre(struct us_loop *loop) {
26+
27+
}
28+
29+
/* This is not HTTP POST, it is merely an event emitted post loop iteration */
30+
void on_post(struct us_loop *loop) {
31+
32+
}
33+
34+
void on_http_socket_writable(struct us_socket *s) {
35+
struct http_socket *http_socket = (struct http_socket *) us_socket_ext(s);
36+
struct http_context *http_context = (struct http_context *) us_socket_context_ext(us_socket_get_context(s));
37+
38+
/* Stream whatever is remaining of the response */
39+
http_socket->offset += us_socket_write(s, http_context->response + http_socket->offset, http_context->length - http_socket->offset, 0);
40+
}
41+
42+
void on_http_socket_close(struct us_socket *s) {
43+
printf("Client disconnected\n");
44+
}
45+
46+
void on_http_socket_end(struct us_socket *s) {
47+
/* HTTP does not support half-closed sockets */
48+
us_socket_shutdown(s);
49+
us_socket_close(s);
50+
}
51+
52+
void on_http_socket_data(struct us_socket *s, char *data, int length) {
53+
/* Get socket extension and the socket's context's extension */
54+
struct http_socket *http_socket = (struct http_socket *) us_socket_ext(s);
55+
struct http_context *http_context = (struct http_context *) us_socket_context_ext(us_socket_get_context(s));
56+
57+
/* We treat all data events as a request */
58+
http_socket->offset = us_socket_write(s, http_context->response, http_context->length, 0);
59+
60+
/* Reset idle timer */
61+
us_socket_timeout(s, 30);
62+
}
63+
64+
void on_http_socket_open(struct us_socket *s) {
65+
struct http_socket *http_socket = (struct http_socket *) us_socket_ext(s);
66+
67+
/* Reset offset */
68+
http_socket->offset = 0;
69+
70+
/* Timeout idle HTTP connections */
71+
us_socket_timeout(s, 30);
72+
73+
printf("Client connected\n");
74+
}
75+
76+
void on_http_socket_timeout(struct us_socket *s) {
77+
/* Close idle HTTP sockets */
78+
us_socket_close(s);
79+
}
80+
81+
int main() {
82+
/* Create the event loop */
83+
struct us_loop *loop = us_create_loop(1, on_wakeup, on_pre, on_post, 0);
84+
85+
/* Create a socket context for HTTP */
86+
struct us_socket_context *http_context = us_create_socket_context(loop, sizeof(struct http_context));
87+
88+
/* Generate the shared response */
89+
const char body[] = "<html><body><h1>Why hello there!</h1></body></html>";
90+
91+
struct http_context *http_context_ext = (struct http_context *) us_socket_context_ext(http_context);
92+
http_context_ext->response = (char *) malloc(128 + sizeof(body) - 1);
93+
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);
94+
95+
/* Set up event handlers */
96+
us_socket_context_on_open(http_context, on_http_socket_open);
97+
us_socket_context_on_data(http_context, on_http_socket_data);
98+
us_socket_context_on_writable(http_context, on_http_socket_writable);
99+
us_socket_context_on_close(http_context, on_http_socket_close);
100+
us_socket_context_on_timeout(http_context, on_http_socket_timeout);
101+
us_socket_context_on_end(http_context, on_http_socket_end);
102+
103+
/* Start serving HTTP connections */
104+
struct us_listen_socket *listen_socket = us_socket_context_listen(http_context, 0, 3000, 0, sizeof(struct http_socket));
105+
106+
if (listen_socket) {
107+
printf("Listening on port 3000...\n");
108+
us_loop_run(loop);
109+
} else {
110+
printf("Failed to listen!\n");
111+
}
112+
}

0 commit comments

Comments
 (0)