diff --git a/Makefile b/Makefile index d333866..ae111b6 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,7 @@ endif # WITH_QUIC enables experimental Http3 examples ifeq ($(WITH_QUIC),1) override CXXFLAGS += -DLIBUS_USE_QUIC + override LDFLAGS += -pthread -lz -lm uSockets/lsquic/src/liblsquic/liblsquic.a endif # WITH_LIBDEFLATE=1 enables fast paths for SHARED_COMPRESSOR and inflation diff --git a/src/Http3App.h b/src/Http3App.h index 46368e8..b57c30a 100644 --- a/src/Http3App.h +++ b/src/Http3App.h @@ -11,7 +11,7 @@ namespace uWS { QuicApp(SocketContextOptions options = {}) { /* Create the http3 context */ - http3Context = Http3Context::create((us_loop_t *)Loop::get(), options); + http3Context = Http3Context::create((us_loop_t *)Loop::get(), {}); } QuicApp &listen(int port, std::function cb) { @@ -25,7 +25,7 @@ namespace uWS { } void run() { - + uWS::Loop::get()->run(); } }; diff --git a/src/Http3Context.h b/src/Http3Context.h index 093fa3b..1137cb1 100644 --- a/src/Http3Context.h +++ b/src/Http3Context.h @@ -1,6 +1,93 @@ + +extern "C" { +#include "quic.h" +} + + +/* Let's just have this one here for now */ +us_quic_socket_context_t *context; + +void print_current_headers() { + /* Iterate the headers and print them */ + for (int i = 0, more = 1; more; i++) { + char *name, *value; + int name_length, value_length; + if (more = us_quic_socket_context_get_header(context, i, &name, &name_length, &value, &value_length)) { + printf("header %.*s = %.*s\n", name_length, name, value_length, value); + } + } +} + +/* This would be a request */ +void on_stream_headers(us_quic_stream_t *s) { + + printf("==== HTTP/3 request ====\n"); + + print_current_headers(); + + /* Write headers */ + us_quic_socket_context_set_header(context, 0, ":status", 7, "200", 3); + //us_quic_socket_context_set_header(context, 1, "content-length", 14, "11", 2); + //us_quic_socket_context_set_header(context, 2, "content-type", 12, "text/html", 9); + us_quic_socket_context_send_headers(context, s, 1, 1); + + /* Write body and shutdown (unknown if content-length must be present?) */ + us_quic_stream_write(s, "Hello quic!", 11); + + /* Every request has its own stream, so we conceptually serve requests like in HTTP 1.0 */ + us_quic_stream_shutdown(s); +} + +/* And this would be the body of the request */ +void on_stream_data(us_quic_stream_t *s, char *data, int length) { + printf("Body length is: %d\n", length); +} + +void on_stream_writable(us_quic_stream_t *s) { + +} + +void on_stream_close(us_quic_stream_t *s) { + printf("Stream closed\n"); +} + +/* On new connection */ +void on_open(us_quic_socket_t *s, int is_client) { + printf("Connection established!\n"); +} + +/* On new stream */ +void on_stream_open(us_quic_stream_t *s, int is_client) { + printf("Stream opened!\n"); +} + +void on_close(us_quic_socket_t *s) { + printf("Disconnected!\n"); +} + namespace uWS { struct Http3Context { - static Http3Context *create(us_loop_t *loop, us_socket_context_options_t options) { + static Http3Context *create(us_loop_t *loop, us_quic_socket_context_options_t options) { + //return nullptr; + + printf("Creating context now\n"); + + /* Create quic socket context (assumes h3 for now) */ + context = us_create_quic_socket_context(loop, options); + + /* Specify application callbacks */ + us_quic_socket_context_on_stream_data(context, on_stream_data); + us_quic_socket_context_on_stream_open(context, on_stream_open); + us_quic_socket_context_on_stream_close(context, on_stream_close); + us_quic_socket_context_on_stream_writable(context, on_stream_writable); + us_quic_socket_context_on_stream_headers(context, on_stream_headers); + us_quic_socket_context_on_open(context, on_open); + us_quic_socket_context_on_close(context, on_close); + + /* The listening socket is the actual UDP socket used */ + us_quic_listen_socket_t *listen_socket = us_quic_socket_context_listen(context, "::1", 9004); + + return nullptr; // call init here after setting the ext to Http3ContextData