1 /* This is a barebone keep-alive HTTP server */
2 #include <libusockets.h>
3 /* Compiling with LIBUS_NO_SSL will ignore SSL */
4 const int SSL = 1;
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9
10 struct http_socket {
11 /* How far we have streamed our response */
12 int offset;
13 };
14
15 struct http_context {
16 /* The shared response */
17 char *response;
18 int length;
19 };
20
21 /* We don't need any of these */
on_wakeup(struct us_loop_t * loop)22 void on_wakeup(struct us_loop_t *loop) {
23
24 }
25
on_pre(struct us_loop_t * loop)26 void on_pre(struct us_loop_t *loop) {
27
28 }
29
30 /* This is not HTTP POST, it is merely an event emitted post loop iteration */
on_post(struct us_loop_t * loop)31 void on_post(struct us_loop_t *loop) {
32
33 }
34
on_http_socket_writable(struct us_socket_t * s)35 struct us_socket_t *on_http_socket_writable(struct us_socket_t *s) {
36 struct http_socket *http_socket = (struct http_socket *) us_socket_ext(SSL, s);
37 struct http_context *http_context = (struct http_context *) us_socket_context_ext(SSL, us_socket_context(SSL, s));
38
39 /* Stream whatever is remaining of the response */
40 http_socket->offset += us_socket_write(SSL, s, http_context->response + http_socket->offset, http_context->length - http_socket->offset, 0);
41
42 return s;
43 }
44
on_http_socket_close(struct us_socket_t * s,int code,void * reason)45 struct us_socket_t *on_http_socket_close(struct us_socket_t *s, int code, void *reason) {
46 printf("Client disconnected\n");
47
48 return s;
49 }
50
on_http_socket_end(struct us_socket_t * s)51 struct us_socket_t *on_http_socket_end(struct us_socket_t *s) {
52 /* HTTP does not support half-closed sockets */
53 us_socket_shutdown(SSL, s);
54 return us_socket_close(SSL, s, 0, NULL);
55 }
56
on_http_socket_data(struct us_socket_t * s,char * data,int length)57 struct us_socket_t *on_http_socket_data(struct us_socket_t *s, char *data, int length) {
58 /* Get socket extension and the socket's context's extension */
59 struct http_socket *http_socket = (struct http_socket *) us_socket_ext(SSL, s);
60 struct http_context *http_context = (struct http_context *) us_socket_context_ext(SSL, us_socket_context(SSL, s));
61
62 /* We treat all data events as a request */
63 http_socket->offset = us_socket_write(SSL, s, http_context->response, http_context->length, 0);
64
65 /* Reset idle timer */
66 us_socket_timeout(SSL, s, 30);
67
68 return s;
69 }
70
on_http_socket_open(struct us_socket_t * s,int is_client,char * ip,int ip_length)71 struct us_socket_t *on_http_socket_open(struct us_socket_t *s, int is_client, char *ip, int ip_length) {
72 struct http_socket *http_socket = (struct http_socket *) us_socket_ext(SSL, s);
73
74 /* Reset offset */
75 http_socket->offset = 0;
76
77 /* Timeout idle HTTP connections */
78 us_socket_timeout(SSL, s, 30);
79
80 printf("Client connected\n");
81
82 return s;
83 }
84
on_http_socket_timeout(struct us_socket_t * s)85 struct us_socket_t *on_http_socket_timeout(struct us_socket_t *s) {
86 /* Close idle HTTP sockets */
87 return us_socket_close(SSL, s, 0, NULL);
88 }
89
main()90 int main() {
91 /* Create the event loop */
92 struct us_loop_t *loop = us_create_loop(0, on_wakeup, on_pre, on_post, 0);
93
94 /* Create a socket context for HTTP */
95 struct us_socket_context_options_t options = {};
96 options.key_file_name = "/home/alexhultman/uWebSockets.js/misc/key.pem";
97 options.cert_file_name = "/home/alexhultman/uWebSockets.js/misc/cert.pem";
98 options.passphrase = "1234";
99
100 struct us_socket_context_t *http_context = us_create_socket_context(SSL, loop, sizeof(struct http_context), options);
101
102
103 /* Generate the shared response */
104 const char body[] = "<html><body><h1>Why hello there!</h1></body></html>";
105
106 struct http_context *http_context_ext = (struct http_context *) us_socket_context_ext(SSL, http_context);
107 http_context_ext->response = (char *) malloc(128 + sizeof(body) - 1);
108 http_context_ext->length = snprintf(http_context_ext->response, 128 + sizeof(body) - 1, "HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n\r\n%s", sizeof(body) - 1, body);
109
110 /* Set up event handlers */
111 us_socket_context_on_open(SSL, http_context, on_http_socket_open);
112 us_socket_context_on_data(SSL, http_context, on_http_socket_data);
113 us_socket_context_on_writable(SSL, http_context, on_http_socket_writable);
114 us_socket_context_on_close(SSL, http_context, on_http_socket_close);
115 us_socket_context_on_timeout(SSL, http_context, on_http_socket_timeout);
116 us_socket_context_on_end(SSL, http_context, on_http_socket_end);
117
118 /* Start serving HTTP connections */
119 struct us_listen_socket_t *listen_socket = us_socket_context_listen(SSL, http_context, 0, 3000, 0, sizeof(struct http_socket));
120
121 if (listen_socket) {
122 printf("Listening on port 3000...\n");
123 us_loop_run(loop);
124 } else {
125 printf("Failed to listen!\n");
126 }
127 }
128