maph 1.0.0 High-Performance Memory-Mapped Key-Value Database with O(1) Lookups

Loading...
Searching...
No Matches
quic.c
Go to the documentation of this file.
1#ifdef LIBUS_USE_QUIC
2
3/* Todo: quic layer should not use bsd layer directly (sendmmsg) */
4#include "internal/networking/bsd.h"
5
6#include "quic.h"
7
8
9
10#include "lsquic.h"
11#include "lsquic_types.h"
12#include "lsxpack_header.h"
13
14/* Todo: remove these */
15#ifndef _WIN32
16#include <netinet/in.h>
17#include <errno.h>
18#endif
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24 void leave_all();
25
26/*
27 struct sockaddr_in client_addr = {
28 AF_INET,
29 1,
30 1
31};
32
33 struct sockaddr_in server_addr = {
34 AF_INET,
35 2,
36 2
37};*/
38
39 // used in process_quic
40 lsquic_engine_t *global_engine;
41 lsquic_engine_t *global_client_engine;
42
43/* Socket context */
44 struct us_quic_socket_context_s {
45
46 struct us_udp_packet_buffer_t *recv_buf;
47 //struct us_udp_packet_buffer_t *send_buf;
48 int outgoing_packets;
49
50 //struct us_udp_socket_t *udp_socket;
51 struct us_loop_t *loop;
52 lsquic_engine_t *engine;
53 lsquic_engine_t *client_engine;
54
55 // we store the options the context was created with here
56 us_quic_socket_context_options_t options;
57
58 void(*on_stream_data)(us_quic_stream_t *s, char *data, int length);
59 void(*on_stream_end)(us_quic_stream_t *s);
60 void(*on_stream_headers)(us_quic_stream_t *s);
61 void(*on_stream_open)(us_quic_stream_t *s, int is_client);
62 void(*on_stream_close)(us_quic_stream_t *s);
63 void(*on_stream_writable)(us_quic_stream_t *s);
64 void(*on_open)(us_quic_socket_t *s, int is_client);
65 void(*on_close)(us_quic_socket_t *s);
66};
67
68/* Setters */
69 void us_quic_socket_context_on_stream_data(us_quic_socket_context_t *context, void(*on_stream_data)(us_quic_stream_t *s, char *data, int length)) {
70 context->on_stream_data = on_stream_data;
71}
72 void us_quic_socket_context_on_stream_end(us_quic_socket_context_t *context, void(*on_stream_end)(us_quic_stream_t *s)) {
73 context->on_stream_end = on_stream_end;
74}
75 void us_quic_socket_context_on_stream_headers(us_quic_socket_context_t *context, void(*on_stream_headers)(us_quic_stream_t *s)) {
76 context->on_stream_headers = on_stream_headers;
77}
78 void us_quic_socket_context_on_stream_open(us_quic_socket_context_t *context, void(*on_stream_open)(us_quic_stream_t *s, int is_client)) {
79 context->on_stream_open = on_stream_open;
80}
81 void us_quic_socket_context_on_stream_close(us_quic_socket_context_t *context, void(*on_stream_close)(us_quic_stream_t *s)) {
82 context->on_stream_close = on_stream_close;
83}
84 void us_quic_socket_context_on_open(us_quic_socket_context_t *context, void(*on_open)(us_quic_socket_t *s, int is_client)) {
85 context->on_open = on_open;
86}
87 void us_quic_socket_context_on_close(us_quic_socket_context_t *context, void(*on_close)(us_quic_socket_t *s)) {
88 context->on_close = on_close;
89}
90 void us_quic_socket_context_on_stream_writable(us_quic_socket_context_t *context, void(*on_stream_writable)(us_quic_stream_t *s)) {
91 context->on_stream_writable = on_stream_writable;
92}
93
94/* UDP handlers */
95 void on_udp_socket_writable(struct us_udp_socket_t *s) {
96 /* Need context from socket here */
97 us_quic_socket_context_t *context = us_udp_socket_user(s);
98
99 /* We just continue now */
100 lsquic_engine_send_unsent_packets(context->engine);
101}
102
103// we need two differetn handlers to know to put it in client or servcer context
104 void on_udp_socket_data_client(struct us_udp_socket_t *s, struct us_udp_packet_buffer_t *buf, int packets) {
105
106 int fd = us_poll_fd((struct us_poll_t *) s);
107 //printf("Reading on fd: %d\n", fd);
108
109 //printf("UDP (client) socket got data: %p\n", s);
110
111 /* We need to lookup the context from the udp socket */
112 //us_udpus_udp_socket_context(s);
113 // do we have udp socket contexts? or do we just have user data?
114
115 us_quic_socket_context_t *context = us_udp_socket_user(s);
116
117 /* We just shove it to lsquic */
118 for (int i = 0; i < packets; i++) {
119 char *payload = us_udp_packet_buffer_payload(buf, i);
120 int length = us_udp_packet_buffer_payload_length(buf, i);
121 int ecn = us_udp_packet_buffer_ecn(buf, i);
122 void *peer_addr = us_udp_packet_buffer_peer(buf, i);
123
124 //printf("Reading UDP of size %d\n", length);
125
126 char ip[16];
127 int ip_length = us_udp_packet_buffer_local_ip(buf, i, ip);
128 if (!ip_length) {
129 printf("We got no ip on received packet!\n");
130 exit(0);
131 }
132
133 //printf("Our received destination IP length is: %d\n", ip_length);
134
135 int port = us_udp_socket_bound_port(s);
136 //printf("We received packet on port: %d\n", port);
137
138 /* We build our address based on what the dest addr is */
139 struct sockaddr_storage local_addr = {0};
140 if (ip_length == 16) {
141 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *) &local_addr;
142
143 ipv6->sin6_family = AF_INET6;
144 ipv6->sin6_port = ntohs(port);
145 memcpy(ipv6->sin6_addr.s6_addr, ip, 16);
146 } else {
147 struct sockaddr_in *ipv4 = (struct sockaddr_in *) &local_addr;
148
149 ipv4->sin_family = AF_INET;
150 ipv4->sin_port = ntohs(port);
151 memcpy(&ipv4->sin_addr.s_addr, ip, 4);
152 }
153
154
155 int ret = lsquic_engine_packet_in(context->client_engine, payload, length, (struct sockaddr *) &local_addr, peer_addr, (void *) s, 0);
156 //printf("Engine returned: %d\n", ret);
157
158
159 }
160
161 lsquic_engine_process_conns(context->client_engine);
162
163}
164
165 void on_udp_socket_data(struct us_udp_socket_t *s, struct us_udp_packet_buffer_t *buf, int packets) {
166
167
168 //printf("UDP socket got data: %p\n", s);
169
170 /* We need to lookup the context from the udp socket */
171 //us_udpus_udp_socket_context(s);
172 // do we have udp socket contexts? or do we just have user data?
173
174 us_quic_socket_context_t *context = us_udp_socket_user(s);
175
176 // process conns now? to accept new connections?
177 lsquic_engine_process_conns(context->engine);
178
179 /* We just shove it to lsquic */
180 for (int i = 0; i < packets; i++) {
181 char *payload = us_udp_packet_buffer_payload(buf, i);
182 int length = us_udp_packet_buffer_payload_length(buf, i);
183 int ecn = us_udp_packet_buffer_ecn(buf, i);
184 void *peer_addr = us_udp_packet_buffer_peer(buf, i);
185
186 //printf("Reading UDP of size %d\n", length);
187
188 char ip[16];
189 int ip_length = us_udp_packet_buffer_local_ip(buf, i, ip);
190 if (!ip_length) {
191 printf("We got no ip on received packet!\n");
192 exit(0);
193 }
194
195 //printf("Our received destination IP length is: %d\n", ip_length);
196
197 int port = us_udp_socket_bound_port(s);
198 //printf("We received packet on port: %d\n", port);
199
200 /* We build our address based on what the dest addr is */
201 struct sockaddr_storage local_addr = {0};
202 if (ip_length == 16) {
203 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *) &local_addr;
204
205 ipv6->sin6_family = AF_INET6;
206 ipv6->sin6_port = ntohs(port);
207 memcpy(ipv6->sin6_addr.s6_addr, ip, 16);
208 } else {
209
210 struct sockaddr_in *ipv4 = (struct sockaddr_in *) &local_addr;
211
212 ipv4->sin_family = AF_INET;
213 ipv4->sin_port = ntohs(port);
214 memcpy(&ipv4->sin_addr.s_addr, ip, 4);
215 }
216
217
218 int ret = lsquic_engine_packet_in(context->engine, payload, length, (struct sockaddr *) &local_addr, peer_addr, (void *) s, 0);
219 //printf("Engine returned: %d\n", ret);
220
221
222 }
223
224 lsquic_engine_process_conns(context->engine);
225
226}
227
228/* Let's use this on Windows and macOS where it is not defined (todo: put in bsd.h) */
229#ifndef UIO_MAXIOV
230#define UIO_MAXIOV 1024
231
232#ifndef _WIN32
233 struct mmsghdr {
234 struct msghdr msg_hdr; /* Message header */
235 unsigned int msg_len; /* Number of bytes transmitted */
236};
237#endif
238#endif
239
240/* Server and client packet out is identical */
241 int send_packets_out(void *ctx, const struct lsquic_out_spec *specs, unsigned n_specs) {
242#ifndef _WIN32
243 us_quic_socket_context_t *context = ctx;
244
245 /* A run is at most UIO_MAXIOV datagrams long */
246 struct mmsghdr hdrs[UIO_MAXIOV];
247 int run_length = 0;
248
249 /* We assume that thiss whole cb will never be called with 0 specs */
250 struct us_udp_socket_t *last_socket = (struct us_udp_socket_t *) specs[0].peer_ctx;
251
252 int sent = 0;
253 for (int i = 0; i < n_specs; i++) {
254 /* Send this run if we need to */
255 if (run_length == UIO_MAXIOV || specs[i].peer_ctx != last_socket) {
256 int ret = bsd_sendmmsg(us_poll_fd((struct us_poll_t *) last_socket), hdrs, run_length, 0);
257 if (ret != run_length) {
258 if (ret == -1) {
259 printf("unhandled udp backpressure!\n");
260 return sent;
261 } else {
262 printf("unhandled udp backpressure!\n");
263 errno = EAGAIN;
264 return sent + ret;
265 }
266 }
267 sent += ret;
268 run_length = 0;
269 last_socket = specs[i].peer_ctx;
270 //printf("different socket breask run!\n");
271 }
272
273 /* Continue existing run or start a new one */
274 //memset(&hdrs[i].msg_hdr, 0, sizeof(hdrs[i].msg_hdr));
275 memset(&hdrs[run_length], 0, sizeof(hdrs[run_length]));
276
277 hdrs[run_length].msg_hdr.msg_name = (void *) specs[i].dest_sa;
278 hdrs[run_length].msg_hdr.msg_namelen = (AF_INET == specs[i].dest_sa->sa_family ?
279 sizeof(struct sockaddr_in) :
280 sizeof(struct sockaddr_in6)),
281 hdrs[run_length].msg_hdr.msg_iov = specs[i].iov;
282 hdrs[run_length].msg_hdr.msg_iovlen = specs[i].iovlen;
283 hdrs[run_length].msg_hdr.msg_flags = 0;
284
285 run_length++;
286 }
287
288 /* Send last run */
289 if (run_length) {
290 int ret = bsd_sendmmsg(us_poll_fd((struct us_poll_t *) last_socket), hdrs, run_length, 0);
291 if (ret == -1) {
292 printf("backpressure! A\n");
293 return sent;
294 }
295 if (sent + ret != n_specs) {
296 printf("backpressure! B\n");
297 printf("errno is: %d\n", errno);
298 errno = EAGAIN;
299 }
300 //printf("Returning %d of %d\n", sent + ret, n_specs);
301 return sent + ret;
302 }
303
304 //printf("Returning %d\n", n_specs);
305
306#endif
307
308 return n_specs;
309}
310
311lsquic_conn_ctx_t *on_new_conn(void *stream_if_ctx, lsquic_conn_t *c) {
312 us_quic_socket_context_t *context = stream_if_ctx;
313
314 printf("Context is: %p\n", context);
315
316 /* We need to create some kind of socket here */
317
318 int is_client = 0;
319 if (lsquic_conn_get_engine(c) == context->client_engine) {
320 is_client = 1;
321 }
322
323 context->on_open((us_quic_socket_t *) c, is_client);
324
325 return (lsquic_conn_ctx_t *) context;
326}
327
328 void us_quic_socket_create_stream(us_quic_socket_t *s, int ext_size) {
329 lsquic_conn_make_stream((lsquic_conn_t *) s);
330
331 // here we need to allocate and attach the user data
332
333}
334
335 void on_conn_closed(lsquic_conn_t *c) {
336 us_quic_socket_context_t *context = (us_quic_socket_context_t *) lsquic_conn_get_ctx(c);
337
338 printf("on_conn_closed!\n");
339
340 context->on_close((us_quic_socket_t *) c);
341}
342
343lsquic_stream_ctx_t *on_new_stream(void *stream_if_ctx, lsquic_stream_t *s) {
344
345 /* In true usockets style we always want read */
346 lsquic_stream_wantread(s, 1);
347
348 us_quic_socket_context_t *context = stream_if_ctx;
349
350 // the conn's ctx should point at the udp socket and the socket context
351 // the ext size of streams and conn's are set by the listen/connect calls, which
352 // are the calls that create the UDP socket so we need conn to point to the UDP socket
353 // to get that ext_size set in listen/connect calls, back here.
354 // todo: hardcoded for now
355
356 int ext_size = 256;
357
358 void *ext = malloc(ext_size);
359 // yes hello
360 strcpy(ext, "Hello I am ext!");
361
362 int is_client = 0;
363 if (lsquic_conn_get_engine(lsquic_stream_conn(s)) == context->client_engine) {
364 is_client = 1;
365 }
366
367 // luckily we can set the ext before we return
368 lsquic_stream_set_ctx(s, ext);
369 context->on_stream_open((us_quic_stream_t *) s, is_client);
370
371 return ext;
372}
373
374//#define V(v) (v), strlen(v)
375
376// header bug is really just an offset buffer - perfect for per context!
377// could even use cork buffer or similar
378 struct header_buf
379{
380 unsigned off;
381 char buf[UINT16_MAX];
382};
383
384 int
385header_set_ptr (struct lsxpack_header *hdr, struct header_buf *header_buf,
386 const char *name, size_t name_len,
387 const char *val, size_t val_len)
388{
389 if (header_buf->off + name_len + val_len <= sizeof(header_buf->buf))
390 {
391 memcpy(header_buf->buf + header_buf->off, name, name_len);
392 memcpy(header_buf->buf + header_buf->off + name_len, val, val_len);
393 lsxpack_header_set_offset2(hdr, header_buf->buf + header_buf->off,
394 0, name_len, name_len, val_len);
395 header_buf->off += name_len + val_len;
396 return 0;
397 }
398 else
399 return -1;
400}
401
402/* Static storage should be per context or really per loop */
403 struct header_buf hbuf;
404 struct lsxpack_header headers_arr[10];
405
406 void us_quic_socket_context_set_header(us_quic_socket_context_t *context, int index, const char *key, int key_length, const char *value, int value_length) {
407 if (header_set_ptr(&headers_arr[index], &hbuf, key, key_length, value, value_length) != 0) {
408 printf("CANNOT FORMAT HEADER!\n");
409 exit(0);
410 }
411}
412
413 void us_quic_socket_context_send_headers(us_quic_socket_context_t *context, us_quic_stream_t *s, int num, int has_body) {
414
415 lsquic_http_headers_t headers = {
416 .count = num,
417 .headers = headers_arr,
418 };
419 // last here is whether this is eof or not (has body)
420 if (lsquic_stream_send_headers((lsquic_stream_t *) s, &headers, has_body ? 0 : 1)) {// pass 0 if data
421 printf("CANNOT SEND HEADERS!\n");
422 exit(0);
423 }
424
425 /* Reset header offset */
426 hbuf.off = 0;
427}
428
429 int us_quic_stream_is_client(us_quic_stream_t *s) {
430 us_quic_socket_context_t *context = (us_quic_socket_context_t *) lsquic_conn_get_ctx(lsquic_stream_conn((lsquic_stream_t *) s));
431
432 int is_client = 0;
433 if (lsquic_conn_get_engine(lsquic_stream_conn((lsquic_stream_t *) s)) == context->client_engine) {
434 is_client = 1;
435 }
436 return is_client;
437}
438
439us_quic_socket_t *us_quic_stream_socket(us_quic_stream_t *s) {
440 return (us_quic_socket_t *) lsquic_stream_conn((lsquic_stream_t *) s);
441}
442
443//#include <errno.h>
444
445
446// only for servers?
447 static void on_read(lsquic_stream_t *s, lsquic_stream_ctx_t *h) {
448
449 /* The user data of the connection owning the stream, points to the socket context */
450 us_quic_socket_context_t *context = (us_quic_socket_context_t *) lsquic_conn_get_ctx(lsquic_stream_conn(s));
451
452 /* This object is (and must be) fetched from a stream by
453 * calling lsquic_stream_get_hset() before the stream can be read. */
454 /* This call must precede calls to lsquic_stream_read(), lsquic_stream_readv(), and lsquic_stream_readf(). */
455 void *header_set = lsquic_stream_get_hset(s);
456 if (header_set) {
457 context->on_stream_headers((us_quic_stream_t *) s);
458 // header management is obviously broken and needs to be per-stream
459 leave_all();
460 }
461
462 // all of this logic should be moved to uws and WE here should only hand over the data
463
464 char temp[4096] = {0};
465 int nr = lsquic_stream_read(s, temp, 4096);
466
467 // emit on_end when we receive fin, regardless of whether we emitted data yet
468 if (nr == 0) {
469 // any time we read EOF we stop reading
470 lsquic_stream_wantread(s, 0);
471 context->on_stream_end((us_quic_stream_t *) s);
472 } else if (nr == -1) {
473 if (errno != EWOULDBLOCK) {
474 // error handling should not be needed if we use lsquic correctly
475 printf("UNHANDLED ON_READ ERROR\n");
476 exit(0);
477 }
478 // if we for some reason could not read even though we were told to read, we just ignore it
479 // this should not really happen but whatever
480 } else {
481 // otherwise if we have data, then emit it
482 context->on_stream_data((us_quic_stream_t *) s, temp, nr);
483 }
484
485 // that's it
486 return;
487
488 //lsquic_stream_readf
489
490 printf("read returned: %d\n", nr);
491
492 // we will get 9, ebadf if we read from a closed stream
493 if (nr == -1) {
494 printf("Error in reading! errno is: %d\n", errno);
495 if (errno != EWOULDBLOCK) {
496 printf("Errno is not EWOULDBLOCK\n");
497 } else {
498 printf("Errno is would block, fine!\n");
499 }
500 exit(0);
501 return;
502 }
503
504 /* We have reached EOF */
505 if (nr == 0) {
506
507 /* Are we polling for writable (todo: make this check faster)? */
508 if (lsquic_stream_wantwrite(s, 1)) {
509
510 // we happened to be polling for writable so leave the connection open until on_write eventually closes it
511 printf("we are polling for write, so leaving the stream open!\n");
512
513 // stop reading though!
514 lsquic_stream_wantread(s, 0); // I hope this is fine? half open?
515
516 } else {
517 // we weren't polling for writable so reset it to old value
518 lsquic_stream_wantwrite(s, 0);
519
520 // I guess we can close it since we have called shutdown before this so data should flow out
521 lsquic_stream_close(s);
522 }
523
524 // reached the EOF
525 //lsquic_stream_close(s);
526 //lsquic_stream_wantread(s, 0);
527 return;
528 }
529
530 //printf("read: %d\n", nr);
531
532 //printf("%s\n", temp);
533
534 // why do we get tons of zero reads?
535 // maybe it doesn't matter, if we can parse this input then we are fine
536 //lsquic_stream_wantread(s, 0);
537 //lsquic_stream_wantwrite(s, 1);
538
539 printf("on_stream_data: %d\n", nr);
540 context->on_stream_data((us_quic_stream_t *) s, temp, nr);
541}
542
543 int us_quic_stream_write(us_quic_stream_t *s, char *data, int length) {
544 lsquic_stream_t *stream = (lsquic_stream_t *) s;
545 int ret = lsquic_stream_write((lsquic_stream_t *) s, data, length);
546 // just like otherwise, we automatically poll for writable when failed
547 if (ret != length) {
548 lsquic_stream_wantwrite((lsquic_stream_t *) s, 1);
549 } else {
550 lsquic_stream_wantwrite((lsquic_stream_t *) s, 0);
551 }
552 return ret;
553}
554
555 static void on_write (lsquic_stream_t *s, lsquic_stream_ctx_t *h) {
556
557 us_quic_socket_context_t *context = (us_quic_socket_context_t *) lsquic_conn_get_ctx(lsquic_stream_conn(s));
558
559 context->on_stream_writable((us_quic_stream_t *) s);
560
561 // here we might want to check if the user did write to failure or not, and if the user did not write, stop polling for writable
562 // i think that is what we do for http1
563}
564
565 static void on_stream_close (lsquic_stream_t *s, lsquic_stream_ctx_t *h) {
566 //printf("STREAM CLOSED!\n");
567}
568
569#include "openssl/ssl.h"
570
571 static char s_alpn[0x100];
572
573 int add_alpn (const char *alpn)
574{
575 size_t alpn_len, all_len;
576
577 alpn_len = strlen(alpn);
578 if (alpn_len > 255)
579 return -1;
580
581 all_len = strlen(s_alpn);
582 if (all_len + 1 + alpn_len + 1 > sizeof(s_alpn))
583 return -1;
584
585 s_alpn[all_len] = alpn_len;
586 memcpy(&s_alpn[all_len + 1], alpn, alpn_len);
587 s_alpn[all_len + 1 + alpn_len] = '\0';
588 return 0;
589}
590
591 static int select_alpn(SSL *ssl, const unsigned char **out, unsigned char *outlen,
592 const unsigned char *in, unsigned int inlen, void *arg) {
593 int r;
594
595 printf("select_alpn\n");
596
597 r = SSL_select_next_proto((unsigned char **) out, outlen, in, inlen,
598 (unsigned char *) s_alpn, strlen(s_alpn));
599 if (r == OPENSSL_NPN_NEGOTIATED) {
600 printf("OPENSSL_NPN_NEGOTIATED\n");
601 return SSL_TLSEXT_ERR_OK;
602 }
603 else
604 {
605 printf("no supported protocol can be selected!\n");
606 //LSQ_WARN("no supported protocol can be selected from %.*s",
607 //(int) inlen, (char *) in);
608 return SSL_TLSEXT_ERR_ALERT_FATAL;
609 }
610}
611
612SSL_CTX *old_ctx;
613
614 int server_name_cb(SSL *s, int *al, void *arg) {
615 printf("yolo SNI server_name_cb\n");
616
617 SSL_set_SSL_CTX(s, old_ctx);
618
619 printf("existing name is: %s\n", SSL_get_servername(s, TLSEXT_NAMETYPE_host_name));
620
621 if (!SSL_get_servername(s, TLSEXT_NAMETYPE_host_name)) {
622 SSL_set_tlsext_host_name(s, "YOLO NAME!");
623 printf("set name is: %s\n", SSL_get_servername(s, TLSEXT_NAMETYPE_host_name));
624 }
625
626
627 return SSL_TLSEXT_ERR_OK;
628}
629
630// this one is required for servers
631 struct ssl_ctx_st *get_ssl_ctx(void *peer_ctx, const struct sockaddr *local) {
632 printf("getting ssl ctx now, peer_ctx: %p\n", peer_ctx);
633
634 // peer_ctx point to the us_udp_socket_t that passed the UDP packet in via
635 // lsquic_engine_packet_in (it got passed as peer_ctx)
636 // we want the per-context ssl cert from this udp socket
637 struct us_udp_socket_t *udp_socket = (struct us_udp_socket_t *) peer_ctx;
638
639 // the udp socket of a server points to the context
640 struct us_quic_socket_context_s *context = us_udp_socket_user(udp_socket);
641
642 if (old_ctx) {
643 return old_ctx;
644 }
645
646 // peer_ctx should be the options struct!
647 us_quic_socket_context_options_t *options = &context->options;
648
649
650 SSL_CTX *ctx = SSL_CTX_new(TLS_method());
651
652 old_ctx = ctx;
653
654 SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
655 SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION);
656
657 //SSL_CTX_set_default_verify_paths(ctx);
658
659 // probably cannot use this when http is in use?
660 // alpn is needed
661 SSL_CTX_set_alpn_select_cb(ctx, select_alpn, NULL);
662
663 // sni is needed
664 SSL_CTX_set_tlsext_servername_callback(ctx, server_name_cb);
665 //long SSL_CTX_set_tlsext_servername_arg(SSL_CTX *ctx, void *arg);
666
667 printf("Key: %s\n", options->key_file_name);
668 printf("Cert: %s\n", options->cert_file_name);
669
670 int a = SSL_CTX_use_certificate_chain_file(ctx, options->cert_file_name);
671 int b = SSL_CTX_use_PrivateKey_file(ctx, options->key_file_name, SSL_FILETYPE_PEM);
672
673 printf("loaded cert and key? %d, %d\n", a, b);
674
675 return ctx;
676}
677
678SSL_CTX *sni_lookup(void *lsquic_cert_lookup_ctx, const struct sockaddr *local, const char *sni) {
679 printf("simply returning old ctx in sni\n");
680 return old_ctx;
681}
682
683 int log_buf_cb(void *logger_ctx, const char *buf, size_t len) {
684 printf("%.*s\n", (int) len, buf);
685 return 0;
686}
687
688 int us_quic_stream_shutdown_read(us_quic_stream_t *s) {
689 lsquic_stream_t *stream = (lsquic_stream_t *) s;
690
691 int ret = lsquic_stream_shutdown((lsquic_stream_t *) s, 0);
692 if (ret != 0) {
693 printf("cannot shutdown stream!\n");
694 exit(0);
695 }
696
697 return 0;
698}
699
700 void *us_quic_stream_ext(us_quic_stream_t *s) {
701 return lsquic_stream_get_ctx((lsquic_stream_t *) s);
702}
703
704 void us_quic_stream_close(us_quic_stream_t *s) {
705 lsquic_stream_t *stream = (lsquic_stream_t *) s;
706
707 int ret = lsquic_stream_close((lsquic_stream_t *) s);
708 if (ret != 0) {
709 printf("cannot close stream!\n");
710 exit(0);
711 }
712
713 return;
714}
715
716 int us_quic_stream_shutdown(us_quic_stream_t *s) {
717 lsquic_stream_t *stream = (lsquic_stream_t *) s;
718
719 int ret = lsquic_stream_shutdown((lsquic_stream_t *) s, 1);
720 if (ret != 0) {
721 printf("cannot shutdown stream!\n");
722 exit(0);
723 }
724
725 return 0;
726}
727
728// header of header set
729 struct header_set_hd {
730 int offset;
731};
732
733// let's just store last header set here
734 struct header_set_hd *last_hset;
735
736// just a shitty marker for now
737 struct processed_header {
738 void *name, *value;
739 int name_length, value_length;
740};
741
742 int us_quic_socket_context_get_header(us_quic_socket_context_t *context, int index, char **name, int *name_length, char **value, int *value_length) {
743
744 if (index < last_hset->offset) {
745
746 struct processed_header *pd = (struct processed_header *) (last_hset + 1);
747
748 pd = pd + index;
749
750 *name = pd->name;
751 *value = pd->value;
752 *value_length = pd->value_length;
753 *name_length = pd->name_length;
754
755 return 1;
756 }
757
758 return 0;
759
760}
761
762 char pool[1000][4096];
763 int pool_top = 0;
764
765 void *take() {
766 if (pool_top == 1000) {
767 printf("out of memory\n");
768 exit(0);
769 }
770 return pool[pool_top++];
771}
772
773 void leave_all() {
774 pool_top = 0;
775}
776
777
778// header set callbacks
779 void *hsi_create_header_set(void *hsi_ctx, lsquic_stream_t *stream, int is_push_promise) {
780
781 //printf("hsi_create_header_set\n");
782
783 void *hset = take();//malloc(1024);
784 memset(hset, 0, sizeof(struct header_set_hd));
785
786 // hsi_ctx is set in engine creation below
787
788 // I guess we just return whatever here, what we return here is gettable via the stream
789
790 // gettable via lsquic_stream_get_hset
791
792 // return user defined header set
793
794 return hset;
795}
796
797 void hsi_discard_header_set(void *hdr_set) {
798 // this is pretty much the destructor of above constructor
799
800 printf("hsi_discard_header!\n");
801}
802
803// one header set allocates one 8kb buffer from a linked list of available buffers
804
805
806// 8kb of preallocated heap for headers
807 char header_decode_heap[1024 * 8];
808 int header_decode_heap_offset = 0;
809
810 struct lsxpack_header *hsi_prepare_decode(void *hdr_set, struct lsxpack_header *hdr, size_t space) {
811
812 //printf("hsi_prepare_decode\n");
813
814 if (!hdr) {
815 char *mem = take();
816 hdr = (struct lsxpack_header *) mem;//malloc(sizeof(struct lsxpack_header));
817 memset(hdr, 0, sizeof(struct lsxpack_header));
818 hdr->buf = mem + sizeof(struct lsxpack_header);//take();//malloc(space);
819 lsxpack_header_prepare_decode(hdr, hdr->buf, 0, space);
820 } else {
821
822 if (space > 4096 - sizeof(struct lsxpack_header)) {
823 printf("not hanlded!\n");
824 exit(0);
825 }
826
827 hdr->val_len = space;
828 //hdr->buf = realloc(hdr->buf, space);
829 }
830
831 return hdr;
832}
833
834 int hsi_process_header(void *hdr_set, struct lsxpack_header *hdr) {
835
836 // I guess this is the emitting of the header to app space
837
838 //printf("hsi_process_header: %p\n", hdr);
839
840 struct header_set_hd *hd = hdr_set;
841 struct processed_header *proc_hdr = (struct processed_header *) (hd + 1);
842
843 if (!hdr) {
844 //printf("end of headers!\n");
845
846 last_hset = hd;
847
848 // mark end, well we can also just read the offset!
849 //memset(&proc_hdr[hd->offset], 0, sizeof(struct processed_header));
850
851 return 0;
852 }
853
854 /*if (hdr->hpack_index) {
855 printf("header has hpack index: %d\n", hdr->hpack_index);
856 }
857
858 if (hdr->qpack_index) {
859 printf("header has qpack index: %d\n", hdr->qpack_index);
860 }*/
861
862 proc_hdr[hd->offset].value = &hdr->buf[hdr->val_offset];
863 proc_hdr[hd->offset].name = &hdr->buf[hdr->name_offset];
864 proc_hdr[hd->offset].value_length = hdr->val_len;
865 proc_hdr[hd->offset].name_length = hdr->name_len;
866
867 //printf("header %.*s = %.*s\n", hdr->name_len, &hdr->buf[hdr->name_offset], hdr->val_len, &hdr->buf[hdr->val_offset]);
868
869 hd->offset++;
870
871 return 0;
872}
873
874//extern us_quic_socket_context_t *context;
875
876 void timer_cb(struct us_timer_t *t) {
877 //printf("Processing conns from timer\n");
878 lsquic_engine_process_conns(global_engine);
879 lsquic_engine_process_conns(global_client_engine);
880
881 // these are handled by this timer, should be polling for udp writable
882 lsquic_engine_send_unsent_packets(global_engine);
883 lsquic_engine_send_unsent_packets(global_client_engine);
884}
885
886// lsquic_conn
887us_quic_socket_context_t *us_quic_socket_context(us_quic_socket_t *s) {
888 return (us_quic_socket_context_t *) lsquic_conn_get_ctx((lsquic_conn_t *) s);
889}
890
891 void *us_quic_socket_context_ext(us_quic_socket_context_t *context) {
892 return context + 1;
893}
894
895// this will be for both client and server, but will be only for either h3 or raw quic
896us_quic_socket_context_t *us_create_quic_socket_context(struct us_loop_t *loop, us_quic_socket_context_options_t options, int ext_size) {
897
898
899 printf("Creating socket context with ssl: %s\n", options.key_file_name);
900
901 // every _listen_ call creates a new udp socket that feeds inputs to the engine in the context
902 // every context has its own send buffer and udp send socket (not bound to any port or ip?)
903
904 // or just make it so that once you listen, it will listen on that port for input, and the context will use
905 // the first udp socket for output as it doesn't matter which one is used
906
907 /* Holds all callbacks */
908 us_quic_socket_context_t *context = malloc(sizeof(struct us_quic_socket_context_s) + ext_size);
909
910 // the option is put on the socket context
911 context->options = options;
912
913 context->loop = loop;
914 //context->udp_socket = 0;
915
916 /* Allocate per thread, UDP packet buffers */
917 context->recv_buf = us_create_udp_packet_buffer();
918 //context->send_buf = us_create_udp_packet_buffer();
919
920 /* Init lsquic engine */
921 if (0 != lsquic_global_init(LSQUIC_GLOBAL_CLIENT|LSQUIC_GLOBAL_SERVER)) {
922 exit(EXIT_FAILURE);
923 }
924
925 static struct lsquic_stream_if stream_callbacks = {
926 .on_close = on_stream_close,
927 .on_conn_closed = on_conn_closed,
928 .on_write = on_write,
929 .on_read = on_read,
930 .on_new_stream = on_new_stream,
931 .on_new_conn = on_new_conn
932 };
933
934 //memset(&stream_callbacks, 13, sizeof(struct lsquic_stream_if));
935
936 static struct lsquic_hset_if hset_if = {
937 .hsi_discard_header_set = hsi_discard_header_set,
938 .hsi_create_header_set = hsi_create_header_set,
939 .hsi_prepare_decode = hsi_prepare_decode,
940 .hsi_process_header = hsi_process_header
941 };
942
943
944 add_alpn("h3");
945
946 struct lsquic_engine_api engine_api = {
947 .ea_packets_out = send_packets_out,
948 .ea_packets_out_ctx = (void *) context, /* For example */
949 .ea_stream_if = &stream_callbacks,
950 .ea_stream_if_ctx = context,
951
952 .ea_get_ssl_ctx = get_ssl_ctx,
953
954 // lookup certificate
955 .ea_lookup_cert = sni_lookup,
956 .ea_cert_lu_ctx = 0,
957
958 // these are zero anyways
959 .ea_hsi_ctx = 0,
960 .ea_hsi_if = &hset_if,
961 };
962
964
965 static struct lsquic_logger_if logger = {
966 .log_buf = log_buf_cb,
967 };
968
969
970
971 //lsquic_logger_init(&logger, 0, LLTS_NONE);
972
973 /* Create an engine in server mode with HTTP behavior: */
974 context->engine = lsquic_engine_new(LSENG_SERVER | LSENG_HTTP, &engine_api);
975
976 struct lsquic_engine_api engine_api_client = {
977 .ea_packets_out = send_packets_out,
978 .ea_packets_out_ctx = (void *) context, /* For example */
979 .ea_stream_if = &stream_callbacks,
980 .ea_stream_if_ctx = context,
981
982 //.ea_get_ssl_ctx = get_ssl_ctx, // for client?
983
984 // lookup certificate
985 //.ea_lookup_cert = sni_lookup, // for client?
986 //.ea_cert_lu_ctx = 13, // for client?
987
988 // these are zero anyways
989 .ea_hsi_ctx = 0,
990 .ea_hsi_if = &hset_if,
991 };
992
993 context->client_engine = lsquic_engine_new(LSENG_HTTP, &engine_api_client);
994
995 printf("Engine: %p\n", context->engine);
996 printf("Client Engine: %p\n", context->client_engine);
997
998 // start a timer to handle connections
999 struct us_timer_t *delayTimer = us_create_timer(loop, 0, 0);
1000 us_timer_set(delayTimer, timer_cb, 50, 50);
1001
1002 // used by process_quic
1003 global_engine = context->engine;
1004 global_client_engine = context->client_engine;
1005
1006 return context;
1007}
1008
1009us_quic_listen_socket_t *us_quic_socket_context_listen(us_quic_socket_context_t *context, const char *host, int port, int ext_size) {
1010 /* We literally do create a listen socket */
1011 return (us_quic_listen_socket_t *) us_create_udp_socket(context->loop, /*context->recv_buf*/ NULL, on_udp_socket_data, on_udp_socket_writable, host, port, context);
1012 //return NULL;
1013}
1014
1015/* A client connection is its own UDP socket, while a server connection makes use of the shared listen UDP socket */
1016us_quic_socket_t *us_quic_socket_context_connect(us_quic_socket_context_t *context, const char *host, int port, int ext_size) {
1017 printf("Connecting..\n");
1018
1019
1020 // localhost 9004 ipv4
1021 struct sockaddr_storage storage = {0};
1022 // struct sockaddr_in *addr = (struct sockaddr_in *) &storage;
1023 // addr->sin_addr.s_addr = 16777343;
1024 // addr->sin_port = htons(9004);
1025 // addr->sin_family = AF_INET;
1026
1027 struct sockaddr_in6 *addr = (struct sockaddr_in6 *) &storage;
1028 addr->sin6_addr.s6_addr[15] = 1;
1029 addr->sin6_port = htons(9004);
1030 addr->sin6_family = AF_INET6;
1031
1032 // Create the UDP socket binding to ephemeral port
1033 struct us_udp_socket_t *udp_socket = us_create_udp_socket(context->loop, /*context->recv_buf*/ NULL, on_udp_socket_data_client, on_udp_socket_writable, 0, 0, context);
1034
1035 // Determine what port we got, creating the local sockaddr
1036 int ephemeral = us_udp_socket_bound_port(udp_socket);
1037
1038 printf("Connecting with udp socket bound to port: %d\n", ephemeral);
1039
1040 printf("Client udp socket is: %p\n", udp_socket);
1041
1042
1043 // let's call ourselves an ipv6 client and see if that solves anything
1044 struct sockaddr_storage local_storage = {0};
1045 // struct sockaddr_in *local_addr = (struct sockaddr_in *) &local_storage;
1046 // local_addr->sin_addr.s_addr = 16777343;
1047 // local_addr->sin_port = htons(ephemeral);
1048 // local_addr->sin_family = AF_INET;
1049
1050 struct sockaddr_in6 *local_addr = (struct sockaddr_in6 *) &local_storage;
1051 local_addr->sin6_addr.s6_addr[15] = 1;
1052 local_addr->sin6_port = htons(ephemeral);
1053 local_addr->sin6_family = AF_INET6;
1054
1055 // Refer to the UDP socket, and from that, get the context?
1056
1057 // Create an UDP socket with host-picked port, or well, any port for now
1058
1059 // we need 1 socket for servers, then we bind multiple ports to that one socket
1060
1061 void *client = lsquic_engine_connect(context->client_engine, LSQVER_I001, (struct sockaddr *) local_addr, (struct sockaddr *) addr, udp_socket, (lsquic_conn_ctx_t *) udp_socket, "sni", 0, 0, 0, 0, 0);
1062
1063 printf("Client: %p\n", client);
1064
1065 // this is requiored to even have packetgs sending out (run this in post)
1066 lsquic_engine_process_conns(context->client_engine);
1067
1068 return client;
1069}
1070
1071#endif
bsd_sendmmsg
int bsd_sendmmsg(int fd, void *msgvec, unsigned int vlen, int flags)
Definition bsd.c:56
bsd.h
SSL
const int SSL
Definition echo_server.c:4
us_create_timer
struct us_timer_t * us_create_timer(struct us_loop_t *loop, int fallthrough, unsigned int ext_size)
us_create_udp_packet_buffer
struct us_udp_packet_buffer_t * us_create_udp_packet_buffer()
Definition udp.c:63
us_udp_socket_user
void * us_udp_socket_user(struct us_udp_socket_t *s)
Definition udp.c:98
us_udp_packet_buffer_peer
char * us_udp_packet_buffer_peer(struct us_udp_packet_buffer_t *buf, int index)
Definition udp.c:33
us_poll_fd
int us_poll_fd(struct us_poll_t *p)
us_udp_socket_bound_port
int us_udp_socket_bound_port(struct us_udp_socket_t *s)
Definition udp.c:79
us_udp_packet_buffer_local_ip
int us_udp_packet_buffer_local_ip(struct us_udp_packet_buffer_t *buf, int index, char *ip)
Definition udp.c:29
us_udp_packet_buffer_payload_length
int us_udp_packet_buffer_payload_length(struct us_udp_packet_buffer_t *buf, int index)
Definition udp.c:41
us_udp_packet_buffer_ecn
int us_udp_packet_buffer_ecn(struct us_udp_packet_buffer_t *buf, int index)
Definition udp.c:25
us_udp_packet_buffer_payload
char * us_udp_packet_buffer_payload(struct us_udp_packet_buffer_t *buf, int index)
Definition udp.c:37
us_create_udp_socket
struct us_udp_socket_t * us_create_udp_socket(struct us_loop_t *loop, struct us_udp_packet_buffer_t *buf, void(*data_cb)(struct us_udp_socket_t *, struct us_udp_packet_buffer_t *, int), void(*drain_cb)(struct us_udp_socket_t *), const char *host, unsigned short port, void *user)
Definition udp.c:104
us_timer_set
void us_timer_set(struct us_timer_t *timer, void(*cb)(struct us_timer_t *t), int ms, int repeat_ms)
us_loop_t::fd
int fd
Definition epoll_kqueue.h:50
us_loop_t::data
struct us_internal_loop_data_t data
Definition asio.h:27
us_poll_t
Definition asio.h:37
us_loop_t
Definition asio.h:26
quic.h