diff --git a/include/ulib/net/server/server.h b/include/ulib/net/server/server.h index dc766c89..424484b9 100644 --- a/include/ulib/net/server/server.h +++ b/include/ulib/net/server/server.h @@ -115,6 +115,7 @@ vClientImage = new client_type[UNotifier::max_connection]; } } #endif +class UQuic; class UHTTP; class UHTTP2; class UHTTP3; @@ -1458,6 +1459,7 @@ private: U_DISALLOW_COPY_AND_ASSIGN(UServer_Base) + friend class UQuic; friend class UHTTP; friend class UHTTP2; friend class UHTTP3; diff --git a/include/ulib/net/socket.h b/include/ulib/net/socket.h index 81eaef37..78fed18a 100644 --- a/include/ulib/net/socket.h +++ b/include/ulib/net/socket.h @@ -59,6 +59,7 @@ * they use class UIPAddress instances and port numbers rather than sockaddr structures */ +class UQuic; class UFile; class UHTTP; class UHTTP2; @@ -906,6 +907,7 @@ protected: private: U_DISALLOW_COPY_AND_ASSIGN(USocket) + friend class UQuic; friend class UFile; friend class UHTTP; friend class UHTTP2; diff --git a/include/ulib/string.h b/include/ulib/string.h index 0c150368..25929544 100644 --- a/include/ulib/string.h +++ b/include/ulib/string.h @@ -1267,7 +1267,7 @@ public: // ORM SQLITE static const UString* str_sqlite_name; static const UString* str_dbdir; -#ifndef U_HTTP2_DISABLE +#if !defined(U_HTTP2_DISABLE) || !defined(U_HTTP3_DISABLE) static const UString* str_authority; static const UString* str_method; static const UString* str_method_get; diff --git a/include/ulib/utility/http2.h b/include/ulib/utility/http2.h index 34a0880f..08442f69 100644 --- a/include/ulib/utility/http2.h +++ b/include/ulib/utility/http2.h @@ -31,6 +31,7 @@ #define HTTP2_CONNECTION_PREFACE "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" // (24 bytes) class UHTTP; +class UHTTP3; class UClientImage_Base; class U_EXPORT UHTTP2 { @@ -282,6 +283,7 @@ protected: static void sendPing(); static void readFrame(); static void setStream(); + static void buildTable(); static void manageData(); static bool initRequest(); static void writeResponse(); @@ -490,7 +492,7 @@ protected: U_RETURN(false); } - + static bool eraseHeaders(UStringRep* key, void* elem) // callWithDeleteForAllEntry()... { U_TRACE(0, "UHTTP2::eraseHeaders(%V,%p)", key, elem) @@ -849,6 +851,7 @@ private: U_DISALLOW_COPY_AND_ASSIGN(UHTTP2) friend class UHTTP; + friend class UHTTP3; friend class Application; friend class UClientImage_Base; }; diff --git a/include/ulib/utility/http3.h b/include/ulib/utility/http3.h index fc3fe6f4..627b6770 100644 --- a/include/ulib/utility/http3.h +++ b/include/ulib/utility/http3.h @@ -7,23 +7,15 @@ // http3.h - HTTP/3 utility // // = AUTHOR -// Stefano Casazza +// Stefano Casazza + Victor Stewart // // ============================================================================ #ifndef ULIB_HTTP3_H #define ULIB_HTTP3_H 1 -#include -#include - -#define U_MAX_TOKEN_LEN \ - sizeof("quiche")-1 + \ - sizeof(struct sockaddr_storage) + \ - QUICHE_MAX_CONN_ID_LEN - -#define U_LOCAL_CONN_ID_LEN 16 -#define U_MAX_DATAGRAM_SIZE 1350 +#include +#include /** * HTTP3 connection Information @@ -31,38 +23,17 @@ * This class contains data about an HTTP3 connection */ -// override the default... -template <> inline void u_destroy( const UClientImage_Base* ptr) { U_TRACE(0,"u_destroy(%p)", ptr) } -template <> inline void u_destroy( const UClientImage_Base** ptr, uint32_t n) { U_TRACE(0,"u_destroy(%p,%u)", ptr, n) } -template <> inline void u_construct(const UClientImage_Base** ptr, bool b) { U_TRACE(0,"u_construct(%p,%b)", ptr, b) } - class U_EXPORT UHTTP3 { public: - // QUIC packet type - enum Type { - Initial = 1, - Retry = 2, - Handshake = 3, - ZeroRTT = 4, - Short = 5, - VersionNegotiation = 6 - }; - static int loadConfigParam(); protected: - static uint8_t pkt_type; - static quiche_conn* conn; + static uint32_t headers_len; static quiche_h3_conn* http3; - static quiche_config* qconfig; static quiche_h3_header* headers; + static UHashMap* itable; // headers request static quiche_h3_config* http3_config; - static struct sockaddr_storage peer_addr; - static UHashMap* peers; - static size_t conn_id_len, scid_len, token_len; - static uint32_t pkt_version, peer_addr_len, headers_len; - static uint8_t token[U_MAX_TOKEN_LEN], scid[QUICHE_MAX_CONN_ID_LEN], conn_id[QUICHE_MAX_CONN_ID_LEN]; // SERVICES @@ -70,90 +41,27 @@ protected: { U_TRACE_NO_PARAM(0, "UHTTP3::ctor()") - U_INTERNAL_ASSERT_EQUALS(peers, U_NULLPTR) +# ifdef U_HTTP2_DISABLE + UHTTP2::buildTable(); +# endif - U_NEW(UHashMap, peers, UHashMap(UNotifier::max_connection)); + U_NEW(UHashMap, itable, UHashMap(64, UHTTP2::setIndexStaticTable)); } static void dtor() { U_TRACE_NO_PARAM(0, "UHTTP3::dtor()") - if (peers) U_DELETE(peers) + if (itable) U_DELETE(itable) - if (qconfig) U_SYSCALL_VOID(quiche_config_free, "%p", qconfig); if (http3_config) U_SYSCALL_VOID(quiche_h3_config_free, "%p", http3_config); } static bool parseHeader(); static bool handlerNewConnection(); static void handlerRequest(quiche_conn* lconn, quiche_h3_conn* lh3); - static bool handlerRead(quiche_conn* lconn = U_NULLPTR, bool bwait_for_data = false); - // Lookup a connection based on the packet's connection ID - - static bool lookup() - { - U_TRACE_NO_PARAM(0, "UHTTP3::lookup()") - - if (peers->empty() == false && - ((UServer_Base::pClientImage = peers->at((const char*)conn_id, conn_id_len)))) - { - UServer_Base::nClientIndex = UServer_Base::pClientImage - UServer_Base::vClientImage; - - U_INTERNAL_DUMP("UServer_Base::nClientIndex = %u", UServer_Base::nClientIndex) - - U_INTERNAL_ASSERT_MINOR(UServer_Base::nClientIndex, UNotifier::max_connection) - - U_RETURN(true); - } - - U_RETURN(false); - } - - static void insert() - { - U_TRACE_NO_PARAM(0, "UHTTP3::insert()") - - peers->insert((const char*)conn_id, conn_id_len, UServer_Base::pClientImage); - } - - static bool processesPackets(quiche_conn* lconn) - { - U_TRACE(0, "UHTTP3::processesPackets(%p)", lconn) - - U_INTERNAL_ASSERT_POINTER(lconn) - - // Processes QUIC packets received from the peer - ssize_t done = U_SYSCALL(quiche_conn_recv, "%p,%p,%u", lconn, (uint8_t*)U_STRING_TO_PARAM(*UServer_Base::rbuffer)); - - if (done < 0) - { - U_DEBUG("UHTTP3::processesPackets(): failed to process packet: %d", done) - - U_RETURN(false); - } - - U_DEBUG("quiche: recv %d bytes", done) - - U_RETURN(true); - } - - static int for_each_header(uint8_t* name, size_t name_len, uint8_t* value, size_t value_len, void* argp) - { - U_TRACE(0, "UHTTP3::for_each_header(%.*S,%u,%.*S,%u,%p)", name_len, name, name_len, value_len, value, value_len, argp) - - U_DEBUG("quiche: got HTTP header: %.*S(%u)=%.*S(%u)", name_len, name, name_len, value_len, value, value_len) - - U_RETURN(0); - } - -#ifdef DEBUG - static void quiche_debug_log(const char* line, void* argp) - { - U_DEBUG("%s\n", line) - } -#endif + static int for_each_header(uint8_t* name, size_t name_len, uint8_t* value, size_t value_len, void* argp); private: U_DISALLOW_COPY_AND_ASSIGN(UHTTP3) diff --git a/include/ulib/utility/uquic.h b/include/ulib/utility/uquic.h new file mode 100644 index 00000000..4e3f10e9 --- /dev/null +++ b/include/ulib/utility/uquic.h @@ -0,0 +1,151 @@ +// ============================================================================ +// +// = LIBRARY +// ULib - c++ library +// +// = FILENAME +// uquic.h - Quic utility +// +// = AUTHOR +// Stefano Casazza + Victor Stewart +// +// ============================================================================ + +#ifndef U_QUIC_H +#define U_QUIC_H 1 + +#include +#include + +#define U_MAX_TOKEN_LEN \ + sizeof("quiche")-1 + \ + sizeof(struct sockaddr_storage) + \ + QUICHE_MAX_CONN_ID_LEN + +#define U_LOCAL_CONN_ID_LEN 16 +#define U_MAX_DATAGRAM_SIZE 1350 + +// override the default... +template <> inline void u_destroy( const UClientImage_Base* ptr) { U_TRACE(0,"u_destroy(%p)", ptr) } +template <> inline void u_destroy( const UClientImage_Base** ptr, uint32_t n) { U_TRACE(0,"u_destroy(%p,%u)", ptr, n) } +template <> inline void u_construct(const UClientImage_Base** ptr, bool b) { U_TRACE(0,"u_construct(%p,%b)", ptr, b) } + +class UHTTP3; + +class U_EXPORT UQuic { +public: + + // QUIC packet type + enum Type { + Initial = 1, + Retry = 2, + Handshake = 3, + ZeroRTT = 4, + Short = 5, + VersionNegotiation = 6 + }; + + static int loadConfigParam(); + +protected: + static uint8_t pkt_type; + static quiche_conn* conn; + static quiche_config* qconfig; + static struct sockaddr_storage peer_addr; + static UHashMap* peers; + static uint32_t pkt_version, peer_addr_len; + static size_t conn_id_len, scid_len, token_len; + static uint8_t token[U_MAX_TOKEN_LEN], scid[QUICHE_MAX_CONN_ID_LEN], conn_id[QUICHE_MAX_CONN_ID_LEN]; + + // SERVICES + + static void ctor() + { + U_TRACE_NO_PARAM(0, "UQuic::ctor()") + + U_INTERNAL_ASSERT_EQUALS(peers, U_NULLPTR) + + U_NEW(UHashMap, peers, UHashMap(UNotifier::max_connection)); + } + + static void dtor() + { + U_TRACE_NO_PARAM(0, "UQuic::dtor()") + + if (peers) U_DELETE(peers) + + if (qconfig) U_SYSCALL_VOID(quiche_config_free, "%p", qconfig); + } + + static bool parseHeader(); + static bool handlerNewConnection(); + static void handlerRequest(quiche_conn* lconn, quiche_h3_conn* lh3); + static bool handlerRead(quiche_conn* lconn = U_NULLPTR, bool bwait_for_data = false); + + // Lookup a connection based on the packet's connection ID + + static bool lookup() + { + U_TRACE_NO_PARAM(0, "UQuic::lookup()") + + if (peers->empty() == false && + ((UServer_Base::pClientImage = peers->at((const char*)conn_id, conn_id_len)))) + { + UServer_Base::nClientIndex = UServer_Base::pClientImage - UServer_Base::vClientImage; + + U_INTERNAL_DUMP("UServer_Base::nClientIndex = %u", UServer_Base::nClientIndex) + + U_INTERNAL_ASSERT_MINOR(UServer_Base::nClientIndex, UNotifier::max_connection) + + U_RETURN(true); + } + + U_RETURN(false); + } + + static void insert() + { + U_TRACE_NO_PARAM(0, "UQuic::insert()") + + peers->insert((const char*)conn_id, conn_id_len, UServer_Base::pClientImage); + } + + static bool processesPackets(quiche_conn* lconn) + { + U_TRACE(0, "UQuic::processesPackets(%p)", lconn) + + U_INTERNAL_ASSERT_POINTER(lconn) + + // Processes QUIC packets received from the peer + ssize_t done = U_SYSCALL(quiche_conn_recv, "%p,%p,%u", lconn, (uint8_t*)U_STRING_TO_PARAM(*UServer_Base::rbuffer)); + + if (done < 0) + { + U_DEBUG("UQuic::processesPackets(): failed to process packet: %d", done) + + U_RETURN(false); + } + + U_DEBUG("quiche: recv %d bytes", done) + + U_RETURN(true); + } + +#ifdef DEBUG + static void quiche_debug_log(const char* line, void* argp) + { + U_DEBUG("%s\n", line) + } +#endif + +private: + U_DISALLOW_COPY_AND_ASSIGN(UQuic) + + friend class UHTTP; + friend class UHTTP3; + friend class Application; + friend class UHttpPlugIn; + friend class UServer_Base; + friend class UClientImage_Base; +}; +#endif diff --git a/src/ulib/Makefile.am b/src/ulib/Makefile.am index 4c3ff92b..10518822 100644 --- a/src/ulib/Makefile.am +++ b/src/ulib/Makefile.am @@ -61,7 +61,10 @@ if HTTP2 SRC_CPP += utility/http2.cpp endif if HTTP3 -SRC_CPP += utility/http3.cpp +SRC_CPP += utility/http3.cpp utility/uquic.cpp +if !HTTP2 +SRC_CPP += utility/http2.cpp +endif endif if STDCPP diff --git a/src/ulib/Makefile.in b/src/ulib/Makefile.in index d54b9d8b..5a4f0f55 100644 --- a/src/ulib/Makefile.in +++ b/src/ulib/Makefile.in @@ -93,81 +93,82 @@ target_triplet = @target@ @LIBTDB_TRUE@am__append_1 = db/tdb.cpp @MONGODB_TRUE@am__append_2 = net/client/mongodb.cpp @HTTP2_TRUE@am__append_3 = utility/http2.cpp -@HTTP3_TRUE@am__append_4 = utility/http3.cpp -@STDCPP_TRUE@am__append_5 = internal/objectIO.cpp -@PTHREAD_TRUE@am__append_6 = thread.cpp -@DEBUG_TRUE@am__append_7 = base/base_trace.c -@DEBUG_TRUE@am__append_8 = debug/debug_common.cpp debug/trace.cpp debug/error_memory.cpp debug/error_simulation.cpp -@DEBUG_TRUE@@STDCPP_TRUE@am__append_9 = debug/objectDB.cpp -@GETOPT_LONG_FALSE@am__append_10 = replace/getopt_long.c -@MREMAP_FALSE@am__append_11 = replace/mremap.c -@NANOSLEEP_FALSE@am__append_12 = replace/nanosleep.c -@SENDFILE_FALSE@am__append_13 = replace/sendfile.c -@STRNDUP_FALSE@am__append_14 = replace/strndup.c -@SEMAPHORE_FALSE@am__append_15 = replace/sem.c -@SEMAPHORE_TRUE@@SEM_TIMEDWAIT_FALSE@am__append_16 = replace/sem_timedwait.c -@STRPTIME_FALSE@am__append_17 = replace/strptime.c -@MKDTEMP_FALSE@am__append_18 = replace/mkdtemp.c -@MEMMEM_FALSE@am__append_19 = replace/memmem.c -@MEMRCHR_FALSE@am__append_20 = replace/memrchr.c -@GMTIME_R_FALSE@am__append_21 = replace/gmtime.c -@TIMEGM_FALSE@am__append_22 = replace/timegm.c -@FNMATCH_FALSE@am__append_23 = replace/fnmatch.c -@FALLOCATE_FALSE@am__append_24 = replace/fallocate.c -@FALLOCATE64_FALSE@am__append_25 = replace/fallocate64.c -@PREAD_FALSE@am__append_26 = replace/pread.c -@ASSERT_FALSE@am__append_27 = replace/assert.c -@APEXMEM_TRUE@am__append_28 = base/apex/apex_memmove.c -@SCHED_GETCPU_FALSE@am__append_29 = replace/sched_getcpu.c -@ZIP_TRUE@am__append_30 = base/zip/inflate.c base/zip/dostime.c base/zip/pushback.c base/zip/ziptool.c -@ZIP_TRUE@am__append_31 = zip/zip.cpp -@LIBZ_TRUE@am__append_32 = base/coder/cgzio.c -@USE_PARSER_TRUE@am__append_33 = flex/flexer.cpp flex/bison.cpp -@PCRE_TRUE@am__append_34 = pcre/pcre.cpp -@SSL_TRUE@am__append_35 = base/ssl/cdes3.c base/ssl/dgst.c -@SSL_TRUE@am__append_36 = ssl/certificate.cpp ssl/pkcs7.cpp ssl/crl.cpp ssl/pkcs10.cpp net/client/twilio.cpp net/client/uwebsocket.cpp \ +@HTTP3_TRUE@am__append_4 = utility/http3.cpp utility/uquic.cpp +@HTTP2_FALSE@@HTTP3_TRUE@am__append_5 = utility/http2.cpp +@STDCPP_TRUE@am__append_6 = internal/objectIO.cpp +@PTHREAD_TRUE@am__append_7 = thread.cpp +@DEBUG_TRUE@am__append_8 = base/base_trace.c +@DEBUG_TRUE@am__append_9 = debug/debug_common.cpp debug/trace.cpp debug/error_memory.cpp debug/error_simulation.cpp +@DEBUG_TRUE@@STDCPP_TRUE@am__append_10 = debug/objectDB.cpp +@GETOPT_LONG_FALSE@am__append_11 = replace/getopt_long.c +@MREMAP_FALSE@am__append_12 = replace/mremap.c +@NANOSLEEP_FALSE@am__append_13 = replace/nanosleep.c +@SENDFILE_FALSE@am__append_14 = replace/sendfile.c +@STRNDUP_FALSE@am__append_15 = replace/strndup.c +@SEMAPHORE_FALSE@am__append_16 = replace/sem.c +@SEMAPHORE_TRUE@@SEM_TIMEDWAIT_FALSE@am__append_17 = replace/sem_timedwait.c +@STRPTIME_FALSE@am__append_18 = replace/strptime.c +@MKDTEMP_FALSE@am__append_19 = replace/mkdtemp.c +@MEMMEM_FALSE@am__append_20 = replace/memmem.c +@MEMRCHR_FALSE@am__append_21 = replace/memrchr.c +@GMTIME_R_FALSE@am__append_22 = replace/gmtime.c +@TIMEGM_FALSE@am__append_23 = replace/timegm.c +@FNMATCH_FALSE@am__append_24 = replace/fnmatch.c +@FALLOCATE_FALSE@am__append_25 = replace/fallocate.c +@FALLOCATE64_FALSE@am__append_26 = replace/fallocate64.c +@PREAD_FALSE@am__append_27 = replace/pread.c +@ASSERT_FALSE@am__append_28 = replace/assert.c +@APEXMEM_TRUE@am__append_29 = base/apex/apex_memmove.c +@SCHED_GETCPU_FALSE@am__append_30 = replace/sched_getcpu.c +@ZIP_TRUE@am__append_31 = base/zip/inflate.c base/zip/dostime.c base/zip/pushback.c base/zip/ziptool.c +@ZIP_TRUE@am__append_32 = zip/zip.cpp +@LIBZ_TRUE@am__append_33 = base/coder/cgzio.c +@USE_PARSER_TRUE@am__append_34 = flex/flexer.cpp flex/bison.cpp +@PCRE_TRUE@am__append_35 = pcre/pcre.cpp +@SSL_TRUE@am__append_36 = base/ssl/cdes3.c base/ssl/dgst.c +@SSL_TRUE@am__append_37 = ssl/certificate.cpp ssl/pkcs7.cpp ssl/crl.cpp ssl/pkcs10.cpp net/client/twilio.cpp net/client/uwebsocket.cpp \ @SSL_TRUE@ ssl/mime/mime_pkcs7.cpp ssl/net/sslsocket.cpp ssl/net/ssl_session.cpp utility/des3.cpp -@SSL_TRUE@@SSL_TS_TRUE@am__append_37 = ssl/timestamp.cpp -@SSH_TRUE@am__append_38 = ssh/net/sshsocket.cpp -@LDAP_TRUE@am__append_39 = ldap/ldap.cpp -@CURL_TRUE@am__append_40 = curl/curl.cpp -@EXPAT_TRUE@am__append_41 = xml/expat/attribute.cpp xml/expat/element.cpp xml/expat/xml_parser.cpp xml/expat/xml2txt.cpp \ +@SSL_TRUE@@SSL_TS_TRUE@am__append_38 = ssl/timestamp.cpp +@SSH_TRUE@am__append_39 = ssh/net/sshsocket.cpp +@LDAP_TRUE@am__append_40 = ldap/ldap.cpp +@CURL_TRUE@am__append_41 = curl/curl.cpp +@EXPAT_TRUE@am__append_42 = xml/expat/attribute.cpp xml/expat/element.cpp xml/expat/xml_parser.cpp xml/expat/xml2txt.cpp \ @EXPAT_TRUE@ xml/soap/soap_fault.cpp xml/soap/soap_gen_method.cpp xml/soap/soap_parser.cpp xml/soap/soap_encoder.cpp xml/soap/soap_client.cpp -@LIBXML2_TRUE@am__append_42 = xml/libxml2/node.cpp xml/libxml2/document.cpp xml/libxml2/schema.cpp -@MAGIC_TRUE@am__append_43 = magic/magic.cpp -@DBI_TRUE@am__append_44 = dbi/dbi.cpp -@LIBEVENT_TRUE@am__append_45 = libevent/event.cpp -@MINGW_TRUE@am__append_46 = base/win32/mingw32.c -@MINGW_FALSE@am__append_47 = net/unixsocket.cpp +@LIBXML2_TRUE@am__append_43 = xml/libxml2/node.cpp xml/libxml2/document.cpp xml/libxml2/schema.cpp +@MAGIC_TRUE@am__append_44 = magic/magic.cpp +@DBI_TRUE@am__append_45 = dbi/dbi.cpp +@LIBEVENT_TRUE@am__append_46 = libevent/event.cpp +@MINGW_TRUE@am__append_47 = base/win32/mingw32.c +@MINGW_FALSE@am__append_48 = net/unixsocket.cpp # Handler static plugin -@STATIC_HANDLER_RPC_TRUE@am__append_48 = net/server/plugin/mod_rpc.cpp -@MOD_SHIB_TRUE@@STATIC_HANDLER_SHIB_TRUE@am__append_49 = net/server/plugin/mod_shib/mod_shib.cpp -@STATIC_HANDLER_STREAM_TRUE@am__append_50 = net/server/plugin/mod_stream.cpp -@STATIC_HANDLER_NOCAT_TRUE@am__append_51 = net/server/plugin/mod_nocat.cpp -@STATIC_HANDLER_NODOG_TRUE@am__append_52 = net/server/plugin/mod_nodog.cpp -@STATIC_HANDLER_SOCKET_TRUE@am__append_53 = net/server/plugin/mod_socket.cpp -@STATIC_HANDLER_SCGI_TRUE@am__append_54 = net/server/plugin/mod_scgi.cpp -@STATIC_HANDLER_FCGI_TRUE@am__append_55 = net/server/plugin/mod_fcgi.cpp -@GEOIP_TRUE@@STATIC_HANDLER_GEOIP_TRUE@am__append_56 = net/server/plugin/mod_geoip/mod_geoip.cpp -@PCRE_TRUE@@STATIC_HANDLER_PROXY_TRUE@am__append_57 = net/server/plugin/mod_proxy.cpp -@EXPAT_TRUE@@STATIC_HANDLER_SOAP_TRUE@am__append_58 = net/server/plugin/mod_soap.cpp -@STATIC_HANDLER_SSI_TRUE@am__append_59 = net/server/plugin/mod_ssi.cpp -@STATIC_HANDLER_TSA_TRUE@am__append_60 = net/server/plugin/mod_tsa.cpp -@STATIC_HANDLER_HTTP_TRUE@am__append_61 = net/server/plugin/mod_http.cpp -@STATIC_HANDLER_ECHO_TRUE@am__append_62 = net/server/plugin/mod_echo.cpp +@STATIC_HANDLER_RPC_TRUE@am__append_49 = net/server/plugin/mod_rpc.cpp +@MOD_SHIB_TRUE@@STATIC_HANDLER_SHIB_TRUE@am__append_50 = net/server/plugin/mod_shib/mod_shib.cpp +@STATIC_HANDLER_STREAM_TRUE@am__append_51 = net/server/plugin/mod_stream.cpp +@STATIC_HANDLER_NOCAT_TRUE@am__append_52 = net/server/plugin/mod_nocat.cpp +@STATIC_HANDLER_NODOG_TRUE@am__append_53 = net/server/plugin/mod_nodog.cpp +@STATIC_HANDLER_SOCKET_TRUE@am__append_54 = net/server/plugin/mod_socket.cpp +@STATIC_HANDLER_SCGI_TRUE@am__append_55 = net/server/plugin/mod_scgi.cpp +@STATIC_HANDLER_FCGI_TRUE@am__append_56 = net/server/plugin/mod_fcgi.cpp +@GEOIP_TRUE@@STATIC_HANDLER_GEOIP_TRUE@am__append_57 = net/server/plugin/mod_geoip/mod_geoip.cpp +@PCRE_TRUE@@STATIC_HANDLER_PROXY_TRUE@am__append_58 = net/server/plugin/mod_proxy.cpp +@EXPAT_TRUE@@STATIC_HANDLER_SOAP_TRUE@am__append_59 = net/server/plugin/mod_soap.cpp +@STATIC_HANDLER_SSI_TRUE@am__append_60 = net/server/plugin/mod_ssi.cpp +@STATIC_HANDLER_TSA_TRUE@am__append_61 = net/server/plugin/mod_tsa.cpp +@STATIC_HANDLER_HTTP_TRUE@am__append_62 = net/server/plugin/mod_http.cpp +@STATIC_HANDLER_ECHO_TRUE@am__append_63 = net/server/plugin/mod_echo.cpp # Handler static orm driver -@STATIC_ORM_DRIVER_SQLITE_TRUE@am__append_63 = orm/driver/orm_driver_sqlite.cpp -@STATIC_ORM_DRIVER_MYSQL_TRUE@am__append_64 = orm/driver/orm_driver_mysql.cpp -@STATIC_ORM_DRIVER_PGSQL_TRUE@am__append_65 = orm/driver/orm_driver_pgsql.cpp -@STATIC_ORM_DRIVER_PGSQL_TRUE@am__append_66 = $(top_builddir)/src/ulib/orm/driver/libpq/libpq.la -@MINGW_TRUE@am__append_67 = -export-symbols $(srcdir)/@ULIB@.def -no-undefined -Wl,ULib-win32-res.o +@STATIC_ORM_DRIVER_SQLITE_TRUE@am__append_64 = orm/driver/orm_driver_sqlite.cpp +@STATIC_ORM_DRIVER_MYSQL_TRUE@am__append_65 = orm/driver/orm_driver_mysql.cpp +@STATIC_ORM_DRIVER_PGSQL_TRUE@am__append_66 = orm/driver/orm_driver_pgsql.cpp +@STATIC_ORM_DRIVER_PGSQL_TRUE@am__append_67 = $(top_builddir)/src/ulib/orm/driver/libpq/libpq.la +@MINGW_TRUE@am__append_68 = -export-symbols $(srcdir)/@ULIB@.def -no-undefined -Wl,ULib-win32-res.o # Handler static http servlet -@STATIC_ONLY_TRUE@@STATIC_SERVLET_TRUE@am__append_68 = net/server/plugin/usp/loader.autoconf.inc +@STATIC_ONLY_TRUE@@STATIC_SERVLET_TRUE@am__append_69 = net/server/plugin/usp/loader.autoconf.inc subdir = src/ulib ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_package.m4 \ @@ -269,12 +270,13 @@ am__lib@ULIB@_la_SOURCES_DIST = base/base.c base/base_error.c \ process.cpp file_config.cpp log.cpp options.cpp \ application.cpp cache.cpp date.cpp url.cpp tokenizer.cpp \ command.cpp db/tdb.cpp net/client/mongodb.cpp \ - utility/http2.cpp utility/http3.cpp internal/objectIO.cpp \ - thread.cpp debug/debug_common.cpp debug/trace.cpp \ - debug/error_memory.cpp debug/error_simulation.cpp \ - debug/objectDB.cpp zip/zip.cpp flex/flexer.cpp flex/bison.cpp \ - pcre/pcre.cpp ssl/certificate.cpp ssl/pkcs7.cpp ssl/crl.cpp \ - ssl/pkcs10.cpp net/client/twilio.cpp net/client/uwebsocket.cpp \ + utility/http2.cpp utility/http3.cpp utility/uquic.cpp \ + internal/objectIO.cpp thread.cpp debug/debug_common.cpp \ + debug/trace.cpp debug/error_memory.cpp \ + debug/error_simulation.cpp debug/objectDB.cpp zip/zip.cpp \ + flex/flexer.cpp flex/bison.cpp pcre/pcre.cpp \ + ssl/certificate.cpp ssl/pkcs7.cpp ssl/crl.cpp ssl/pkcs10.cpp \ + net/client/twilio.cpp net/client/uwebsocket.cpp \ ssl/mime/mime_pkcs7.cpp ssl/net/sslsocket.cpp \ ssl/net/ssl_session.cpp utility/des3.cpp ssl/timestamp.cpp \ ssh/net/sshsocket.cpp ldap/ldap.cpp curl/curl.cpp \ @@ -344,69 +346,70 @@ am__objects_26 = base/base.lo base/base_error.lo base/hash.lo \ @LIBTDB_TRUE@am__objects_27 = db/tdb.lo @MONGODB_TRUE@am__objects_28 = net/client/mongodb.lo @HTTP2_TRUE@am__objects_29 = utility/http2.lo -@HTTP3_TRUE@am__objects_30 = utility/http3.lo -@STDCPP_TRUE@am__objects_31 = internal/objectIO.lo -@PTHREAD_TRUE@am__objects_32 = thread.lo -@DEBUG_TRUE@am__objects_33 = debug/debug_common.lo debug/trace.lo \ +@HTTP3_TRUE@am__objects_30 = utility/http3.lo utility/uquic.lo +@HTTP2_FALSE@@HTTP3_TRUE@am__objects_31 = utility/http2.lo +@STDCPP_TRUE@am__objects_32 = internal/objectIO.lo +@PTHREAD_TRUE@am__objects_33 = thread.lo +@DEBUG_TRUE@am__objects_34 = debug/debug_common.lo debug/trace.lo \ @DEBUG_TRUE@ debug/error_memory.lo debug/error_simulation.lo -@DEBUG_TRUE@@STDCPP_TRUE@am__objects_34 = debug/objectDB.lo -@ZIP_TRUE@am__objects_35 = zip/zip.lo -@USE_PARSER_TRUE@am__objects_36 = flex/flexer.lo flex/bison.lo -@PCRE_TRUE@am__objects_37 = pcre/pcre.lo -@SSL_TRUE@am__objects_38 = ssl/certificate.lo ssl/pkcs7.lo ssl/crl.lo \ +@DEBUG_TRUE@@STDCPP_TRUE@am__objects_35 = debug/objectDB.lo +@ZIP_TRUE@am__objects_36 = zip/zip.lo +@USE_PARSER_TRUE@am__objects_37 = flex/flexer.lo flex/bison.lo +@PCRE_TRUE@am__objects_38 = pcre/pcre.lo +@SSL_TRUE@am__objects_39 = ssl/certificate.lo ssl/pkcs7.lo ssl/crl.lo \ @SSL_TRUE@ ssl/pkcs10.lo net/client/twilio.lo \ @SSL_TRUE@ net/client/uwebsocket.lo ssl/mime/mime_pkcs7.lo \ @SSL_TRUE@ ssl/net/sslsocket.lo ssl/net/ssl_session.lo \ @SSL_TRUE@ utility/des3.lo -@SSL_TRUE@@SSL_TS_TRUE@am__objects_39 = ssl/timestamp.lo -@SSH_TRUE@am__objects_40 = ssh/net/sshsocket.lo -@LDAP_TRUE@am__objects_41 = ldap/ldap.lo -@CURL_TRUE@am__objects_42 = curl/curl.lo -@EXPAT_TRUE@am__objects_43 = xml/expat/attribute.lo \ +@SSL_TRUE@@SSL_TS_TRUE@am__objects_40 = ssl/timestamp.lo +@SSH_TRUE@am__objects_41 = ssh/net/sshsocket.lo +@LDAP_TRUE@am__objects_42 = ldap/ldap.lo +@CURL_TRUE@am__objects_43 = curl/curl.lo +@EXPAT_TRUE@am__objects_44 = xml/expat/attribute.lo \ @EXPAT_TRUE@ xml/expat/element.lo xml/expat/xml_parser.lo \ @EXPAT_TRUE@ xml/expat/xml2txt.lo xml/soap/soap_fault.lo \ @EXPAT_TRUE@ xml/soap/soap_gen_method.lo \ @EXPAT_TRUE@ xml/soap/soap_parser.lo xml/soap/soap_encoder.lo \ @EXPAT_TRUE@ xml/soap/soap_client.lo -@LIBXML2_TRUE@am__objects_44 = xml/libxml2/node.lo \ +@LIBXML2_TRUE@am__objects_45 = xml/libxml2/node.lo \ @LIBXML2_TRUE@ xml/libxml2/document.lo xml/libxml2/schema.lo -@MAGIC_TRUE@am__objects_45 = magic/magic.lo -@DBI_TRUE@am__objects_46 = dbi/dbi.lo -@LIBEVENT_TRUE@am__objects_47 = libevent/event.lo -@MINGW_FALSE@am__objects_48 = net/unixsocket.lo -@STATIC_HANDLER_RPC_TRUE@am__objects_49 = \ +@MAGIC_TRUE@am__objects_46 = magic/magic.lo +@DBI_TRUE@am__objects_47 = dbi/dbi.lo +@LIBEVENT_TRUE@am__objects_48 = libevent/event.lo +@MINGW_FALSE@am__objects_49 = net/unixsocket.lo +@STATIC_HANDLER_RPC_TRUE@am__objects_50 = \ @STATIC_HANDLER_RPC_TRUE@ net/server/plugin/mod_rpc.lo -@MOD_SHIB_TRUE@@STATIC_HANDLER_SHIB_TRUE@am__objects_50 = net/server/plugin/mod_shib/mod_shib.lo -@STATIC_HANDLER_STREAM_TRUE@am__objects_51 = \ +@MOD_SHIB_TRUE@@STATIC_HANDLER_SHIB_TRUE@am__objects_51 = net/server/plugin/mod_shib/mod_shib.lo +@STATIC_HANDLER_STREAM_TRUE@am__objects_52 = \ @STATIC_HANDLER_STREAM_TRUE@ net/server/plugin/mod_stream.lo -@STATIC_HANDLER_NOCAT_TRUE@am__objects_52 = \ +@STATIC_HANDLER_NOCAT_TRUE@am__objects_53 = \ @STATIC_HANDLER_NOCAT_TRUE@ net/server/plugin/mod_nocat.lo -@STATIC_HANDLER_NODOG_TRUE@am__objects_53 = \ +@STATIC_HANDLER_NODOG_TRUE@am__objects_54 = \ @STATIC_HANDLER_NODOG_TRUE@ net/server/plugin/mod_nodog.lo -@STATIC_HANDLER_SOCKET_TRUE@am__objects_54 = \ +@STATIC_HANDLER_SOCKET_TRUE@am__objects_55 = \ @STATIC_HANDLER_SOCKET_TRUE@ net/server/plugin/mod_socket.lo -@STATIC_HANDLER_SCGI_TRUE@am__objects_55 = \ +@STATIC_HANDLER_SCGI_TRUE@am__objects_56 = \ @STATIC_HANDLER_SCGI_TRUE@ net/server/plugin/mod_scgi.lo -@STATIC_HANDLER_FCGI_TRUE@am__objects_56 = \ +@STATIC_HANDLER_FCGI_TRUE@am__objects_57 = \ @STATIC_HANDLER_FCGI_TRUE@ net/server/plugin/mod_fcgi.lo -@GEOIP_TRUE@@STATIC_HANDLER_GEOIP_TRUE@am__objects_57 = net/server/plugin/mod_geoip/mod_geoip.lo -@PCRE_TRUE@@STATIC_HANDLER_PROXY_TRUE@am__objects_58 = net/server/plugin/mod_proxy.lo -@EXPAT_TRUE@@STATIC_HANDLER_SOAP_TRUE@am__objects_59 = net/server/plugin/mod_soap.lo -@STATIC_HANDLER_SSI_TRUE@am__objects_60 = \ +@GEOIP_TRUE@@STATIC_HANDLER_GEOIP_TRUE@am__objects_58 = net/server/plugin/mod_geoip/mod_geoip.lo +@PCRE_TRUE@@STATIC_HANDLER_PROXY_TRUE@am__objects_59 = net/server/plugin/mod_proxy.lo +@EXPAT_TRUE@@STATIC_HANDLER_SOAP_TRUE@am__objects_60 = net/server/plugin/mod_soap.lo +@STATIC_HANDLER_SSI_TRUE@am__objects_61 = \ @STATIC_HANDLER_SSI_TRUE@ net/server/plugin/mod_ssi.lo -@STATIC_HANDLER_TSA_TRUE@am__objects_61 = \ +@STATIC_HANDLER_TSA_TRUE@am__objects_62 = \ @STATIC_HANDLER_TSA_TRUE@ net/server/plugin/mod_tsa.lo -@STATIC_HANDLER_HTTP_TRUE@am__objects_62 = \ +@STATIC_HANDLER_HTTP_TRUE@am__objects_63 = \ @STATIC_HANDLER_HTTP_TRUE@ net/server/plugin/mod_http.lo -@STATIC_HANDLER_ECHO_TRUE@am__objects_63 = \ +@STATIC_HANDLER_ECHO_TRUE@am__objects_64 = \ @STATIC_HANDLER_ECHO_TRUE@ net/server/plugin/mod_echo.lo -@STATIC_ORM_DRIVER_SQLITE_TRUE@am__objects_64 = orm/driver/orm_driver_sqlite.lo -@STATIC_ORM_DRIVER_MYSQL_TRUE@am__objects_65 = \ +@STATIC_ORM_DRIVER_SQLITE_TRUE@am__objects_65 = orm/driver/orm_driver_sqlite.lo +@STATIC_ORM_DRIVER_MYSQL_TRUE@am__objects_66 = \ @STATIC_ORM_DRIVER_MYSQL_TRUE@ orm/driver/orm_driver_mysql.lo -@STATIC_ORM_DRIVER_PGSQL_TRUE@am__objects_66 = \ +@STATIC_ORM_DRIVER_PGSQL_TRUE@am__objects_67 = \ @STATIC_ORM_DRIVER_PGSQL_TRUE@ orm/driver/orm_driver_pgsql.lo -am__objects_67 = -am__objects_68 = internal/common.lo internal/error.lo \ +am__objects_68 = +am__objects_69 = internal/common.lo internal/error.lo \ internal/memory_pool.lo ui/dialog.lo db/cdb.lo db/rdb.lo \ dynamic/dynamic.lo dynamic/plugin.lo mime/header.lo \ mime/entity.lo mime/multipart.lo container/vector.lo \ @@ -445,9 +448,10 @@ am__objects_68 = internal/common.lo internal/error.lo \ $(am__objects_56) $(am__objects_57) $(am__objects_58) \ $(am__objects_59) $(am__objects_60) $(am__objects_61) \ $(am__objects_62) $(am__objects_63) $(am__objects_64) \ - $(am__objects_65) $(am__objects_66) $(am__objects_67) + $(am__objects_65) $(am__objects_66) $(am__objects_67) \ + $(am__objects_68) @FINAL_FALSE@am_lib@ULIB@_la_OBJECTS = $(am__objects_26) \ -@FINAL_FALSE@ $(am__objects_68) +@FINAL_FALSE@ $(am__objects_69) @FINAL_TRUE@am_lib@ULIB@_la_OBJECTS = all_c.lo all_cpp.lo lib@ULIB@_la_OBJECTS = $(am_lib@ULIB@_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) @@ -581,7 +585,7 @@ am__depfiles_remade = ./$(DEPDIR)/all_c.Plo ./$(DEPDIR)/all_cpp.Plo \ utility/$(DEPDIR)/semaphore.Plo utility/$(DEPDIR)/services.Plo \ utility/$(DEPDIR)/socket_ext.Plo \ utility/$(DEPDIR)/string_ext.Plo utility/$(DEPDIR)/uhttp.Plo \ - utility/$(DEPDIR)/websocket.Plo \ + utility/$(DEPDIR)/uquic.Plo utility/$(DEPDIR)/websocket.Plo \ xml/expat/$(DEPDIR)/attribute.Plo \ xml/expat/$(DEPDIR)/element.Plo \ xml/expat/$(DEPDIR)/xml2txt.Plo \ @@ -918,15 +922,15 @@ SRC_C = base/base.c base/base_error.c base/hash.c base/utility.c \ base/miniz/miniz.c base/coder/cbase64.c \ base/coder/cquoted_printable.c base/coder/curl_coder.c \ base/coder/cxml_coder.c base/coder/cescape.c \ - base/coder/chexdump.c $(am__append_7) $(am__append_10) \ - $(am__append_11) $(am__append_12) $(am__append_13) \ - $(am__append_14) $(am__append_15) $(am__append_16) \ - $(am__append_17) $(am__append_18) $(am__append_19) \ - $(am__append_20) $(am__append_21) $(am__append_22) \ - $(am__append_23) $(am__append_24) $(am__append_25) \ - $(am__append_26) $(am__append_27) $(am__append_28) \ - $(am__append_29) $(am__append_30) $(am__append_32) \ - $(am__append_35) $(am__append_46) + base/coder/chexdump.c $(am__append_8) $(am__append_11) \ + $(am__append_12) $(am__append_13) $(am__append_14) \ + $(am__append_15) $(am__append_16) $(am__append_17) \ + $(am__append_18) $(am__append_19) $(am__append_20) \ + $(am__append_21) $(am__append_22) $(am__append_23) \ + $(am__append_24) $(am__append_25) $(am__append_26) \ + $(am__append_27) $(am__append_28) $(am__append_29) \ + $(am__append_30) $(am__append_31) $(am__append_33) \ + $(am__append_36) $(am__append_47) SRC_CPP = internal/common.cpp internal/error.cpp \ internal/memory_pool.cpp ui/dialog.cpp db/cdb.cpp db/rdb.cpp \ dynamic/dynamic.cpp dynamic/plugin.cpp mime/header.cpp \ @@ -958,20 +962,20 @@ SRC_CPP = internal/common.cpp internal/error.cpp \ application.cpp cache.cpp date.cpp url.cpp tokenizer.cpp \ command.cpp $(am__append_1) $(am__append_2) $(am__append_3) \ $(am__append_4) $(am__append_5) $(am__append_6) \ - $(am__append_8) $(am__append_9) $(am__append_31) \ - $(am__append_33) $(am__append_34) $(am__append_36) \ + $(am__append_7) $(am__append_9) $(am__append_10) \ + $(am__append_32) $(am__append_34) $(am__append_35) \ $(am__append_37) $(am__append_38) $(am__append_39) \ $(am__append_40) $(am__append_41) $(am__append_42) \ $(am__append_43) $(am__append_44) $(am__append_45) \ - $(am__append_47) $(am__append_48) $(am__append_49) \ + $(am__append_46) $(am__append_48) $(am__append_49) \ $(am__append_50) $(am__append_51) $(am__append_52) \ $(am__append_53) $(am__append_54) $(am__append_55) \ $(am__append_56) $(am__append_57) $(am__append_58) \ $(am__append_59) $(am__append_60) $(am__append_61) \ $(am__append_62) $(am__append_63) $(am__append_64) \ - $(am__append_65) $(am__append_68) -lib@ULIB@_la_LDFLAGS = @ULIB_LIBS@ $(am__append_66) -version-info \ - 1:0:0 -release @ULIB_VERSION@ $(am__append_67) + $(am__append_65) $(am__append_66) $(am__append_69) +lib@ULIB@_la_LDFLAGS = @ULIB_LIBS@ $(am__append_67) -version-info \ + 1:0:0 -release @ULIB_VERSION@ $(am__append_68) @MINGW_TRUE@lib@ULIB@_la_DEPENDENCIES = ULib-win32-res.o @FINAL_FALSE@lib@ULIB@_la_SOURCES = $(SRC_C) $(SRC_CPP) @FINAL_TRUE@lib@ULIB@_la_SOURCES = all_c.c all_cpp.cpp @@ -1402,6 +1406,8 @@ utility/http2.lo: utility/$(am__dirstamp) \ utility/$(DEPDIR)/$(am__dirstamp) utility/http3.lo: utility/$(am__dirstamp) \ utility/$(DEPDIR)/$(am__dirstamp) +utility/uquic.lo: utility/$(am__dirstamp) \ + utility/$(DEPDIR)/$(am__dirstamp) internal/objectIO.lo: internal/$(am__dirstamp) \ internal/$(DEPDIR)/$(am__dirstamp) debug/$(am__dirstamp): @@ -1887,6 +1893,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@utility/$(DEPDIR)/socket_ext.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utility/$(DEPDIR)/string_ext.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utility/$(DEPDIR)/uhttp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@utility/$(DEPDIR)/uquic.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utility/$(DEPDIR)/websocket.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@xml/expat/$(DEPDIR)/attribute.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@xml/expat/$(DEPDIR)/element.Plo@am__quote@ # am--include-marker @@ -2491,6 +2498,7 @@ distclean: distclean-recursive -rm -f utility/$(DEPDIR)/socket_ext.Plo -rm -f utility/$(DEPDIR)/string_ext.Plo -rm -f utility/$(DEPDIR)/uhttp.Plo + -rm -f utility/$(DEPDIR)/uquic.Plo -rm -f utility/$(DEPDIR)/websocket.Plo -rm -f xml/expat/$(DEPDIR)/attribute.Plo -rm -f xml/expat/$(DEPDIR)/element.Plo @@ -2718,6 +2726,7 @@ maintainer-clean: maintainer-clean-recursive -rm -f utility/$(DEPDIR)/socket_ext.Plo -rm -f utility/$(DEPDIR)/string_ext.Plo -rm -f utility/$(DEPDIR)/uhttp.Plo + -rm -f utility/$(DEPDIR)/uquic.Plo -rm -f utility/$(DEPDIR)/websocket.Plo -rm -f xml/expat/$(DEPDIR)/attribute.Plo -rm -f xml/expat/$(DEPDIR)/element.Plo diff --git a/src/ulib/all_cpp.cpp b/src/ulib/all_cpp.cpp index 75f08b45..f7d71abe 100644 --- a/src/ulib/all_cpp.cpp +++ b/src/ulib/all_cpp.cpp @@ -112,6 +112,7 @@ # include "utility/http2.cpp" # endif # ifndef U_HTTP3_DISABLE +# include "utility/uquic.cpp" # include "utility/http3.cpp" # endif # ifdef ENABLE_ZIP diff --git a/src/ulib/net/server/server.cpp b/src/ulib/net/server/server.cpp index f97d2023..0d5f7244 100644 --- a/src/ulib/net/server/server.cpp +++ b/src/ulib/net/server/server.cpp @@ -4945,7 +4945,7 @@ void UServer_Base::logNewClient() setClientAddress(); #ifndef U_HTTP3_DISABLE - U_INTERNAL_DUMP("UHTTP3::conn_id = %M", UHTTP3::conn_id, UHTTP3::conn_id_len) + U_INTERNAL_DUMP("UQuic::conn_id = %M", UQuic::conn_id, UQuic::conn_id_len) #endif #ifndef U_LOG_DISABLE @@ -5456,9 +5456,9 @@ void UServer_Base::runLoop(const char* user) rbuffer->size_adjust_force(result); - if (UHTTP3::parseHeader() == false) goto next; + if (UQuic::parseHeader() == false) goto next; - if ((blookup = UHTTP3::lookup()) == false) + if ((blookup = UQuic::lookup()) == false) { logNewClient(); @@ -5468,7 +5468,7 @@ void UServer_Base::runLoop(const char* user) if (pthis->handlerAccept(-1) == false) goto next; - pClientImage->conn = UHTTP3::conn; + pClientImage->conn = UQuic::conn; pClientImage->http3 = UHTTP3::http3; pClientImage->socket->setFd(pClientImage->fd = fds[0]); @@ -5482,7 +5482,7 @@ void UServer_Base::runLoop(const char* user) U_DUMP("result = %d csocket->isClosed() = %b U_ClientImage_close = %b", result, csocket->isClosed(), U_ClientImage_close) - // if (blookup == false) UHTTP3::insert(); + // if (blookup == false) UQuic::insert(); } next: prepareOperation(UClientImage_Base::_RECVMSG); diff --git a/src/ulib/string.cpp b/src/ulib/string.cpp index 54cf641f..9d92e555 100644 --- a/src/ulib/string.cpp +++ b/src/ulib/string.cpp @@ -114,7 +114,7 @@ const UString* UString::str_pgsql_name; const UString* UString::str_sqlite_name; const UString* UString::str_dbdir; const UString* UString::str_memory; -#ifndef U_HTTP2_DISABLE +#if !defined(U_HTTP2_DISABLE) || !defined(U_HTTP3_DISABLE) const UString* UString::str_authority; const UString* UString::str_method; const UString* UString::str_method_get; @@ -181,10 +181,10 @@ const UString* UString::str_www_authenticate; const UString* UString::str_ULib; #endif -#ifdef U_HTTP2_DISABLE -static ustringrep stringrep_storage[75] = { -#else +#if !defined(U_HTTP2_DISABLE) || !defined(U_HTTP3_DISABLE) static ustringrep stringrep_storage[139] = { +#else +static ustringrep stringrep_storage[75] = { #endif { U_STRINGREP_FROM_CONSTANT("host") }, { U_STRINGREP_FROM_CONSTANT("chunked") }, @@ -270,7 +270,7 @@ static ustringrep stringrep_storage[139] = { { U_STRINGREP_FROM_CONSTANT("auto-reconnect") }, // ORM PGSQL { U_STRINGREP_FROM_CONSTANT("pgsql") }, -#ifndef U_HTTP2_DISABLE +#if !defined(U_HTTP2_DISABLE) || !defined(U_HTTP3_DISABLE) { U_STRINGREP_FROM_CONSTANT(":authority") }, { U_STRINGREP_FROM_CONSTANT(":method") }, { U_STRINGREP_FROM_CONSTANT("GET") }, @@ -530,7 +530,7 @@ void UString::str_allocate(int which) U_NEW_ULIB_STRING(str_auto_reconnect, UString(stringrep_storage+STR_ALLOCATE_INDEX_ORM+13)); U_NEW_ULIB_STRING(str_pgsql_name, UString(stringrep_storage+STR_ALLOCATE_INDEX_ORM+14)); } -#ifndef U_HTTP2_DISABLE +#if !defined(U_HTTP2_DISABLE) || !defined(U_HTTP3_DISABLE) else if ((which & STR_ALLOCATE_HTTP2) != 0) { U_INTERNAL_ASSERT_EQUALS(str_authority, U_NULLPTR) diff --git a/src/ulib/utility/http2.cpp b/src/ulib/utility/http2.cpp index 8f6f8cf8..2bd40271 100644 --- a/src/ulib/utility/http2.cpp +++ b/src/ulib/utility/http2.cpp @@ -160,9 +160,9 @@ UHTTP2::Connection::Connection() : itable(64, setIndexStaticTable) hpack_error[i].desc = d #endif -void UHTTP2::ctor() +void UHTTP2::buildTable() { - U_TRACE_NO_PARAM(0+256, "UHTTP2::ctor()") + U_TRACE_NO_PARAM(0+256, "UHTTP2::buildTable()") UString::str_allocate(STR_ALLOCATE_HTTP2); @@ -293,6 +293,13 @@ void UHTTP2::ctor() hash_static_table[59] = UString::str_via->hashIgnoreCase(); hpack_static_table[60].name = UString::str_www_authenticate->rep; hash_static_table[60] = UString::str_www_authenticate->hashIgnoreCase(); +} + +void UHTTP2::ctor() +{ + U_TRACE_NO_PARAM(0+256, "UHTTP2::ctor()") + + buildTable(); #ifdef DEBUG if (btest) @@ -3084,7 +3091,8 @@ void UHTTP2::downgradeRequest() if (sz) { if (U_http_content_type_len) UClientImage_Base::request->snprintf_add(U_CONSTANT_TO_PARAM("Content-Type: %.*s\r\n"), U_HTTP_CTYPE_TO_TRACE); - UClientImage_Base::request->snprintf_add(U_CONSTANT_TO_PARAM("Content-Length: %u\r\n"), sz); + + UClientImage_Base::request->snprintf_add(U_CONSTANT_TO_PARAM("Content-Length: %u\r\n"), sz); } pConnection->itable.callForAllEntry(copyHeaders); @@ -3583,7 +3591,7 @@ process_request: U_SRV_LOG_WITH_ADDR("send response (HTTP2,id:%u,bytes:%u) %#.*S to", pStream->id, sz0, sz0, ptr0); - if (USocketExt::write(UServer_Base::csocket, ptr0, sz0, 0) != (int)sz0) nerror = CONNECT_ERROR; + if (USocketExt::write(UServer_Base::csocket, ptr0, sz0, 0) != sz0) nerror = CONNECT_ERROR; # ifdef DEBUG // (void) UFile::writeToTmp(ptr0, sz0, O_RDWR | O_TRUNC, U_CONSTANT_TO_PARAM("load_balance_response.%P"), 0); diff --git a/src/ulib/utility/http3.cpp b/src/ulib/utility/http3.cpp index 245cca16..60b0018c 100644 --- a/src/ulib/utility/http3.cpp +++ b/src/ulib/utility/http3.cpp @@ -7,330 +7,90 @@ // http3.cpp - HTTP/3 utility // // = AUTHOR -// Stefano Casazza +// Stefano Casazza + Victor Stewart // // ============================================================================ #include #include -size_t UHTTP3::scid_len; -size_t UHTTP3::token_len; -size_t UHTTP3::conn_id_len; -uint8_t UHTTP3::pkt_type; -uint8_t UHTTP3::token[U_MAX_TOKEN_LEN]; -uint8_t UHTTP3::scid[QUICHE_MAX_CONN_ID_LEN]; -uint8_t UHTTP3::conn_id[QUICHE_MAX_CONN_ID_LEN]; -uint32_t UHTTP3::pkt_version; -uint32_t UHTTP3::headers_len; -uint32_t UHTTP3::peer_addr_len; -quiche_conn* UHTTP3::conn; -quiche_config* UHTTP3::qconfig; -quiche_h3_conn* UHTTP3::http3; -quiche_h3_header* UHTTP3::headers; -quiche_h3_config* UHTTP3::http3_config; - -struct sockaddr_storage UHTTP3::peer_addr; -UHashMap* UHTTP3::peers; +uint32_t UHTTP3::headers_len; +quiche_h3_conn* UHTTP3::http3; +quiche_h3_header* UHTTP3::headers; +quiche_h3_config* UHTTP3::http3_config; +UHashMap* UHTTP3::itable; // headers request int UHTTP3::loadConfigParam() { U_TRACE_NO_PARAM(0, "UHTTP3::loadConfigParam()") - U_INTERNAL_ASSERT(UServer_Base::budp) - U_INTERNAL_ASSERT_POINTER(UServer_Base::pcfg) - -#ifndef USE_LIBQUICHE - U_ERROR("Sorry, I was compiled without libquiche so there isn't HTTP/3 support"); -#endif - - if (UServer_Base::key_file->empty() || - UServer_Base::cert_file->empty()) + if (UQuic::loadConfigParam() == U_PLUGIN_HANDLER_OK) { - U_ERROR("You need to specify in configuration file the property KEY_FILE and CERT_FILE"); - } + // Stores configuration shared between multiple connections + http3_config = (quiche_h3_config*) U_SYSCALL_NO_PARAM(quiche_h3_config_new); // Creates an HTTP/3 config object with default settings values -#ifdef DEBUG -// (void) U_SYSCALL(quiche_enable_debug_logging, "%p,%p", quiche_debug_log, U_NULLPTR); -#endif - - // Stores configuration shared between multiple connections - qconfig = (quiche_config*) U_SYSCALL(quiche_config_new, "%u", QUICHE_PROTOCOL_VERSION); - http3_config = (quiche_h3_config*) U_SYSCALL_NO_PARAM(quiche_h3_config_new); // Creates an HTTP/3 config object with default settings values - - if (qconfig == U_NULLPTR || - http3_config == U_NULLPTR) - { - U_ERROR("Failed to create quiche/HTTP3 config"); - } - - // Configures the given certificate chain - (void) U_SYSCALL(quiche_config_load_cert_chain_from_pem_file, "%p,%S", qconfig, UServer_Base::cert_file->data()); - - // Configures the given private key - (void) U_SYSCALL(quiche_config_load_priv_key_from_pem_file, "%p,%S", qconfig, UServer_Base::key_file->data()); - - // Configures the list of supported application protocols - (void) U_SYSCALL(quiche_config_set_application_protos, "%p,%p,%u", qconfig, (uint8_t*)U_CONSTANT_TO_PARAM(QUICHE_H3_APPLICATION_PROTOCOL)); - - if (UServer_Base::pcfg->searchForObjectStream(U_CONSTANT_TO_PARAM("http3"))) - { - UServer_Base::pcfg->table.clear(); - - if (UServer_Base::pcfg->loadTable()) + if (http3_config == U_NULLPTR) { - // -------------------------------------------------------------------------------------------------------------------------------------- - // userver_udp - http3 configuration parameters - // -------------------------------------------------------------------------------------------------------------------------------------- - // QUICHE_GREASE Whether to send GREASE - // QUICHE_LOG_KEYS Enables logging of secrets - // QUICHE_VERIFY_PEER Whether to verify the peer's certificate - // QUICHE_CC_ALGORITHM Sets the congestion control algorithm used - // QUICHE_MAX_ACK_DELAY Sets the `max_ack_delay` transport parameter - // QUICHE_MAX_PACKET_SIZE Sets the max_packet_size transport parameter - // QUICHE_MAX_IDLE_TIMEOUT Sets the `max_idle_timeout` transport parameter - // QUICHE_INITIAL_MAX_DATA Sets the `initial_max_data` transport parameter - // QUICHE_ENABLE_EARLY_DATA Enables sending or receiving early data - // QUICHE_ACK_DELAY_EXPONENT Sets the `ack_delay_exponent` transport parameter - // QUICHE_MAX_UDP_PAYLOAD_SIZE Sets the `max_udp_payload_size` transport parameter - // QUICHE_INITIAL_MAX_STREAM_UNI Sets the `initial_max_streams_uni` transport parameter - // QUICHE_DISABLE_ACTIVE_MIGRATION Sets the `disable_active_migration` transport parameter - // QUICHE_INITIAL_MAX_STREAMS_BIDI Sets the `initial_max_streams_bidi` transport parameter - // QUICHE_INITIAL_MAX_STREAM_DATA_UNI Sets the `initial_max_stream_data_uni` transport parameter - // QUICHE_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL Sets the `initial_max_stream_data_bidi_local` transport parameter - // QUICHE_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE Sets the `initial_max_stream_data_bidi_remote` transport parameter - // - // QUICHE_H3_MAX_HEADER_LIST_SIZE Sets the `SETTINGS_MAX_HEADER_LIST_SIZE` setting - // QUICHE_H3_QPACK_BLOCKED_STREAMS Sets the `SETTINGS_QPACK_BLOCKED_STREAMS` setting - // QUICHE_H3_QPACK_MAX_TABLE_CAPACITY Sets the `SETTINGS_QPACK_BLOCKED_STREAMS` setting - // -------------------------------------------------------------------------------------------------------------------------------------- + U_ERROR("Failed to create HTTP3 config"); + } - long param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_MAX_IDLE_TIMEOUT"), 180000); - bool param1 = UServer_Base::pcfg->readBoolean(U_CONSTANT_TO_PARAM("QUICHE_DISABLE_ACTIVE_MIGRATION"), true); + // Configures the list of supported application protocols + (void) U_SYSCALL(quiche_config_set_application_protos, "%p,%p,%u", UQuic::qconfig, (uint8_t*)U_CONSTANT_TO_PARAM(QUICHE_H3_APPLICATION_PROTOCOL)); - U_SYSCALL_VOID(quiche_config_set_max_idle_timeout, "%p,%lu", qconfig, param0); - U_SYSCALL_VOID(quiche_config_set_disable_active_migration, "%p,%b", qconfig, param1); + if (UServer_Base::pcfg->searchForObjectStream(U_CONSTANT_TO_PARAM("http3"))) + { + UServer_Base::pcfg->table.clear(); - param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_CC_ALGORITHM"), 0); // QUICHE_CC_RENO = 0 + if (UServer_Base::pcfg->loadTable()) + { + // -------------------------------------------------------------------------------------------------------------------------------------- + // userver_udp - http3 configuration parameters + // -------------------------------------------------------------------------------------------------------------------------------------- + // QUICHE_H3_MAX_HEADER_LIST_SIZE Sets the `SETTINGS_MAX_HEADER_LIST_SIZE` setting + // QUICHE_H3_QPACK_BLOCKED_STREAMS Sets the `SETTINGS_QPACK_BLOCKED_STREAMS` setting + // QUICHE_H3_QPACK_MAX_TABLE_CAPACITY Sets the `SETTINGS_QPACK_BLOCKED_STREAMS` setting + // -------------------------------------------------------------------------------------------------------------------------------------- - U_SYSCALL_VOID(quiche_config_set_cc_algorithm, "%p,%lu", qconfig, (quiche_cc_algorithm)param0); + /* + long param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_H3_MAX_HEADER_LIST_SIZE"), 16384); -# ifdef LIBQUICHE_AT_LEAST_0_5 - param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_MAX_UDP_PAYLOAD_SIZE"), U_MAX_DATAGRAM_SIZE); + U_SYSCALL_VOID(quiche_h3_config_set_max_header_list_size, "%p,%lu", http3_config, param0); + */ - U_SYSCALL_VOID(quiche_config_set_max_udp_payload_size, "%p,%lu", qconfig, param0); -# else - param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_MAX_PACKET_SIZE"), U_MAX_DATAGRAM_SIZE); + /** TODO - U_SYSCALL_VOID(quiche_config_set_max_packet_size, "%p,%lu", qconfig, param0); -# endif + param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_H3_QPACK_BLOCKED_STREAMS"), ???); - param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_INITIAL_MAX_DATA"), 10485760); + U_SYSCALL_VOID(quiche_h3_config_set_qpack_blocked_streams, "%p,%lu", http3_config, param0); - U_SYSCALL_VOID(quiche_config_set_initial_max_data, "%p,%lu", qconfig, param0); + param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_H3_QPACK_MAX_TABLE_CAPACITY"), ???); - param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_INITIAL_MAX_STREAM_UNI"), 3); // For HTTP/3 we only need 3 unidirectional streams + U_SYSCALL_VOID(quiche_h3_config_set_qpack_max_table_capacity, "%p,%lu", http3_config, param0); + */ - U_SYSCALL_VOID(quiche_config_set_initial_max_streams_uni, "%p,%lu", qconfig, param0); - - param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_INITIAL_MAX_STREAMS_BIDI"), 128); - - U_SYSCALL_VOID(quiche_config_set_initial_max_streams_bidi, "%p,%lu", qconfig, param0); - - param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_INITIAL_MAX_STREAM_DATA_UNI"), 1048576); - - U_SYSCALL_VOID(quiche_config_set_initial_max_stream_data_uni, "%p,%lu", qconfig, param0); - - param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL"), 1000000); - - U_SYSCALL_VOID(quiche_config_set_initial_max_stream_data_bidi_local, "%p,%lu", qconfig, param0); - - param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE"), 1048576); - - U_SYSCALL_VOID(quiche_config_set_initial_max_stream_data_bidi_remote, "%p,%lu", qconfig, param0); - - /* - param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_MAX_ACK_DELAY"), 25); - - U_SYSCALL_VOID(quiche_config_set_max_ack_delay, "%p,%lu", qconfig, param0); - - param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_ACK_DELAY_EXPONENT"), 3); - - U_SYSCALL_VOID(quiche_config_set_ack_delay_exponent, "%p,%lu", qconfig, param0); - - param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_H3_MAX_HEADER_LIST_SIZE"), 16384); - - U_SYSCALL_VOID(quiche_h3_config_set_max_header_list_size, "%p,%lu", http3_config, param0); - */ - - if (UServer_Base::pcfg->readBoolean(U_CONSTANT_TO_PARAM("QUICHE_ENABLE_EARLY_DATA"), false)) U_SYSCALL_VOID(quiche_config_enable_early_data, "%p", qconfig); - - /** TODO - - void quiche_config_log_keys(quiche_config *config); - void quiche_config_grease(quiche_config *config, bool v); - void quiche_config_verify_peer(quiche_config *config, bool v); - - param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_H3_QPACK_BLOCKED_STREAMS"), ???); - - U_SYSCALL_VOID(quiche_h3_config_set_qpack_blocked_streams, "%p,%lu", http3_config, param0); - - param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_H3_QPACK_MAX_TABLE_CAPACITY"), ???); - - U_SYSCALL_VOID(quiche_h3_config_set_qpack_max_table_capacity, "%p,%lu", http3_config, param0); - */ - - UServer_Base::pcfg->reset(); + UServer_Base::pcfg->reset(); + } } } U_RETURN(U_PLUGIN_HANDLER_OK); } -bool UHTTP3::parseHeader() +int UHTTP3::for_each_header(uint8_t* name, size_t name_len, uint8_t* value, size_t value_len, void* argp) { - U_TRACE_NO_PARAM(0, "UHTTP3::parseHeader()") + U_TRACE(0, "UHTTP3::for_each_header(%.*S,%u,%.*S,%u,%p)", name_len, name, name_len, value_len, value, value_len, argp) - // Parse the QUIC packet's header + /* + * quiche: got HTTP header: ":method"(7)="GET"(3) + * quiche: got HTTP header: ":scheme"(7)="https"(5) + * quiche: got HTTP header: ":authority"(10)="127.0.0.1"(9) + * quiche: got HTTP header: ":path"(5)="/"(1) + * quiche: got HTTP header: "user-agent"(10)="quiche"(6) + */ - scid_len = - conn_id_len = QUICHE_MAX_CONN_ID_LEN; - token_len = U_MAX_TOKEN_LEN; + U_INTERNAL_DUMP("quiche: got HTTP header: %.*S(%u)=%.*S(%u)", name_len, name, name_len, value_len, value, value_len) - // Extracts version, type, source / destination connection ID and address verification token from the packet in buffer - int rc = U_SYSCALL(quiche_header_info, "%p,%u,%u,%p,%p,%p,%p,%p,%p,%p,%p", (const uint8_t*)U_STRING_TO_PARAM(*UServer_Base::rbuffer), U_LOCAL_CONN_ID_LEN, - &pkt_version, &pkt_type, scid, &scid_len, conn_id, &conn_id_len, token, &token_len); - - if (rc < 0) - { - U_DEBUG("UHTTP3::handlerRead(): failed to parse header: %d", rc) - - U_RETURN(false); - } - - U_INTERNAL_DUMP("scid(%u) = %#.*S token(%u) = %#.*S conn_id(%u) = %#.*S pkt_version = %p pkt_type = %u", - scid_len, scid_len, scid, token_len, token_len, token, conn_id_len, conn_id_len, conn_id, pkt_version, pkt_type) - - U_RETURN(true); -} - -bool UHTTP3::handlerRead(quiche_conn* lconn, bool bwait_for_data) -{ - U_TRACE(0, "UHTTP3::handlerRead(%p,%b)", lconn, bwait_for_data) - - U_ASSERT_EQUALS(UClientImage_Base::rbuffer->capacity(), UServer_Base::rbuffer_size) - - int iBytesRead; - char* ptr = UServer_Base::rbuffer->data(); - - // Read incoming UDP packets from the socket and feed them to quiche, until there are no more packets to read - -loop: - peer_addr_len = sizeof(peer_addr); - - (void) U_SYSCALL(memset, "%p,%u,%u", &peer_addr, 0, U_SIZE_SOCKADDR); - - iBytesRead = U_SYSCALL(recvfrom, "%d,%p,%u,%u,%p,%p", UServer_Base::fds[0], ptr, UServer_Base::rbuffer_size, (bwait_for_data ? 0 : MSG_DONTWAIT), - (struct sockaddr*)&peer_addr, &peer_addr_len); - - if (iBytesRead <= 0) - { - if (errno == EAGAIN) - { - U_DEBUG("quiche: recvfrom would block") - - U_INTERNAL_ASSERT_EQUALS(bwait_for_data, false) - - if (lconn) // reported no read packets, we will then proceed with the send loop - { - uint8_t out[65536]; - ssize_t written, sent; - uint32_t start = 0, remain = sizeof(out); - - while (true) - { - written = U_SYSCALL(quiche_conn_send, "%p,%p,%u", lconn, &out[start], remain); - - if (written == QUICHE_ERR_DONE) - { - U_DEBUG("quiche: done writing") - - break; - } - - if (written < 0) - { - U_DEBUG("UHTTP3::handlerRead(): failed to create packet: %d", written) - - break; - } - - start += written; - remain -= written; - - U_INTERNAL_ASSERT_MINOR(start, sizeof(out)) - - U_DEBUG("quiche: sent %u bytes", written) - } - - sent = U_SYSCALL(sendto, "%d,%p,%u,%u,%p,%d", UServer_Base::fds[0], out, start, 0, (struct sockaddr*)&USocket::peer_addr, USocket::peer_addr_len); - - if (sent != start) - { - U_DEBUG("UHTTP3::handlerRead(): failed to send") - - U_RETURN(false); - } - - if (U_SYSCALL(quiche_conn_is_closed, "%p", lconn)) - { - quiche_stats stats; - - U_SYSCALL_VOID(quiche_conn_stats, "%p,%p", lconn, &stats); - - U_DEBUG("quiche: connection closed, recv=%u sent=%u lost=%u rtt=%u cwnd=%u", stats.recv, stats.sent, stats.lost, stats.rtt, stats.cwnd) - - U_SYSCALL_VOID(quiche_conn_free, "%p", lconn); - - U_RETURN(false); - } - } - - bwait_for_data = true; - - goto loop; - } - - U_WARNING("recvfrom on fd %d got %d%R", UServer_Base::fds[0], iBytesRead, 0); // NB: the last argument (0) is necessary... - - if (errno == EINTR) UInterrupt::checkForEventSignalPending(); - - U_RETURN(false); - } - - U_INTERNAL_DUMP("peer_addr_len = %u BytesRead(%u) = %#.*S", peer_addr_len, iBytesRead, iBytesRead, ptr) - - U_INTERNAL_ASSERT_MAJOR(peer_addr_len, 0) - - UServer_Base::rbuffer->size_adjust_force(iBytesRead); - - if (memcmp(&peer_addr, &USocket::peer_addr, peer_addr_len) != 0) - { - // TODO - - U_WARNING("recvfrom() different address"); - - /* Lookup a connection based on the packet's connection ID. If there is no connection matching, create a new one - - if (lookup()) - { - } - */ - } - - if (lconn || parseHeader()) U_RETURN(true); - - U_RETURN(false); + U_RETURN(0); } void UHTTP3::handlerRequest(quiche_conn* lconn, quiche_h3_conn* lh3) @@ -351,8 +111,8 @@ void UHTTP3::handlerRequest(quiche_conn* lconn, quiche_h3_conn* lh3) if (s < 0) { - if (handlerRead(lconn, true) && - processesPackets(lconn)) + if (UQuic::handlerRead(lconn, true) && + UQuic::processesPackets(lconn)) { continue; } @@ -360,12 +120,22 @@ void UHTTP3::handlerRequest(quiche_conn* lconn, quiche_h3_conn* lh3) break; } + U_INTERNAL_DUMP("quiche_h3_event_type(ev) = %d", quiche_h3_event_type(ev)) + switch (quiche_h3_event_type(ev)) { case QUICHE_H3_EVENT_HEADERS: { + if (itable->empty() == false) + { + U_DUMP_CONTAINER(*itable) + + itable->clear(); + } + // Iterates over the headers in the event. The `cb` callback will be called for each header in `ev`. `cb` should check the validity of // pseudo-headers and headers. If `cb` returns any value other than `0`, processing will be interrupted and the value is returned to the caller + rc = U_SYSCALL(quiche_h3_event_for_each_header, "%p,%p,%p", ev, for_each_header, 0); if (rc != 0) @@ -373,11 +143,14 @@ void UHTTP3::handlerRequest(quiche_conn* lconn, quiche_h3_conn* lh3) U_DEBUG("UHTTP3::handlerRequest(): failed to process headers: %d", rc) } - // Sends an HTTP/3 response on the specified stream - (void) U_SYSCALL(quiche_h3_send_response, "%p,%p,%lu,%p,%p,%b", lh3, lconn, s, headers, headers_len, false); - - // Sends an HTTP/3 body chunk on the given stream. - (void) U_SYSCALL(quiche_h3_send_body, "%p,%p,%lu,%p,%p", lh3, lconn, s, (uint8_t*)U_STRING_TO_PARAM(*UHTTP::body), true); + U_INTERNAL_DUMP("Host = %.*S", U_HTTP_HOST_TO_TRACE) + U_INTERNAL_DUMP("Range = %.*S", U_HTTP_RANGE_TO_TRACE) + U_INTERNAL_DUMP("Accept = %.*S", U_HTTP_ACCEPT_TO_TRACE) + U_INTERNAL_DUMP("Cookie = %.*S", U_HTTP_COOKIE_TO_TRACE) + U_INTERNAL_DUMP("Referer = %.*S", U_HTTP_REFERER_TO_TRACE) + U_INTERNAL_DUMP("User-Agent = %.*S", U_HTTP_USER_AGENT_TO_TRACE) + U_INTERNAL_DUMP("Content-Type = %.*S", U_HTTP_CTYPE_TO_TRACE) + U_INTERNAL_DUMP("Accept-Language = %.*S", U_HTTP_ACCEPT_LANGUAGE_TO_TRACE) break; } @@ -390,7 +163,16 @@ void UHTTP3::handlerRequest(quiche_conn* lconn, quiche_h3_conn* lh3) } case QUICHE_H3_EVENT_FINISHED: - break; + { + /* Sends an HTTP/3 response on the specified stream + (void) U_SYSCALL(quiche_h3_send_response, "%p,%p,%lu,%p,%p,%b", lh3, lconn, s, headers, headers_len, false); + + // Sends an HTTP/3 body chunk on the given stream. + (void) U_SYSCALL(quiche_h3_send_body, "%p,%p,%lu,%p,%p", lh3, lconn, s, (uint8_t*)U_STRING_TO_PARAM(*UHTTP::body), true); + */ + + break; + } } U_SYSCALL_VOID(quiche_h3_event_free, "%p", ev); @@ -401,166 +183,21 @@ bool UHTTP3::handlerNewConnection() { U_TRACE_NO_PARAM(0, "UHTTP3::handlerNewConnection()") - U_INTERNAL_ASSERT_POINTER(peers) - U_INTERNAL_ASSERT(UServer_Base::budp) - - const char* ptr; - ssize_t written, sent; - const char* pkt = "vneg"; - uint8_t out[U_MAX_DATAGRAM_SIZE]; - - conn = U_NULLPTR; http3 = U_NULLPTR; -loop: - if (pkt_type != Initial) + if (UQuic::handlerNewConnection()) { - U_DEBUG("UHTTP3::handlerNewConnection(): packet is NOT initial: %u", pkt_type) + // Creates a new HTTP/3 connection using the provided QUIC connection + http3 = (quiche_h3_conn*) U_SYSCALL(quiche_h3_conn_new_with_transport, "%p,%p", UQuic::conn, http3_config); - U_RETURN(false); - } - - // Client Initial packets must be at least 1200 bytes - if (UServer_Base::rbuffer->size() < QUICHE_MIN_CLIENT_INITIAL_LEN) - { - U_DEBUG("UHTTP3::handlerNewConnection(): quic initial packet is too short: %u", UServer_Base::rbuffer->size()) - - U_RETURN(false); - } - - // Returns true if the given protocol version is supported - if (U_SYSCALL(quiche_version_is_supported, "%u", pkt_version) == false) - { - U_DEBUG("quiche: version negotiation") - - // Writes a version negotiation packet - written = U_SYSCALL(quiche_negotiate_version, "%p,%u,%p,%u,%p,%u", scid, scid_len, conn_id, conn_id_len, out, sizeof(out)); - -pkt: if (written < 0) + if (http3 == U_NULLPTR) { - U_DEBUG("UHTTP3::handlerNewConnection(): failed to create %S packet: %d", pkt, written) + U_DEBUG("UHTTP3::handlerNewConnection(): failed to create HTTP/3 connection") U_RETURN(false); } - sent = U_SYSCALL(sendto, "%u,%p,%u,%u,%p,%d", UServer_Base::fds[0], out, written, 0, (struct sockaddr*)&USocket::peer_addr, USocket::peer_addr_len); - - if (sent == written) - { - U_DEBUG("quiche: sent %u bytes", sent) - } - else - { - U_DEBUG("UHTTP3::handlerNewConnection(): failed to send") - - U_RETURN(false); - } - - if (handlerRead()) goto loop; - - U_RETURN(false); - } - - if (token_len == 0) - { - // Generate a stateless retry token. The token includes the static string "quiche" followed - // by the IP address of the client and by the original destination connection ID generated by the client - - U_DEBUG("quiche: stateless retry") - - U_INTERNAL_DUMP("USocket::peer_addr_len = %u", USocket::peer_addr_len) - - U_INTERNAL_ASSERT_MAJOR(conn_id_len, 0) - U_INTERNAL_ASSERT_MAJOR(USocket::peer_addr_len, 0) - - // 6 -> U_CONSTANT_SIZE("quiche") - U_MEMCPY(token, "quiche", 6); - U_MEMCPY(token + 6, &USocket::peer_addr, USocket::peer_addr_len); - U_MEMCPY(token + 6 + USocket::peer_addr_len, conn_id, conn_id_len); - - token_len = 6 + USocket::peer_addr_len + conn_id_len; - - U_INTERNAL_DUMP("scid(%u) = %.*S conn_id(%u) = %.*S token(%u) = %.*S pkt_version = %p", - scid_len, scid_len, scid, conn_id_len, conn_id_len, conn_id, token_len, token_len, token, pkt_version) - - // Writes a retry packet -# ifdef LIBQUICHE_AT_LEAST_0_5 - written = U_SYSCALL(quiche_retry, "%p,%u,%p,%u,%p,%u,%p,%u,%u,%p,%u", scid, scid_len, conn_id, conn_id_len, conn_id, conn_id_len, token, token_len, pkt_version, out, sizeof(out)); -# else - written = U_SYSCALL(quiche_retry, "%p,%u,%p,%u,%p,%u,%p,%u, %p,%u", scid, scid_len, conn_id, conn_id_len, conn_id, conn_id_len, token, token_len, out, sizeof(out)); -# endif - - pkt = "retry"; - - goto pkt; - } - - // Validates a stateless retry token. This checks that the ticket includes the `"quiche"` static string, and that the client IP address matches the address stored in the ticket - if (token_len < 6 || - memcmp(token, U_CONSTANT_TO_PARAM("quiche"))) - { - U_DEBUG("UHTTP3::handlerNewConnection(): invalid address validation token") - - U_RETURN(false); - } - - token_len -= 6; - - ptr = (const char*)&token[0] + 6; - - if (token_len < USocket::peer_addr_len || - memcmp(ptr, &USocket::peer_addr, USocket::peer_addr_len)) - { - U_DEBUG("UHTTP3::handlerNewConnection(): invalid address validation token") - - U_RETURN(false); - } - - ptr += USocket::peer_addr_len; - token_len -= USocket::peer_addr_len; - - if (conn_id_len != token_len) // The token was not valid, meaning the retry failed, so drop the packet - { - U_DEBUG("UHTTP3::handlerNewConnection(): invalid address validation token") - - U_RETURN(false); - } - - // Reuse the source connection ID we sent in the Retry packet, instead of changing it again. Creates a new server-side connection - conn = (quiche_conn*) U_SYSCALL(quiche_accept, "%p,%u,%p,%u,%p", conn_id, conn_id_len, (const uint8_t*)ptr, token_len, qconfig); - - if (conn == U_NULLPTR) - { - U_DEBUG("UHTTP3::handlerNewConnection(): failed to create connection") - - U_RETURN(false); - } - - U_DEBUG("quiche: new connection") - - while (processesPackets(conn)) - { - if (U_SYSCALL(quiche_conn_is_established, "%p", conn)) - { - U_DEBUG("UHTTP3::handlerNewConnection(): connection handshake is complete") - - if (http3 == U_NULLPTR) - { - // Creates a new HTTP/3 connection using the provided QUIC connection - http3 = (quiche_h3_conn*) U_SYSCALL(quiche_h3_conn_new_with_transport, "%p,%p", conn, http3_config); - - if (http3 == U_NULLPTR) - { - U_DEBUG("UHTTP3::handlerNewConnection(): failed to create HTTP/3 connection") - - U_RETURN(false); - } - } - - U_RETURN(true); - } - - if (handlerRead(conn) == false) U_RETURN(false); + U_RETURN(true); } U_RETURN(false); diff --git a/src/ulib/utility/uquic.cpp b/src/ulib/utility/uquic.cpp new file mode 100644 index 00000000..29bc9b46 --- /dev/null +++ b/src/ulib/utility/uquic.cpp @@ -0,0 +1,463 @@ +// ============================================================================ +// +// = LIBRARY +// ULib - c++ library +// +// = FILENAME +// uquic.cpp - Quic utility +// +// = AUTHOR +// Stefano Casazza + Victor Stewart +// +// ============================================================================ + +#include + +size_t UQuic::scid_len; +size_t UQuic::token_len; +size_t UQuic::conn_id_len; +uint8_t UQuic::pkt_type; +uint8_t UQuic::token[U_MAX_TOKEN_LEN]; +uint8_t UQuic::scid[QUICHE_MAX_CONN_ID_LEN]; +uint8_t UQuic::conn_id[QUICHE_MAX_CONN_ID_LEN]; +uint32_t UQuic::pkt_version; +uint32_t UQuic::peer_addr_len; +quiche_conn* UQuic::conn; +quiche_config* UQuic::qconfig; + +struct sockaddr_storage UQuic::peer_addr; +UHashMap* UQuic::peers; + +int UQuic::loadConfigParam() +{ + U_TRACE_NO_PARAM(0, "UQuic::loadConfigParam()") + + U_INTERNAL_ASSERT(UServer_Base::budp) + U_INTERNAL_ASSERT_POINTER(UServer_Base::pcfg) + +#ifndef USE_LIBQUICHE + U_ERROR("Sorry, I was compiled without libquiche so there isn't HTTP/3 support"); +#endif + + if (UServer_Base::key_file->empty() || + UServer_Base::cert_file->empty()) + { + U_ERROR("You need to specify in configuration file the property KEY_FILE and CERT_FILE"); + } + +#ifdef DEBUG +// (void) U_SYSCALL(quiche_enable_debug_logging, "%p,%p", quiche_debug_log, U_NULLPTR); +#endif + + // Stores configuration shared between multiple connections + qconfig = (quiche_config*) U_SYSCALL(quiche_config_new, "%u", QUICHE_PROTOCOL_VERSION); + + if (qconfig == U_NULLPTR) + { + U_ERROR("Failed to create quiche config"); + } + + // Configures the given certificate chain + (void) U_SYSCALL(quiche_config_load_cert_chain_from_pem_file, "%p,%S", qconfig, UServer_Base::cert_file->data()); + + // Configures the given private key + (void) U_SYSCALL(quiche_config_load_priv_key_from_pem_file, "%p,%S", qconfig, UServer_Base::key_file->data()); + + if (UServer_Base::pcfg->searchForObjectStream(U_CONSTANT_TO_PARAM("quic"))) + { + UServer_Base::pcfg->table.clear(); + + if (UServer_Base::pcfg->loadTable()) + { + // -------------------------------------------------------------------------------------------------------------------------------------- + // userver_udp - quic configuration parameters + // -------------------------------------------------------------------------------------------------------------------------------------- + // QUICHE_GREASE Whether to send GREASE + // QUICHE_LOG_KEYS Enables logging of secrets + // QUICHE_VERIFY_PEER Whether to verify the peer's certificate + // QUICHE_CC_ALGORITHM Sets the congestion control algorithm used + // QUICHE_MAX_ACK_DELAY Sets the `max_ack_delay` transport parameter + // QUICHE_MAX_PACKET_SIZE Sets the max_packet_size transport parameter + // QUICHE_MAX_IDLE_TIMEOUT Sets the `max_idle_timeout` transport parameter + // QUICHE_INITIAL_MAX_DATA Sets the `initial_max_data` transport parameter + // QUICHE_ENABLE_EARLY_DATA Enables sending or receiving early data + // QUICHE_ACK_DELAY_EXPONENT Sets the `ack_delay_exponent` transport parameter + // QUICHE_MAX_UDP_PAYLOAD_SIZE Sets the `max_udp_payload_size` transport parameter + // QUICHE_INITIAL_MAX_STREAM_UNI Sets the `initial_max_streams_uni` transport parameter + // QUICHE_DISABLE_ACTIVE_MIGRATION Sets the `disable_active_migration` transport parameter + // QUICHE_INITIAL_MAX_STREAMS_BIDI Sets the `initial_max_streams_bidi` transport parameter + // QUICHE_INITIAL_MAX_STREAM_DATA_UNI Sets the `initial_max_stream_data_uni` transport parameter + // QUICHE_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL Sets the `initial_max_stream_data_bidi_local` transport parameter + // QUICHE_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE Sets the `initial_max_stream_data_bidi_remote` transport parameter + // -------------------------------------------------------------------------------------------------------------------------------------- + + long param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_MAX_IDLE_TIMEOUT"), 180000); + bool param1 = UServer_Base::pcfg->readBoolean(U_CONSTANT_TO_PARAM("QUICHE_DISABLE_ACTIVE_MIGRATION"), true); + + U_SYSCALL_VOID(quiche_config_set_max_idle_timeout, "%p,%lu", qconfig, param0); + U_SYSCALL_VOID(quiche_config_set_disable_active_migration, "%p,%b", qconfig, param1); + + param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_CC_ALGORITHM"), 0); // QUICHE_CC_RENO = 0 + + U_SYSCALL_VOID(quiche_config_set_cc_algorithm, "%p,%lu", qconfig, (quiche_cc_algorithm)param0); + +# ifdef LIBQUICHE_AT_LEAST_0_5 + param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_MAX_UDP_PAYLOAD_SIZE"), U_MAX_DATAGRAM_SIZE); + + U_SYSCALL_VOID(quiche_config_set_max_udp_payload_size, "%p,%lu", qconfig, param0); +# else + param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_MAX_PACKET_SIZE"), U_MAX_DATAGRAM_SIZE); + + U_SYSCALL_VOID(quiche_config_set_max_packet_size, "%p,%lu", qconfig, param0); +# endif + + param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_INITIAL_MAX_DATA"), 10485760); + + U_SYSCALL_VOID(quiche_config_set_initial_max_data, "%p,%lu", qconfig, param0); + + param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_INITIAL_MAX_STREAM_UNI"), 3); // For HTTP/3 we only need 3 unidirectional streams + + U_SYSCALL_VOID(quiche_config_set_initial_max_streams_uni, "%p,%lu", qconfig, param0); + + param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_INITIAL_MAX_STREAMS_BIDI"), 128); + + U_SYSCALL_VOID(quiche_config_set_initial_max_streams_bidi, "%p,%lu", qconfig, param0); + + param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_INITIAL_MAX_STREAM_DATA_UNI"), 1048576); + + U_SYSCALL_VOID(quiche_config_set_initial_max_stream_data_uni, "%p,%lu", qconfig, param0); + + param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL"), 1000000); + + U_SYSCALL_VOID(quiche_config_set_initial_max_stream_data_bidi_local, "%p,%lu", qconfig, param0); + + param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE"), 1048576); + + U_SYSCALL_VOID(quiche_config_set_initial_max_stream_data_bidi_remote, "%p,%lu", qconfig, param0); + + /* + param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_MAX_ACK_DELAY"), 25); + + U_SYSCALL_VOID(quiche_config_set_max_ack_delay, "%p,%lu", qconfig, param0); + + param0 = UServer_Base::pcfg->readLong(U_CONSTANT_TO_PARAM("QUICHE_ACK_DELAY_EXPONENT"), 3); + + U_SYSCALL_VOID(quiche_config_set_ack_delay_exponent, "%p,%lu", qconfig, param0); + */ + + if (UServer_Base::pcfg->readBoolean(U_CONSTANT_TO_PARAM("QUICHE_ENABLE_EARLY_DATA"), false)) U_SYSCALL_VOID(quiche_config_enable_early_data, "%p", qconfig); + + /** TODO + + void quiche_config_log_keys(quiche_config *config); + void quiche_config_grease(quiche_config *config, bool v); + void quiche_config_verify_peer(quiche_config *config, bool v); + */ + + UServer_Base::pcfg->reset(); + } + } + + U_RETURN(U_PLUGIN_HANDLER_OK); +} + +bool UQuic::parseHeader() +{ + U_TRACE_NO_PARAM(0, "UQuic::parseHeader()") + + // Parse the QUIC packet's header + + scid_len = + conn_id_len = QUICHE_MAX_CONN_ID_LEN; + token_len = U_MAX_TOKEN_LEN; + + // Extracts version, type, source / destination connection ID and address verification token from the packet in buffer + int rc = U_SYSCALL(quiche_header_info, "%p,%u,%u,%p,%p,%p,%p,%p,%p,%p,%p", (const uint8_t*)U_STRING_TO_PARAM(*UServer_Base::rbuffer), U_LOCAL_CONN_ID_LEN, + &pkt_version, &pkt_type, scid, &scid_len, conn_id, &conn_id_len, token, &token_len); + + if (rc < 0) + { + U_DEBUG("UQuic::handlerRead(): failed to parse header: %d", rc) + + U_RETURN(false); + } + + U_INTERNAL_DUMP("scid(%u) = %#.*S token(%u) = %#.*S conn_id(%u) = %#.*S pkt_version = %p pkt_type = %u", + scid_len, scid_len, scid, token_len, token_len, token, conn_id_len, conn_id_len, conn_id, pkt_version, pkt_type) + + U_RETURN(true); +} + +bool UQuic::handlerRead(quiche_conn* lconn, bool bwait_for_data) +{ + U_TRACE(0, "UQuic::handlerRead(%p,%b)", lconn, bwait_for_data) + + U_ASSERT_EQUALS(UClientImage_Base::rbuffer->capacity(), UServer_Base::rbuffer_size) + + int iBytesRead; + char* ptr = UServer_Base::rbuffer->data(); + + // Read incoming UDP packets from the socket and feed them to quiche, until there are no more packets to read + +loop: + peer_addr_len = sizeof(peer_addr); + + (void) U_SYSCALL(memset, "%p,%u,%u", &peer_addr, 0, U_SIZE_SOCKADDR); + + iBytesRead = U_SYSCALL(recvfrom, "%d,%p,%u,%u,%p,%p", UServer_Base::fds[0], ptr, UServer_Base::rbuffer_size, (bwait_for_data ? 0 : MSG_DONTWAIT), + (struct sockaddr*)&peer_addr, &peer_addr_len); + + if (iBytesRead <= 0) + { + if (errno == EAGAIN) + { + U_DEBUG("quiche: recvfrom would block") + + U_INTERNAL_ASSERT_EQUALS(bwait_for_data, false) + + if (lconn) // reported no read packets, we will then proceed with the send loop + { + uint8_t out[65536]; + ssize_t written, sent; + uint32_t start = 0, remain = sizeof(out); + + while (true) + { + written = U_SYSCALL(quiche_conn_send, "%p,%p,%u", lconn, &out[start], remain); + + if (written == QUICHE_ERR_DONE) + { + U_DEBUG("quiche: done writing") + + break; + } + + if (written < 0) + { + U_DEBUG("UQuic::handlerRead(): failed to create packet: %d", written) + + break; + } + + start += written; + remain -= written; + + U_INTERNAL_ASSERT_MINOR(start, sizeof(out)) + + U_DEBUG("quiche: sent %u bytes", written) + } + + sent = U_SYSCALL(sendto, "%d,%p,%u,%u,%p,%d", UServer_Base::fds[0], out, start, 0, (struct sockaddr*)&USocket::peer_addr, USocket::peer_addr_len); + + if (sent != start) + { + U_DEBUG("UQuic::handlerRead(): failed to send") + + U_RETURN(false); + } + + if (U_SYSCALL(quiche_conn_is_closed, "%p", lconn)) + { + quiche_stats stats; + + U_SYSCALL_VOID(quiche_conn_stats, "%p,%p", lconn, &stats); + + U_DEBUG("quiche: connection closed, recv=%u sent=%u lost=%u rtt=%u cwnd=%u", stats.recv, stats.sent, stats.lost, stats.rtt, stats.cwnd) + + U_SYSCALL_VOID(quiche_conn_free, "%p", lconn); + + U_RETURN(false); + } + } + + bwait_for_data = true; + + goto loop; + } + + U_WARNING("recvfrom on fd %d got %d%R", UServer_Base::fds[0], iBytesRead, 0); // NB: the last argument (0) is necessary... + + if (errno == EINTR) UInterrupt::checkForEventSignalPending(); + + U_RETURN(false); + } + + U_INTERNAL_DUMP("peer_addr_len = %u BytesRead(%u) = %#.*S", peer_addr_len, iBytesRead, iBytesRead, ptr) + + U_INTERNAL_ASSERT_MAJOR(peer_addr_len, 0) + + UServer_Base::rbuffer->size_adjust_force(iBytesRead); + + if (memcmp(&peer_addr, &USocket::peer_addr, peer_addr_len) != 0) + { + // TODO + + U_WARNING("recvfrom() different address"); + + /* Lookup a connection based on the packet's connection ID. If there is no connection matching, create a new one + + if (lookup()) + { + } + */ + } + + if (lconn || parseHeader()) U_RETURN(true); + + U_RETURN(false); +} + +bool UQuic::handlerNewConnection() +{ + U_TRACE_NO_PARAM(0, "UQuic::handlerNewConnection()") + + U_INTERNAL_ASSERT_POINTER(peers) + U_INTERNAL_ASSERT(UServer_Base::budp) + + const char* ptr; + ssize_t written, sent; + const char* pkt = "vneg"; + uint8_t out[U_MAX_DATAGRAM_SIZE]; + + conn = U_NULLPTR; + +loop: + if (pkt_type != Initial) + { + U_DEBUG("UQuic::handlerNewConnection(): packet is NOT initial: %u", pkt_type) + + U_RETURN(false); + } + + // Client Initial packets must be at least 1200 bytes + if (UServer_Base::rbuffer->size() < QUICHE_MIN_CLIENT_INITIAL_LEN) + { + U_DEBUG("UQuic::handlerNewConnection(): quic initial packet is too short: %u", UServer_Base::rbuffer->size()) + + U_RETURN(false); + } + + // Returns true if the given protocol version is supported + if (U_SYSCALL(quiche_version_is_supported, "%u", pkt_version) == false) + { + U_DEBUG("quiche: version negotiation") + + // Writes a version negotiation packet + written = U_SYSCALL(quiche_negotiate_version, "%p,%u,%p,%u,%p,%u", scid, scid_len, conn_id, conn_id_len, out, sizeof(out)); + +pkt: if (written < 0) + { + U_DEBUG("UQuic::handlerNewConnection(): failed to create %S packet: %d", pkt, written) + + U_RETURN(false); + } + + sent = U_SYSCALL(sendto, "%u,%p,%u,%u,%p,%d", UServer_Base::fds[0], out, written, 0, (struct sockaddr*)&USocket::peer_addr, USocket::peer_addr_len); + + if (sent == written) + { + U_DEBUG("quiche: sent %u bytes", sent) + } + else + { + U_DEBUG("UQuic::handlerNewConnection(): failed to send") + + U_RETURN(false); + } + + if (handlerRead()) goto loop; + + U_RETURN(false); + } + + if (token_len == 0) + { + // Generate a stateless retry token. The token includes the static string "quiche" followed + // by the IP address of the client and by the original destination connection ID generated by the client + + U_DEBUG("quiche: stateless retry") + + U_INTERNAL_DUMP("USocket::peer_addr_len = %u", USocket::peer_addr_len) + + U_INTERNAL_ASSERT_MAJOR(conn_id_len, 0) + U_INTERNAL_ASSERT_MAJOR(USocket::peer_addr_len, 0) + + // 6 -> U_CONSTANT_SIZE("quiche") + U_MEMCPY(token, "quiche", 6); + U_MEMCPY(token + 6, &USocket::peer_addr, USocket::peer_addr_len); + U_MEMCPY(token + 6 + USocket::peer_addr_len, conn_id, conn_id_len); + + token_len = 6 + USocket::peer_addr_len + conn_id_len; + + U_INTERNAL_DUMP("scid(%u) = %.*S conn_id(%u) = %.*S token(%u) = %.*S pkt_version = %p", + scid_len, scid_len, scid, conn_id_len, conn_id_len, conn_id, token_len, token_len, token, pkt_version) + + // Writes a retry packet +# ifdef LIBQUICHE_AT_LEAST_0_5 + written = U_SYSCALL(quiche_retry, "%p,%u,%p,%u,%p,%u,%p,%u,%u,%p,%u", scid, scid_len, conn_id, conn_id_len, conn_id, conn_id_len, token, token_len, pkt_version, out, sizeof(out)); +# else + written = U_SYSCALL(quiche_retry, "%p,%u,%p,%u,%p,%u,%p,%u, %p,%u", scid, scid_len, conn_id, conn_id_len, conn_id, conn_id_len, token, token_len, out, sizeof(out)); +# endif + + pkt = "retry"; + + goto pkt; + } + + // Validates a stateless retry token. This checks that the ticket includes the `"quiche"` static string, and that the client IP address matches the address stored in the ticket + if (token_len < 6 || + memcmp(token, U_CONSTANT_TO_PARAM("quiche"))) + { + U_DEBUG("UQuic::handlerNewConnection(): invalid address validation token") + + U_RETURN(false); + } + + token_len -= 6; + + ptr = (const char*)&token[0] + 6; + + if (token_len < USocket::peer_addr_len || + memcmp(ptr, &USocket::peer_addr, USocket::peer_addr_len)) + { + U_DEBUG("UQuic::handlerNewConnection(): invalid address validation token") + + U_RETURN(false); + } + + ptr += USocket::peer_addr_len; + token_len -= USocket::peer_addr_len; + + if (conn_id_len != token_len) // The token was not valid, meaning the retry failed, so drop the packet + { + U_DEBUG("UQuic::handlerNewConnection(): invalid address validation token") + + U_RETURN(false); + } + + // Reuse the source connection ID we sent in the Retry packet, instead of changing it again. Creates a new server-side connection + conn = (quiche_conn*) U_SYSCALL(quiche_accept, "%p,%u,%p,%u,%p", conn_id, conn_id_len, (const uint8_t*)ptr, token_len, qconfig); + + if (conn == U_NULLPTR) + { + U_DEBUG("UQuic::handlerNewConnection(): failed to create connection") + + U_RETURN(false); + } + + U_DEBUG("quiche: new connection") + + while (processesPackets(conn)) + { + if (U_SYSCALL(quiche_conn_is_established, "%p", conn)) + { + U_DEBUG("UQuic::handlerNewConnection(): connection handshake is complete") + + U_RETURN(true); + } + + if (handlerRead(conn) == false) U_RETURN(false); + } + + U_RETURN(false); +} diff --git a/tests/examples/TSA/tsaserial b/tests/examples/TSA/tsaserial index 95c03b3c..2aaa74b6 100644 --- a/tests/examples/TSA/tsaserial +++ b/tests/examples/TSA/tsaserial @@ -1 +1 @@ -0A20 +0A2E diff --git a/tests/ulib/README b/tests/ulib/README index 534b1c6c..a1318ded 100644 --- a/tests/ulib/README +++ b/tests/ulib/README @@ -7,8 +7,8 @@ Debian 8.11 was released Saturday, 23rd June 2018. Debian 9.13, or stretch. Access this release through dists/oldstable Debian 9.13 was released Saturday, 18th July 2020. -Debian 10.4, or buster. Access this release through dists/stable -Debian 10.4 was released Saturday, 9th May 2020. +Debian 10.5, or buster. Access this release through dists/stable +Debian 10.5 was released Saturday, 1st August 2020. Testing, or bullseye. Access this release through dists/testing. The current tested development snapshot is named bullseye. Packages which