1 /* This example, or test, is a moron test where the library is being hammered in all the possible ways randomly over time */
2 
3 #include <libusockets.h>
4 const int SSL = 1;
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <time.h>
10 #include <stdbool.h>
11 
12 int port;
13 int opened_connections, closed_connections, operations_done;
14 struct us_socket_context_t *server_context, *client_context;
15 struct us_listen_socket_t *listen_socket;
16 
17 char client_msg[] = "Hello from client";
18 char server_msg[] = "Hello from server";
19 
20 // also make sure to have socket ext data
21 // and context ext data
22 // and loop ext data
23 
24 bool client_received_data;
25 bool server_received_data;
26 
27 struct socket_context {
28     char *backpressure;
29     int length;
30 };
31 
on_wakeup(struct us_loop_t * loop)32 void on_wakeup(struct us_loop_t *loop) {
33     // note: we expose internal functions to trigger a timeout sweep to find bugs
34     extern void us_internal_timer_sweep(struct us_loop_t * loop);
35     us_internal_timer_sweep(loop);
36 }
37 
38 // maybe use thse to count spurious wakeups?
39 // that is, if we get tons of pre/post over and over without any events
40 // that would point towards 100% cpu usage kind of bugs
on_pre(struct us_loop_t * loop)41 void on_pre(struct us_loop_t *loop) {
42     // printf("PRE\n");
43 }
44 
on_post(struct us_loop_t * loop)45 void on_post(struct us_loop_t *loop) {
46     // check if we did perform_random_operation
47 }
48 
write_buffered(int SSL,struct us_socket_t * s,const char * data,int length)49 int write_buffered(int SSL, struct us_socket_t *s, const char *data, int length) {
50 
51     struct socket_context *ctx = (struct socket_context *)us_socket_ext(SSL, s);
52 
53     int written = us_socket_write(SSL, s, data, length, 0);
54     if (written != length) {
55         char *new_buffer = (char *)malloc(ctx->length + length - written);
56         memcpy(new_buffer, ctx->backpressure, ctx->length);
57         memcpy(new_buffer + ctx->length, data + written, length - written);
58         free(ctx->backpressure);
59         ctx->backpressure = new_buffer;
60         ctx->length += length - written;
61     }
62     return written;
63 }
64 
write_backpressure(int SSL,struct us_socket_t * s)65 void write_backpressure(int SSL, struct us_socket_t *s) {
66 
67     struct socket_context *ctx = (struct socket_context *)us_socket_ext(SSL, s);
68 
69     /* Continue writing out our backpressure */
70     int written = us_socket_write(SSL, s, ctx->backpressure, ctx->length, 0);
71     if (written != ctx->length) {
72         char *new_buffer = (char *)malloc(ctx->length - written);
73         memcpy(new_buffer, ctx->backpressure, ctx->length - written);
74         free(ctx->backpressure);
75         ctx->backpressure = new_buffer;
76         ctx->length -= written;
77     } else {
78         free(ctx->backpressure);
79         ctx->length = 0;
80     }
81 }
82 
on_server_socket_writable(struct us_socket_t * s)83 struct us_socket_t *on_server_socket_writable(struct us_socket_t *s) {
84     printf("on_server_socket_writable\n");
85 
86     write_backpressure(SSL, s);
87 
88     /* Peer is not boring */
89     us_socket_timeout(SSL, s, 30);
90 
91     return s;
92 }
93 
on_client_socket_writable(struct us_socket_t * s)94 struct us_socket_t *on_client_socket_writable(struct us_socket_t *s) {
95     printf("on_client_socket_writable\n");
96 
97     write_backpressure(SSL, s);
98 
99     /* Peer is not boring */
100     us_socket_timeout(SSL, s, 30);
101 
102     return s;
103 }
104 
on_server_socket_close(struct us_socket_t * s,int code,void * reason)105 struct us_socket_t *on_server_socket_close(struct us_socket_t *s, int code, void *reason) {
106     printf("on_server_socket_close\n");
107 
108     us_listen_socket_close(SSL, listen_socket);
109 
110     return s;
111 }
112 
on_client_socket_close(struct us_socket_t * s,int code,void * reason)113 struct us_socket_t *on_client_socket_close(struct us_socket_t *s, int code, void *reason) {
114 
115     printf("on_client_socket_close\n");
116 
117     return s;
118 }
119 
on_server_socket_end(struct us_socket_t * s)120 struct us_socket_t *on_server_socket_end(struct us_socket_t *s) {
121 
122     return us_socket_close(SSL, s, 0, NULL);
123 }
124 
on_client_socket_end(struct us_socket_t * s)125 struct us_socket_t *on_client_socket_end(struct us_socket_t *s) {
126 
127     return us_socket_close(SSL, s, 0, NULL);
128 }
129 
on_server_socket_data(struct us_socket_t * s,char * data,int length)130 struct us_socket_t *on_server_socket_data(struct us_socket_t *s, char *data, int length) {
131 
132     if (length == 0) {
133         printf("ERROR: Got data event with no data\n");
134         exit(-1);
135     }
136     /* Print the data we received */
137     printf("on_server_socket_data: received '%.*s'\n", length, data);
138 
139     server_received_data = true;
140 
141     write_buffered(SSL, s, server_msg, sizeof(server_msg));
142 
143     return s;
144 }
145 
on_client_socket_data(struct us_socket_t * s,char * data,int length)146 struct us_socket_t *on_client_socket_data(struct us_socket_t *s, char *data, int length) {
147 
148     if (length == 0) {
149         printf("ERROR: Got data event with no data\n");
150         exit(-1);
151     }
152     /* Print the data we received */
153     printf("on_client_socket_data: received '%.*s'\n", length, data);
154 
155     client_received_data = true;
156 
157     return us_socket_close(SSL, s, 0, NULL);
158 }
159 
on_server_socket_open(struct us_socket_t * s,int is_client,char * ip,int ip_length)160 struct us_socket_t *on_server_socket_open(struct us_socket_t *s, int is_client, char *ip, int ip_length) {
161 
162     printf("on_server_socket_open\n");
163     struct socket_context *ctx = (struct socket_context *)us_socket_ext(SSL, s);
164 
165     ctx->backpressure = 0;
166     ctx->length = 0;
167 
168     /* Start a timeout to close the socket if boring */
169     us_socket_timeout(SSL, s, 30);
170 
171     printf("Client connected\n");
172 
173     return s;
174 }
175 
on_client_socket_open(struct us_socket_t * s,int is_client,char * ip,int ip_length)176 struct us_socket_t *on_client_socket_open(struct us_socket_t *s, int is_client, char *ip, int ip_length) {
177 
178     printf("on_client_socket_open\n");
179 
180     struct socket_context *ctx = (struct socket_context *)us_socket_ext(SSL, s);
181 
182     ctx->backpressure = 0;
183     ctx->length = 0;
184 
185     write_buffered(SSL, s, client_msg, sizeof(client_msg));
186 
187     return s;
188 }
189 
on_client_socket_timeout(struct us_socket_t * s)190 struct us_socket_t *on_client_socket_timeout(struct us_socket_t *s) {
191     return s;
192 }
193 
on_server_socket_timeout(struct us_socket_t * s)194 struct us_socket_t *on_server_socket_timeout(struct us_socket_t *s) {
195     return s;
196 }
197 
expect_peer_verify(const char * test_name,bool expect_data_exchanged,struct us_socket_context_options_t server_options,struct us_socket_context_options_t client_options)198 int expect_peer_verify(const char *test_name, bool expect_data_exchanged,
199                      struct us_socket_context_options_t server_options,
200                      struct us_socket_context_options_t client_options) {
201 
202 
203     printf("----------------------------------------\n"
204            "[[ %s ]]\n"
205            "  server_key: %s\n"
206            "  server_crt: %s\n"
207            "  server_ca: %s\n"
208            "  client_crt: %s\n"
209            "  client_key: %s\n"
210            "  client_ca: %s\n\n",
211            test_name,
212            server_options.key_file_name,
213            server_options.cert_file_name,
214            server_options.ca_file_name,
215            client_options.key_file_name,
216            client_options.cert_file_name,
217            client_options.ca_file_name);
218 
219     srand(time(0));
220     server_received_data = false;
221     client_received_data = false;
222 
223     struct us_loop_t *loop = us_create_loop(0, on_wakeup, on_pre, on_post, 0);
224 
225     server_context = us_create_socket_context(SSL, loop, sizeof(struct socket_context), server_options);
226 
227     us_socket_context_on_open(SSL, server_context, on_server_socket_open);
228     us_socket_context_on_data(SSL, server_context, on_server_socket_data);
229     us_socket_context_on_writable(SSL, server_context, on_server_socket_writable);
230     us_socket_context_on_close(SSL, server_context, on_server_socket_close);
231     us_socket_context_on_timeout(SSL, server_context, on_server_socket_timeout);
232     us_socket_context_on_end(SSL, server_context, on_server_socket_end);
233 
234     port = 3000;
235     listen_socket = us_socket_context_listen(SSL, server_context, "127.0.0.1", port, 0, sizeof(struct socket_context));
236     while (!listen_socket) {
237         listen_socket = us_socket_context_listen(SSL, server_context, "127.0.0.1", ++port, 0, sizeof(struct socket_context));
238     }
239     printf("Server listening on 127.0.0.1:%d\n", port);
240 
241     client_context = us_create_socket_context(SSL, loop, sizeof(struct socket_context), client_options);
242     us_socket_context_on_open(SSL, client_context, on_client_socket_open);
243     us_socket_context_on_data(SSL, client_context, on_client_socket_data);
244     us_socket_context_on_writable(SSL, client_context, on_client_socket_writable);
245     us_socket_context_on_close(SSL, client_context, on_client_socket_close);
246     us_socket_context_on_timeout(SSL, client_context, on_client_socket_timeout);
247     us_socket_context_on_end(SSL, client_context, on_client_socket_end);
248 
249     us_socket_context_connect(SSL, client_context, "127.0.0.1", port, NULL, 0, sizeof(struct socket_context));
250     us_loop_run(loop);
251 
252     us_socket_context_free(SSL, server_context);
253     us_socket_context_free(SSL, client_context);
254     us_loop_free(loop);
255 
256     bool data_exchanged = server_received_data && client_received_data;
257     if (!!expect_data_exchanged != !!data_exchanged) {
258 
259         fprintf(stderr, "\n~ ERROR: expected data_echanged == %s, got %s\n\n",
260                 (expect_data_exchanged ? "true" : "false"),
261                 (data_exchanged ? "true" : "false"));
262         exit(1);
263     }
264 
265     printf("[[ OK ]]\n\n");
266     return 0;
267 }
268 
main()269 int main() {
270 
271     expect_peer_verify("trusted client ca", true,
272         (struct us_socket_context_options_t){
273             .key_file_name = ".certs/valid_server_key.pem",
274             .cert_file_name = ".certs/valid_server_crt.pem",
275             .ca_file_name = ".certs/valid_ca_crt.pem"
276         },
277         (struct us_socket_context_options_t){
278             .key_file_name = ".certs/valid_client_key.pem",
279             .cert_file_name = ".certs/valid_client_crt.pem",
280             .ca_file_name = ".certs/valid_ca_crt.pem"
281         });
282 
283 
284     expect_peer_verify("untrusted client ca", false,
285         (struct us_socket_context_options_t){
286             .key_file_name = ".certs/valid_server_key.pem",
287             .cert_file_name = ".certs/valid_server_crt.pem",
288             .ca_file_name = ".certs/valid_ca_crt.pem"
289         },
290         (struct us_socket_context_options_t){
291             .key_file_name = ".certs/invalid_client_key.pem",
292             .cert_file_name = ".certs/invalid_client_crt.pem",
293             .ca_file_name = ".certs/valid_ca_crt.pem"
294         });
295 
296     expect_peer_verify("trusted selfsigned client", true,
297         (struct us_socket_context_options_t){
298             .key_file_name = ".certs/valid_server_key.pem",
299             .cert_file_name = ".certs/valid_server_crt.pem",
300             .ca_file_name = ".certs/selfsigned_client_crt.pem"
301         },
302         (struct us_socket_context_options_t){
303             .key_file_name = ".certs/selfsigned_client_key.pem",
304             .cert_file_name = ".certs/selfsigned_client_crt.pem",
305             .ca_file_name = ".certs/valid_ca_crt.pem"
306         });
307 
308     expect_peer_verify("untrusted selfsigned client", false,
309         (struct us_socket_context_options_t){
310             .key_file_name = ".certs/valid_server_key.pem",
311             .cert_file_name = ".certs/valid_server_crt.pem",
312             .ca_file_name = ".certs/valid_ca_crt.pem"
313         },
314         (struct us_socket_context_options_t){
315             .key_file_name = ".certs/selfsigned_client_key.pem",
316             .cert_file_name = ".certs/selfsigned_client_crt.pem",
317             .ca_file_name = ".certs/valid_ca_crt.pem"
318         });
319 
320     expect_peer_verify("peer verify disabled", true,
321         (struct us_socket_context_options_t){
322             .key_file_name = ".certs/valid_server_key.pem",
323             .cert_file_name = ".certs/valid_server_crt.pem"
324         },
325         (struct us_socket_context_options_t){
326             .key_file_name = ".certs/valid_client_key.pem",
327             .cert_file_name = ".certs/valid_client_crt.pem"
328         });
329 
330 }
331