protocol-quic 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/ext/ngtcp2/AUTHORS +44 -0
- data/ext/ngtcp2/CMakeLists.txt +431 -0
- data/ext/ngtcp2/CMakeOptions.txt +17 -0
- data/ext/ngtcp2/COPYING +22 -0
- data/ext/ngtcp2/ChangeLog +0 -0
- data/ext/ngtcp2/Makefile.am +60 -0
- data/ext/ngtcp2/NEWS +0 -0
- data/ext/ngtcp2/README +1 -0
- data/ext/ngtcp2/README.rst +258 -0
- data/ext/ngtcp2/ci/build_boringssl.sh +10 -0
- data/ext/ngtcp2/ci/build_nghttp3.sh +9 -0
- data/ext/ngtcp2/ci/build_openssl1.sh +8 -0
- data/ext/ngtcp2/ci/build_openssl1_cross.sh +9 -0
- data/ext/ngtcp2/ci/build_openssl3.sh +8 -0
- data/ext/ngtcp2/ci/build_picotls.sh +26 -0
- data/ext/ngtcp2/ci/build_wolfssl.sh +9 -0
- data/ext/ngtcp2/ci/gen-certificate.sh +8 -0
- data/ext/ngtcp2/cmake/ExtractValidFlags.cmake +31 -0
- data/ext/ngtcp2/cmake/FindCUnit.cmake +40 -0
- data/ext/ngtcp2/cmake/FindJemalloc.cmake +40 -0
- data/ext/ngtcp2/cmake/FindLibev.cmake +38 -0
- data/ext/ngtcp2/cmake/FindLibnghttp3.cmake +41 -0
- data/ext/ngtcp2/cmake/Findwolfssl.cmake +41 -0
- data/ext/ngtcp2/cmake/Version.cmake +11 -0
- data/ext/ngtcp2/cmakeconfig.h.in +36 -0
- data/ext/ngtcp2/configure.ac +755 -0
- data/ext/ngtcp2/crypto/CMakeLists.txt +56 -0
- data/ext/ngtcp2/crypto/Makefile.am +49 -0
- data/ext/ngtcp2/crypto/boringssl/CMakeLists.txt +64 -0
- data/ext/ngtcp2/crypto/boringssl/Makefile.am +39 -0
- data/ext/ngtcp2/crypto/boringssl/boringssl.c +630 -0
- data/ext/ngtcp2/crypto/boringssl/libngtcp2_crypto_boringssl.pc.in +33 -0
- data/ext/ngtcp2/crypto/gnutls/CMakeLists.txt +86 -0
- data/ext/ngtcp2/crypto/gnutls/Makefile.am +43 -0
- data/ext/ngtcp2/crypto/gnutls/gnutls.c +644 -0
- data/ext/ngtcp2/crypto/gnutls/libngtcp2_crypto_gnutls.pc.in +33 -0
- data/ext/ngtcp2/crypto/includes/CMakeLists.txt +56 -0
- data/ext/ngtcp2/crypto/includes/Makefile.am +45 -0
- data/ext/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h +893 -0
- data/ext/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_boringssl.h +104 -0
- data/ext/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_gnutls.h +107 -0
- data/ext/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_openssl.h +132 -0
- data/ext/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_picotls.h +246 -0
- data/ext/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_wolfssl.h +106 -0
- data/ext/ngtcp2/crypto/openssl/CMakeLists.txt +86 -0
- data/ext/ngtcp2/crypto/openssl/Makefile.am +43 -0
- data/ext/ngtcp2/crypto/openssl/libngtcp2_crypto_openssl.pc.in +33 -0
- data/ext/ngtcp2/crypto/openssl/openssl.c +807 -0
- data/ext/ngtcp2/crypto/picotls/CMakeLists.txt +65 -0
- data/ext/ngtcp2/crypto/picotls/Makefile.am +39 -0
- data/ext/ngtcp2/crypto/picotls/libngtcp2_crypto_picotls.pc.in +33 -0
- data/ext/ngtcp2/crypto/picotls/picotls.c +707 -0
- data/ext/ngtcp2/crypto/shared.c +1431 -0
- data/ext/ngtcp2/crypto/shared.h +350 -0
- data/ext/ngtcp2/crypto/wolfssl/CMakeLists.txt +84 -0
- data/ext/ngtcp2/crypto/wolfssl/Makefile.am +43 -0
- data/ext/ngtcp2/crypto/wolfssl/libngtcp2_crypto_wolfssl.pc.in +33 -0
- data/ext/ngtcp2/crypto/wolfssl/wolfssl.c +534 -0
- data/ext/ngtcp2/doc/Makefile.am +65 -0
- data/ext/ngtcp2/doc/make.bat +35 -0
- data/ext/ngtcp2/doc/mkapiref.py +356 -0
- data/ext/ngtcp2/doc/source/conf.py.in +94 -0
- data/ext/ngtcp2/doc/source/index.rst +22 -0
- data/ext/ngtcp2/doc/source/programmers-guide.rst +476 -0
- data/ext/ngtcp2/docker/Dockerfile +39 -0
- data/ext/ngtcp2/examples/CMakeLists.txt +361 -0
- data/ext/ngtcp2/examples/Makefile.am +228 -0
- data/ext/ngtcp2/examples/client.cc +3049 -0
- data/ext/ngtcp2/examples/client.h +192 -0
- data/ext/ngtcp2/examples/client_base.cc +202 -0
- data/ext/ngtcp2/examples/client_base.h +213 -0
- data/ext/ngtcp2/examples/debug.cc +298 -0
- data/ext/ngtcp2/examples/debug.h +124 -0
- data/ext/ngtcp2/examples/examplestest.cc +84 -0
- data/ext/ngtcp2/examples/gtlssimpleclient.c +720 -0
- data/ext/ngtcp2/examples/h09client.cc +2601 -0
- data/ext/ngtcp2/examples/h09client.h +196 -0
- data/ext/ngtcp2/examples/h09server.cc +3024 -0
- data/ext/ngtcp2/examples/h09server.h +237 -0
- data/ext/ngtcp2/examples/http.cc +138 -0
- data/ext/ngtcp2/examples/http.h +44 -0
- data/ext/ngtcp2/examples/network.h +80 -0
- data/ext/ngtcp2/examples/server.cc +3731 -0
- data/ext/ngtcp2/examples/server.h +256 -0
- data/ext/ngtcp2/examples/server_base.cc +58 -0
- data/ext/ngtcp2/examples/server_base.h +195 -0
- data/ext/ngtcp2/examples/shared.cc +385 -0
- data/ext/ngtcp2/examples/shared.h +96 -0
- data/ext/ngtcp2/examples/simpleclient.c +683 -0
- data/ext/ngtcp2/examples/template.h +71 -0
- data/ext/ngtcp2/examples/tests/README.rst +60 -0
- data/ext/ngtcp2/examples/tests/__init__.py +0 -0
- data/ext/ngtcp2/examples/tests/config.ini.in +32 -0
- data/ext/ngtcp2/examples/tests/conftest.py +28 -0
- data/ext/ngtcp2/examples/tests/ngtcp2test/__init__.py +6 -0
- data/ext/ngtcp2/examples/tests/ngtcp2test/certs.py +476 -0
- data/ext/ngtcp2/examples/tests/ngtcp2test/client.py +187 -0
- data/ext/ngtcp2/examples/tests/ngtcp2test/env.py +191 -0
- data/ext/ngtcp2/examples/tests/ngtcp2test/log.py +101 -0
- data/ext/ngtcp2/examples/tests/ngtcp2test/server.py +137 -0
- data/ext/ngtcp2/examples/tests/ngtcp2test/tls.py +983 -0
- data/ext/ngtcp2/examples/tests/test_01_handshake.py +30 -0
- data/ext/ngtcp2/examples/tests/test_02_resume.py +46 -0
- data/ext/ngtcp2/examples/tests/test_03_earlydata.py +56 -0
- data/ext/ngtcp2/examples/tests/test_04_clientcert.py +57 -0
- data/ext/ngtcp2/examples/tests/test_05_ciphers.py +46 -0
- data/ext/ngtcp2/examples/tls_client_context.h +52 -0
- data/ext/ngtcp2/examples/tls_client_context_boringssl.cc +126 -0
- data/ext/ngtcp2/examples/tls_client_context_boringssl.h +49 -0
- data/ext/ngtcp2/examples/tls_client_context_gnutls.cc +74 -0
- data/ext/ngtcp2/examples/tls_client_context_gnutls.h +50 -0
- data/ext/ngtcp2/examples/tls_client_context_openssl.cc +137 -0
- data/ext/ngtcp2/examples/tls_client_context_openssl.h +49 -0
- data/ext/ngtcp2/examples/tls_client_context_picotls.cc +158 -0
- data/ext/ngtcp2/examples/tls_client_context_picotls.h +53 -0
- data/ext/ngtcp2/examples/tls_client_context_wolfssl.cc +177 -0
- data/ext/ngtcp2/examples/tls_client_context_wolfssl.h +51 -0
- data/ext/ngtcp2/examples/tls_client_session.h +52 -0
- data/ext/ngtcp2/examples/tls_client_session_boringssl.cc +110 -0
- data/ext/ngtcp2/examples/tls_client_session_boringssl.h +52 -0
- data/ext/ngtcp2/examples/tls_client_session_gnutls.cc +190 -0
- data/ext/ngtcp2/examples/tls_client_session_gnutls.h +52 -0
- data/ext/ngtcp2/examples/tls_client_session_openssl.cc +113 -0
- data/ext/ngtcp2/examples/tls_client_session_openssl.h +52 -0
- data/ext/ngtcp2/examples/tls_client_session_picotls.cc +147 -0
- data/ext/ngtcp2/examples/tls_client_session_picotls.h +52 -0
- data/ext/ngtcp2/examples/tls_client_session_wolfssl.cc +160 -0
- data/ext/ngtcp2/examples/tls_client_session_wolfssl.h +52 -0
- data/ext/ngtcp2/examples/tls_server_context.h +52 -0
- data/ext/ngtcp2/examples/tls_server_context_boringssl.cc +257 -0
- data/ext/ngtcp2/examples/tls_server_context_boringssl.h +54 -0
- data/ext/ngtcp2/examples/tls_server_context_gnutls.cc +99 -0
- data/ext/ngtcp2/examples/tls_server_context_gnutls.h +59 -0
- data/ext/ngtcp2/examples/tls_server_context_openssl.cc +338 -0
- data/ext/ngtcp2/examples/tls_server_context_openssl.h +54 -0
- data/ext/ngtcp2/examples/tls_server_context_picotls.cc +321 -0
- data/ext/ngtcp2/examples/tls_server_context_picotls.h +58 -0
- data/ext/ngtcp2/examples/tls_server_context_wolfssl.cc +284 -0
- data/ext/ngtcp2/examples/tls_server_context_wolfssl.h +55 -0
- data/ext/ngtcp2/examples/tls_server_session.h +52 -0
- data/ext/ngtcp2/examples/tls_server_session_boringssl.cc +84 -0
- data/ext/ngtcp2/examples/tls_server_session_boringssl.h +47 -0
- data/ext/ngtcp2/examples/tls_server_session_gnutls.cc +155 -0
- data/ext/ngtcp2/examples/tls_server_session_gnutls.h +46 -0
- data/ext/ngtcp2/examples/tls_server_session_openssl.cc +54 -0
- data/ext/ngtcp2/examples/tls_server_session_openssl.h +47 -0
- data/ext/ngtcp2/examples/tls_server_session_picotls.cc +70 -0
- data/ext/ngtcp2/examples/tls_server_session_picotls.h +47 -0
- data/ext/ngtcp2/examples/tls_server_session_wolfssl.cc +55 -0
- data/ext/ngtcp2/examples/tls_server_session_wolfssl.h +47 -0
- data/ext/ngtcp2/examples/tls_session_base_gnutls.cc +87 -0
- data/ext/ngtcp2/examples/tls_session_base_gnutls.h +51 -0
- data/ext/ngtcp2/examples/tls_session_base_openssl.cc +54 -0
- data/ext/ngtcp2/examples/tls_session_base_openssl.h +52 -0
- data/ext/ngtcp2/examples/tls_session_base_picotls.cc +56 -0
- data/ext/ngtcp2/examples/tls_session_base_picotls.h +54 -0
- data/ext/ngtcp2/examples/tls_session_base_wolfssl.cc +54 -0
- data/ext/ngtcp2/examples/tls_session_base_wolfssl.h +54 -0
- data/ext/ngtcp2/examples/tls_shared_picotls.cc +59 -0
- data/ext/ngtcp2/examples/tls_shared_picotls.h +36 -0
- data/ext/ngtcp2/examples/util.cc +646 -0
- data/ext/ngtcp2/examples/util.h +361 -0
- data/ext/ngtcp2/examples/util_gnutls.cc +136 -0
- data/ext/ngtcp2/examples/util_openssl.cc +131 -0
- data/ext/ngtcp2/examples/util_test.cc +237 -0
- data/ext/ngtcp2/examples/util_test.h +45 -0
- data/ext/ngtcp2/examples/util_wolfssl.cc +130 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/ack +0 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/ack_ecn +0 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/connection_close +0 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/crypto +1 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/data_blocked +1 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/datagram +1 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/datagram_len +1 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/max_data +1 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/max_stream_data +0 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/max_streams +0 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/new_connection_id +1 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/new_token +1 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/path_challenge +1 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/path_response +1 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/reset_stream +0 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/retire_connection_id +1 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/stop_sending +0 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/stream +0 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/stream_data_blocked +0 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/stream_len +0 -0
- data/ext/ngtcp2/fuzz/corpus/decode_frame/streams_blocked +0 -0
- data/ext/ngtcp2/fuzz/corpus/ksl/random +0 -0
- data/ext/ngtcp2/fuzz/decode_frame.cc +25 -0
- data/ext/ngtcp2/fuzz/ksl.cc +77 -0
- data/ext/ngtcp2/interop/Dockerfile +39 -0
- data/ext/ngtcp2/interop/run_endpoint.sh +93 -0
- data/ext/ngtcp2/lib/CMakeLists.txt +110 -0
- data/ext/ngtcp2/lib/Makefile.am +122 -0
- data/ext/ngtcp2/lib/includes/CMakeLists.txt +4 -0
- data/ext/ngtcp2/lib/includes/Makefile.am +25 -0
- data/ext/ngtcp2/lib/includes/ngtcp2/ngtcp2.h +5843 -0
- data/ext/ngtcp2/lib/includes/ngtcp2/version.h.in +51 -0
- data/ext/ngtcp2/lib/libngtcp2.pc.in +33 -0
- data/ext/ngtcp2/lib/ngtcp2_acktr.c +335 -0
- data/ext/ngtcp2/lib/ngtcp2_acktr.h +221 -0
- data/ext/ngtcp2/lib/ngtcp2_addr.c +117 -0
- data/ext/ngtcp2/lib/ngtcp2_addr.h +69 -0
- data/ext/ngtcp2/lib/ngtcp2_balloc.c +90 -0
- data/ext/ngtcp2/lib/ngtcp2_balloc.h +91 -0
- data/ext/ngtcp2/lib/ngtcp2_bbr.c +693 -0
- data/ext/ngtcp2/lib/ngtcp2_bbr.h +157 -0
- data/ext/ngtcp2/lib/ngtcp2_bbr2.c +1490 -0
- data/ext/ngtcp2/lib/ngtcp2_bbr2.h +149 -0
- data/ext/ngtcp2/lib/ngtcp2_buf.c +56 -0
- data/ext/ngtcp2/lib/ngtcp2_buf.h +108 -0
- data/ext/ngtcp2/lib/ngtcp2_cc.c +616 -0
- data/ext/ngtcp2/lib/ngtcp2_cc.h +422 -0
- data/ext/ngtcp2/lib/ngtcp2_cid.c +147 -0
- data/ext/ngtcp2/lib/ngtcp2_cid.h +175 -0
- data/ext/ngtcp2/lib/ngtcp2_conn.c +13731 -0
- data/ext/ngtcp2/lib/ngtcp2_conn.h +1119 -0
- data/ext/ngtcp2/lib/ngtcp2_conn_stat.h +131 -0
- data/ext/ngtcp2/lib/ngtcp2_conv.c +291 -0
- data/ext/ngtcp2/lib/ngtcp2_conv.h +208 -0
- data/ext/ngtcp2/lib/ngtcp2_crypto.c +895 -0
- data/ext/ngtcp2/lib/ngtcp2_crypto.h +148 -0
- data/ext/ngtcp2/lib/ngtcp2_err.c +154 -0
- data/ext/ngtcp2/lib/ngtcp2_err.h +34 -0
- data/ext/ngtcp2/lib/ngtcp2_gaptr.c +167 -0
- data/ext/ngtcp2/lib/ngtcp2_gaptr.h +98 -0
- data/ext/ngtcp2/lib/ngtcp2_idtr.c +79 -0
- data/ext/ngtcp2/lib/ngtcp2_idtr.h +89 -0
- data/ext/ngtcp2/lib/ngtcp2_ksl.c +819 -0
- data/ext/ngtcp2/lib/ngtcp2_ksl.h +345 -0
- data/ext/ngtcp2/lib/ngtcp2_log.c +822 -0
- data/ext/ngtcp2/lib/ngtcp2_log.h +123 -0
- data/ext/ngtcp2/lib/ngtcp2_macro.h +58 -0
- data/ext/ngtcp2/lib/ngtcp2_map.c +336 -0
- data/ext/ngtcp2/lib/ngtcp2_map.h +136 -0
- data/ext/ngtcp2/lib/ngtcp2_mem.c +113 -0
- data/ext/ngtcp2/lib/ngtcp2_mem.h +72 -0
- data/ext/ngtcp2/lib/ngtcp2_net.h +136 -0
- data/ext/ngtcp2/lib/ngtcp2_objalloc.c +40 -0
- data/ext/ngtcp2/lib/ngtcp2_objalloc.h +140 -0
- data/ext/ngtcp2/lib/ngtcp2_opl.c +46 -0
- data/ext/ngtcp2/lib/ngtcp2_opl.h +65 -0
- data/ext/ngtcp2/lib/ngtcp2_path.c +77 -0
- data/ext/ngtcp2/lib/ngtcp2_path.h +49 -0
- data/ext/ngtcp2/lib/ngtcp2_pkt.c +2527 -0
- data/ext/ngtcp2/lib/ngtcp2_pkt.h +1235 -0
- data/ext/ngtcp2/lib/ngtcp2_pmtud.c +160 -0
- data/ext/ngtcp2/lib/ngtcp2_pmtud.h +123 -0
- data/ext/ngtcp2/lib/ngtcp2_ppe.c +230 -0
- data/ext/ngtcp2/lib/ngtcp2_ppe.h +153 -0
- data/ext/ngtcp2/lib/ngtcp2_pq.c +164 -0
- data/ext/ngtcp2/lib/ngtcp2_pq.h +126 -0
- data/ext/ngtcp2/lib/ngtcp2_pv.c +172 -0
- data/ext/ngtcp2/lib/ngtcp2_pv.h +194 -0
- data/ext/ngtcp2/lib/ngtcp2_qlog.c +1219 -0
- data/ext/ngtcp2/lib/ngtcp2_qlog.h +161 -0
- data/ext/ngtcp2/lib/ngtcp2_range.c +61 -0
- data/ext/ngtcp2/lib/ngtcp2_range.h +80 -0
- data/ext/ngtcp2/lib/ngtcp2_rcvry.h +40 -0
- data/ext/ngtcp2/lib/ngtcp2_ringbuf.c +121 -0
- data/ext/ngtcp2/lib/ngtcp2_ringbuf.h +132 -0
- data/ext/ngtcp2/lib/ngtcp2_rob.c +319 -0
- data/ext/ngtcp2/lib/ngtcp2_rob.h +197 -0
- data/ext/ngtcp2/lib/ngtcp2_rst.c +138 -0
- data/ext/ngtcp2/lib/ngtcp2_rst.h +86 -0
- data/ext/ngtcp2/lib/ngtcp2_rtb.c +1676 -0
- data/ext/ngtcp2/lib/ngtcp2_rtb.h +468 -0
- data/ext/ngtcp2/lib/ngtcp2_str.c +233 -0
- data/ext/ngtcp2/lib/ngtcp2_str.h +94 -0
- data/ext/ngtcp2/lib/ngtcp2_strm.c +698 -0
- data/ext/ngtcp2/lib/ngtcp2_strm.h +310 -0
- data/ext/ngtcp2/lib/ngtcp2_unreachable.c +71 -0
- data/ext/ngtcp2/lib/ngtcp2_unreachable.h +46 -0
- data/ext/ngtcp2/lib/ngtcp2_vec.c +243 -0
- data/ext/ngtcp2/lib/ngtcp2_vec.h +120 -0
- data/ext/ngtcp2/lib/ngtcp2_version.c +39 -0
- data/ext/ngtcp2/lib/ngtcp2_window_filter.c +99 -0
- data/ext/ngtcp2/lib/ngtcp2_window_filter.h +65 -0
- data/ext/ngtcp2/m4/ax_check_compile_flag.m4 +74 -0
- data/ext/ngtcp2/m4/ax_cxx_compile_stdcxx.m4 +1009 -0
- data/ext/ngtcp2/tests/CMakeLists.txt +68 -0
- data/ext/ngtcp2/tests/Makefile.am +94 -0
- data/ext/ngtcp2/tests/main.c +358 -0
- data/ext/ngtcp2/tests/ngtcp2_acktr_test.c +367 -0
- data/ext/ngtcp2/tests/ngtcp2_acktr_test.h +37 -0
- data/ext/ngtcp2/tests/ngtcp2_conn_test.c +9821 -0
- data/ext/ngtcp2/tests/ngtcp2_conn_test.h +104 -0
- data/ext/ngtcp2/tests/ngtcp2_conv_test.c +430 -0
- data/ext/ngtcp2/tests/ngtcp2_conv_test.h +46 -0
- data/ext/ngtcp2/tests/ngtcp2_crypto_test.c +667 -0
- data/ext/ngtcp2/tests/ngtcp2_crypto_test.h +35 -0
- data/ext/ngtcp2/tests/ngtcp2_gaptr_test.c +127 -0
- data/ext/ngtcp2/tests/ngtcp2_gaptr_test.h +36 -0
- data/ext/ngtcp2/tests/ngtcp2_idtr_test.c +79 -0
- data/ext/ngtcp2/tests/ngtcp2_idtr_test.h +34 -0
- data/ext/ngtcp2/tests/ngtcp2_ksl_test.c +502 -0
- data/ext/ngtcp2/tests/ngtcp2_ksl_test.h +39 -0
- data/ext/ngtcp2/tests/ngtcp2_map_test.c +206 -0
- data/ext/ngtcp2/tests/ngtcp2_map_test.h +38 -0
- data/ext/ngtcp2/tests/ngtcp2_pkt_test.c +1645 -0
- data/ext/ngtcp2/tests/ngtcp2_pkt_test.h +68 -0
- data/ext/ngtcp2/tests/ngtcp2_pmtud_test.c +153 -0
- data/ext/ngtcp2/tests/ngtcp2_pmtud_test.h +34 -0
- data/ext/ngtcp2/tests/ngtcp2_pv_test.c +129 -0
- data/ext/ngtcp2/tests/ngtcp2_pv_test.h +35 -0
- data/ext/ngtcp2/tests/ngtcp2_range_test.c +105 -0
- data/ext/ngtcp2/tests/ngtcp2_range_test.h +36 -0
- data/ext/ngtcp2/tests/ngtcp2_ringbuf_test.c +91 -0
- data/ext/ngtcp2/tests/ngtcp2_ringbuf_test.h +35 -0
- data/ext/ngtcp2/tests/ngtcp2_rob_test.c +552 -0
- data/ext/ngtcp2/tests/ngtcp2_rob_test.h +37 -0
- data/ext/ngtcp2/tests/ngtcp2_rtb_test.c +470 -0
- data/ext/ngtcp2/tests/ngtcp2_rtb_test.h +38 -0
- data/ext/ngtcp2/tests/ngtcp2_str_test.c +96 -0
- data/ext/ngtcp2/tests/ngtcp2_str_test.h +36 -0
- data/ext/ngtcp2/tests/ngtcp2_strm_test.c +575 -0
- data/ext/ngtcp2/tests/ngtcp2_strm_test.h +36 -0
- data/ext/ngtcp2/tests/ngtcp2_test_helper.c +404 -0
- data/ext/ngtcp2/tests/ngtcp2_test_helper.h +191 -0
- data/ext/ngtcp2/tests/ngtcp2_vec_test.c +426 -0
- data/ext/ngtcp2/tests/ngtcp2_vec_test.h +36 -0
- data/ext/ngtcp2/third-party/CMakeLists.txt +34 -0
- data/ext/ngtcp2/third-party/Makefile.am +31 -0
- data/ext/ngtcp2/third-party/http-parser/AUTHORS +68 -0
- data/ext/ngtcp2/third-party/http-parser/LICENSE-MIT +23 -0
- data/ext/ngtcp2/third-party/http-parser/Makefile +157 -0
- data/ext/ngtcp2/third-party/http-parser/README.md +246 -0
- data/ext/ngtcp2/third-party/http-parser/bench.c +111 -0
- data/ext/ngtcp2/third-party/http-parser/contrib/parsertrace.c +160 -0
- data/ext/ngtcp2/third-party/http-parser/contrib/url_parser.c +47 -0
- data/ext/ngtcp2/third-party/http-parser/http_parser.c +2419 -0
- data/ext/ngtcp2/third-party/http-parser/http_parser.gyp +111 -0
- data/ext/ngtcp2/third-party/http-parser/http_parser.h +431 -0
- data/ext/ngtcp2/third-party/http-parser/test.c +4411 -0
- data/lib/protocol/quic/version.rb +10 -0
- data/lib/protocol/quic.rb +9 -0
- data/license.md +21 -0
- data.tar.gz.sig +1 -0
- metadata +424 -0
- metadata.gz.sig +1 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
import re
|
|
4
|
+
import subprocess
|
|
5
|
+
from typing import List
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from .server import ExampleServer, ServerRun
|
|
10
|
+
from .certs import Credentials
|
|
11
|
+
from .tls import HandShake, HSRecord
|
|
12
|
+
from .env import Env, CryptoLib
|
|
13
|
+
from .log import LogFile, HexDumpScanner
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
log = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ClientRun:
|
|
20
|
+
|
|
21
|
+
def __init__(self, env: Env, returncode, logfile: LogFile, srun: ServerRun):
|
|
22
|
+
self.env = env
|
|
23
|
+
self.returncode = returncode
|
|
24
|
+
self.logfile = logfile
|
|
25
|
+
self.log_lines = logfile.get_recent()
|
|
26
|
+
self._data_recs = None
|
|
27
|
+
self._hs_recs = None
|
|
28
|
+
self._srun = srun
|
|
29
|
+
if self.env.verbose > 1:
|
|
30
|
+
log.debug(f'read {len(self.log_lines)} lines from {logfile.path}')
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def handshake(self) -> List[HSRecord]:
|
|
34
|
+
if self._data_recs is None:
|
|
35
|
+
crypto_line = re.compile(r'Ordered CRYPTO data in \S+ crypto level')
|
|
36
|
+
scanner = HexDumpScanner(source=self.log_lines,
|
|
37
|
+
leading_regex=crypto_line)
|
|
38
|
+
self._data_recs = [data for data in scanner]
|
|
39
|
+
if self.env.verbose > 1:
|
|
40
|
+
log.debug(f'detected {len(self._data_recs)} crypto hexdumps '
|
|
41
|
+
f'in {self.logfile.path}')
|
|
42
|
+
if self._hs_recs is None:
|
|
43
|
+
self._hs_recs = [hrec for hrec in HandShake(source=self._data_recs,
|
|
44
|
+
verbose=self.env.verbose)]
|
|
45
|
+
if self.env.verbose > 1:
|
|
46
|
+
log.debug(f'detected {len(self._hs_recs)} crypto '
|
|
47
|
+
f'records in {self.logfile.path}')
|
|
48
|
+
return self._hs_recs
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def hs_stripe(self) -> str:
|
|
52
|
+
return ":".join([hrec.name for hrec in self.handshake])
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def early_data_rejected(self) -> bool:
|
|
56
|
+
for l in self.log_lines:
|
|
57
|
+
if re.match(r'^Early data was rejected by server.*', l):
|
|
58
|
+
return True
|
|
59
|
+
return False
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def server(self) -> ServerRun:
|
|
63
|
+
return self._srun
|
|
64
|
+
|
|
65
|
+
def norm_exp(self, c_hs, s_hs, allow_hello_retry=True):
|
|
66
|
+
if allow_hello_retry and self.hs_stripe.startswith('HelloRetryRequest:'):
|
|
67
|
+
c_hs = "HelloRetryRequest:" + c_hs
|
|
68
|
+
s_hs = "ClientHello:" + s_hs
|
|
69
|
+
return c_hs, s_hs
|
|
70
|
+
|
|
71
|
+
def _assert_hs(self, c_hs, s_hs):
|
|
72
|
+
if not self.hs_stripe.startswith(c_hs):
|
|
73
|
+
# what happened?
|
|
74
|
+
if self.hs_stripe == '':
|
|
75
|
+
# server send nothing
|
|
76
|
+
if self.server.hs_stripe == '':
|
|
77
|
+
# client send nothing
|
|
78
|
+
pytest.fail(f'client did not send a ClientHello"')
|
|
79
|
+
else:
|
|
80
|
+
# client send sth, but server did not respond
|
|
81
|
+
pytest.fail(f'server did not respond to ClientHello: '
|
|
82
|
+
f'{self.server.handshake[0].to_text()}"')
|
|
83
|
+
else:
|
|
84
|
+
pytest.fail(f'Expected "{c_hs}", got "{self.hs_stripe}"')
|
|
85
|
+
assert self.server.hs_stripe == s_hs, \
|
|
86
|
+
f'Expected "{s_hs}", got "{self.server.hs_stripe}"\n'
|
|
87
|
+
|
|
88
|
+
def assert_non_resume_handshake(self, allow_hello_retry=True):
|
|
89
|
+
# for client/server where KEY_SHARE do not match, the hello is retried
|
|
90
|
+
c_hs, s_hs = self.norm_exp(
|
|
91
|
+
"ServerHello:EncryptedExtensions:Certificate:CertificateVerify:Finished",
|
|
92
|
+
"ClientHello:Finished", allow_hello_retry=allow_hello_retry)
|
|
93
|
+
self._assert_hs(c_hs, s_hs)
|
|
94
|
+
|
|
95
|
+
def assert_resume_handshake(self):
|
|
96
|
+
# for client/server where KEY_SHARE do not match, the hello is retried
|
|
97
|
+
c_hs, s_hs = self.norm_exp("ServerHello:EncryptedExtensions:Finished",
|
|
98
|
+
"ClientHello:Finished")
|
|
99
|
+
self._assert_hs(c_hs, s_hs)
|
|
100
|
+
|
|
101
|
+
def assert_verify_null_handshake(self):
|
|
102
|
+
c_hs, s_hs = self.norm_exp(
|
|
103
|
+
"ServerHello:EncryptedExtensions:CertificateRequest:Certificate:CertificateVerify:Finished",
|
|
104
|
+
"ClientHello:Certificate:Finished")
|
|
105
|
+
self._assert_hs(c_hs, s_hs)
|
|
106
|
+
|
|
107
|
+
def assert_verify_cert_handshake(self):
|
|
108
|
+
c_hs, s_hs = self.norm_exp(
|
|
109
|
+
"ServerHello:EncryptedExtensions:CertificateRequest:Certificate:CertificateVerify:Finished",
|
|
110
|
+
"ClientHello:Certificate:CertificateVerify:Finished")
|
|
111
|
+
self._assert_hs(c_hs, s_hs)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class ExampleClient:
|
|
115
|
+
|
|
116
|
+
def __init__(self, env: Env, crypto_lib: str):
|
|
117
|
+
self.env = env
|
|
118
|
+
self._crypto_lib = crypto_lib
|
|
119
|
+
self._path = env.client_path(self._crypto_lib)
|
|
120
|
+
self._log_path = f'{self.env.gen_dir}/{self._crypto_lib}-client.log'
|
|
121
|
+
self._qlog_path = f'{self.env.gen_dir}/{self._crypto_lib}-client.qlog'
|
|
122
|
+
self._session_path = f'{self.env.gen_dir}/{self._crypto_lib}-client.session'
|
|
123
|
+
self._tp_path = f'{self.env.gen_dir}/{self._crypto_lib}-client.tp'
|
|
124
|
+
self._data_path = f'{self.env.gen_dir}/{self._crypto_lib}-client.data'
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def path(self):
|
|
128
|
+
return self._path
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def crypto_lib(self):
|
|
132
|
+
return self._crypto_lib
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def uses_cipher_config(self):
|
|
136
|
+
return CryptoLib.uses_cipher_config(self.crypto_lib)
|
|
137
|
+
|
|
138
|
+
def supports_cipher(self, cipher):
|
|
139
|
+
return CryptoLib.supports_cipher(self.crypto_lib, cipher)
|
|
140
|
+
|
|
141
|
+
def exists(self):
|
|
142
|
+
return os.path.isfile(self.path)
|
|
143
|
+
|
|
144
|
+
def clear_session(self):
|
|
145
|
+
if os.path.isfile(self._session_path):
|
|
146
|
+
os.remove(self._session_path)
|
|
147
|
+
if os.path.isfile(self._tp_path):
|
|
148
|
+
os.remove(self._tp_path)
|
|
149
|
+
|
|
150
|
+
def http_get(self, server: ExampleServer, url: str, extra_args: List[str] = None,
|
|
151
|
+
use_session=False, data=None,
|
|
152
|
+
credentials: Credentials = None,
|
|
153
|
+
ciphers: str = None):
|
|
154
|
+
args = [
|
|
155
|
+
self.path, '--exit-on-all-streams-close',
|
|
156
|
+
f'--qlog-file={self._qlog_path}'
|
|
157
|
+
]
|
|
158
|
+
if use_session:
|
|
159
|
+
args.append(f'--session-file={self._session_path}')
|
|
160
|
+
args.append(f'--tp-file={self._tp_path}')
|
|
161
|
+
if data is not None:
|
|
162
|
+
with open(self._data_path, 'w') as fd:
|
|
163
|
+
fd.write(data)
|
|
164
|
+
args.append(f'--data={self._data_path}')
|
|
165
|
+
if ciphers is not None:
|
|
166
|
+
ciphers = CryptoLib.adjust_ciphers(self.crypto_lib, ciphers)
|
|
167
|
+
args.append(f'--ciphers={ciphers}')
|
|
168
|
+
if credentials is not None:
|
|
169
|
+
args.append(f'--key={credentials.pkey_file}')
|
|
170
|
+
args.append(f'--cert={credentials.cert_file}')
|
|
171
|
+
if extra_args is not None:
|
|
172
|
+
args.extend(extra_args)
|
|
173
|
+
args.extend([
|
|
174
|
+
'localhost', str(self.env.examples_port),
|
|
175
|
+
url
|
|
176
|
+
])
|
|
177
|
+
if os.path.isfile(self._qlog_path):
|
|
178
|
+
os.remove(self._qlog_path)
|
|
179
|
+
with open(self._log_path, 'w') as log_file:
|
|
180
|
+
logfile = LogFile(path=self._log_path)
|
|
181
|
+
server.log.advance()
|
|
182
|
+
process = subprocess.Popen(args=args, text=True,
|
|
183
|
+
stdout=log_file, stderr=log_file)
|
|
184
|
+
process.wait()
|
|
185
|
+
return ClientRun(env=self.env, returncode=process.returncode,
|
|
186
|
+
logfile=logfile, srun=server.get_run())
|
|
187
|
+
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
from configparser import ConfigParser, ExtendedInterpolation
|
|
4
|
+
from typing import Dict, Optional
|
|
5
|
+
|
|
6
|
+
from .certs import CertificateSpec, Ngtcp2TestCA, Credentials
|
|
7
|
+
|
|
8
|
+
log = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CryptoLib:
|
|
12
|
+
|
|
13
|
+
IGNORES_CIPHER_CONFIG = [
|
|
14
|
+
'picotls', 'boringssl'
|
|
15
|
+
]
|
|
16
|
+
UNSUPPORTED_CIPHERS = {
|
|
17
|
+
'wolfssl': [
|
|
18
|
+
'TLS_AES_128_CCM_SHA256', # no plans to
|
|
19
|
+
],
|
|
20
|
+
'picotls': [
|
|
21
|
+
'TLS_AES_128_CCM_SHA256', # no plans to
|
|
22
|
+
],
|
|
23
|
+
'boringssl': [
|
|
24
|
+
'TLS_AES_128_CCM_SHA256', # no plans to
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
GNUTLS_CIPHERS = {
|
|
28
|
+
'TLS_AES_128_GCM_SHA256': 'AES-128-GCM',
|
|
29
|
+
'TLS_AES_256_GCM_SHA384': 'AES-256-GCM',
|
|
30
|
+
'TLS_CHACHA20_POLY1305_SHA256': 'CHACHA20-POLY1305',
|
|
31
|
+
'TLS_AES_128_CCM_SHA256': 'AES-128-CCM',
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@classmethod
|
|
35
|
+
def uses_cipher_config(cls, crypto_lib):
|
|
36
|
+
return crypto_lib not in cls.IGNORES_CIPHER_CONFIG
|
|
37
|
+
|
|
38
|
+
@classmethod
|
|
39
|
+
def supports_cipher(cls, crypto_lib, cipher):
|
|
40
|
+
return crypto_lib not in cls.UNSUPPORTED_CIPHERS or \
|
|
41
|
+
cipher not in cls.UNSUPPORTED_CIPHERS[crypto_lib]
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
def adjust_ciphers(cls, crypto_lib, ciphers: str) -> str:
|
|
45
|
+
if crypto_lib == 'gnutls':
|
|
46
|
+
gciphers = "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL"
|
|
47
|
+
for cipher in ciphers.split(':'):
|
|
48
|
+
gciphers += f':+{cls.GNUTLS_CIPHERS[cipher]}'
|
|
49
|
+
return gciphers
|
|
50
|
+
return ciphers
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def init_config_from(conf_path):
|
|
54
|
+
if os.path.isfile(conf_path):
|
|
55
|
+
config = ConfigParser(interpolation=ExtendedInterpolation())
|
|
56
|
+
config.read(conf_path)
|
|
57
|
+
return config
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
TESTS_PATH = os.path.dirname(os.path.dirname(__file__))
|
|
62
|
+
EXAMPLES_PATH = os.path.dirname(TESTS_PATH)
|
|
63
|
+
DEF_CONFIG = init_config_from(os.path.join(TESTS_PATH, 'config.ini'))
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class Env:
|
|
67
|
+
|
|
68
|
+
@classmethod
|
|
69
|
+
def get_crypto_libs(cls, configurable_ciphers=None):
|
|
70
|
+
names = [name for name in DEF_CONFIG['examples']
|
|
71
|
+
if DEF_CONFIG['examples'][name] == 'yes']
|
|
72
|
+
if configurable_ciphers is not None:
|
|
73
|
+
names = [n for n in names if CryptoLib.uses_cipher_config(n)]
|
|
74
|
+
return names
|
|
75
|
+
|
|
76
|
+
def __init__(self, examples_dir=None, tests_dir=None, config=None,
|
|
77
|
+
pytestconfig=None):
|
|
78
|
+
self._verbose = pytestconfig.option.verbose if pytestconfig is not None else 0
|
|
79
|
+
self._examples_dir = examples_dir if examples_dir is not None else EXAMPLES_PATH
|
|
80
|
+
self._tests_dir = examples_dir if tests_dir is not None else TESTS_PATH
|
|
81
|
+
self._gen_dir = os.path.join(self._tests_dir, 'gen')
|
|
82
|
+
self.config = config if config is not None else DEF_CONFIG
|
|
83
|
+
self._version = self.config['ngtcp2']['version']
|
|
84
|
+
self._crypto_libs = [name for name in self.config['examples']
|
|
85
|
+
if self.config['examples'][name] == 'yes']
|
|
86
|
+
self._clients = [self.config['clients'][lib] for lib in self._crypto_libs
|
|
87
|
+
if lib in self.config['clients']]
|
|
88
|
+
self._servers = [self.config['servers'][lib] for lib in self._crypto_libs
|
|
89
|
+
if lib in self.config['servers']]
|
|
90
|
+
self._examples_pem = {
|
|
91
|
+
'key': 'xxx',
|
|
92
|
+
'cert': 'xxx',
|
|
93
|
+
}
|
|
94
|
+
self._htdocs_dir = os.path.join(self._gen_dir, 'htdocs')
|
|
95
|
+
self._tld = 'tests.ngtcp2.nghttp2.org'
|
|
96
|
+
self._example_domain = f"one.{self._tld}"
|
|
97
|
+
self._ca = None
|
|
98
|
+
self._cert_specs = [
|
|
99
|
+
CertificateSpec(domains=[self._example_domain], key_type='rsa2048'),
|
|
100
|
+
CertificateSpec(name="clientsX", sub_specs=[
|
|
101
|
+
CertificateSpec(name="user1", client=True),
|
|
102
|
+
]),
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
def issue_certs(self):
|
|
106
|
+
if self._ca is None:
|
|
107
|
+
self._ca = Ngtcp2TestCA.create_root(name=self._tld,
|
|
108
|
+
store_dir=os.path.join(self.gen_dir, 'ca'),
|
|
109
|
+
key_type="rsa2048")
|
|
110
|
+
self._ca.issue_certs(self._cert_specs)
|
|
111
|
+
|
|
112
|
+
def setup(self):
|
|
113
|
+
os.makedirs(self._gen_dir, exist_ok=True)
|
|
114
|
+
os.makedirs(self._htdocs_dir, exist_ok=True)
|
|
115
|
+
self.issue_certs()
|
|
116
|
+
|
|
117
|
+
def get_server_credentials(self) -> Optional[Credentials]:
|
|
118
|
+
creds = self.ca.get_credentials_for_name(self._example_domain)
|
|
119
|
+
if len(creds) > 0:
|
|
120
|
+
return creds[0]
|
|
121
|
+
return None
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def verbose(self) -> int:
|
|
125
|
+
return self._verbose
|
|
126
|
+
|
|
127
|
+
@property
|
|
128
|
+
def version(self) -> str:
|
|
129
|
+
return self._version
|
|
130
|
+
|
|
131
|
+
@property
|
|
132
|
+
def gen_dir(self) -> str:
|
|
133
|
+
return self._gen_dir
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def ca(self):
|
|
137
|
+
return self._ca
|
|
138
|
+
|
|
139
|
+
@property
|
|
140
|
+
def htdocs_dir(self) -> str:
|
|
141
|
+
return self._htdocs_dir
|
|
142
|
+
|
|
143
|
+
@property
|
|
144
|
+
def example_domain(self) -> str:
|
|
145
|
+
return self._example_domain
|
|
146
|
+
|
|
147
|
+
@property
|
|
148
|
+
def examples_dir(self) -> str:
|
|
149
|
+
return self._examples_dir
|
|
150
|
+
|
|
151
|
+
@property
|
|
152
|
+
def examples_port(self) -> int:
|
|
153
|
+
return int(self.config['examples']['port'])
|
|
154
|
+
|
|
155
|
+
@property
|
|
156
|
+
def examples_pem(self) -> Dict[str, str]:
|
|
157
|
+
return self._examples_pem
|
|
158
|
+
|
|
159
|
+
@property
|
|
160
|
+
def crypto_libs(self):
|
|
161
|
+
return self._crypto_libs
|
|
162
|
+
|
|
163
|
+
@property
|
|
164
|
+
def clients(self):
|
|
165
|
+
return self._clients
|
|
166
|
+
|
|
167
|
+
@property
|
|
168
|
+
def servers(self):
|
|
169
|
+
return self._servers
|
|
170
|
+
|
|
171
|
+
def client_name(self, crypto_lib):
|
|
172
|
+
if crypto_lib in self.config['clients']:
|
|
173
|
+
return self.config['clients'][crypto_lib]
|
|
174
|
+
return None
|
|
175
|
+
|
|
176
|
+
def client_path(self, crypto_lib):
|
|
177
|
+
cname = self.client_name(crypto_lib)
|
|
178
|
+
if cname is not None:
|
|
179
|
+
return os.path.join(self.examples_dir, cname)
|
|
180
|
+
return None
|
|
181
|
+
|
|
182
|
+
def server_name(self, crypto_lib):
|
|
183
|
+
if crypto_lib in self.config['servers']:
|
|
184
|
+
return self.config['servers'][crypto_lib]
|
|
185
|
+
return None
|
|
186
|
+
|
|
187
|
+
def server_path(self, crypto_lib):
|
|
188
|
+
sname = self.server_name(crypto_lib)
|
|
189
|
+
if sname is not None:
|
|
190
|
+
return os.path.join(self.examples_dir, sname)
|
|
191
|
+
return None
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import binascii
|
|
2
|
+
import os
|
|
3
|
+
import re
|
|
4
|
+
import sys
|
|
5
|
+
import time
|
|
6
|
+
from datetime import timedelta, datetime
|
|
7
|
+
from io import SEEK_END
|
|
8
|
+
from typing import List
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class LogFile:
|
|
12
|
+
|
|
13
|
+
def __init__(self, path: str):
|
|
14
|
+
self._path = path
|
|
15
|
+
self._start_pos = 0
|
|
16
|
+
self._last_pos = self._start_pos
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def path(self) -> str:
|
|
20
|
+
return self._path
|
|
21
|
+
|
|
22
|
+
def reset(self):
|
|
23
|
+
self._start_pos = 0
|
|
24
|
+
self._last_pos = self._start_pos
|
|
25
|
+
|
|
26
|
+
def advance(self) -> None:
|
|
27
|
+
if os.path.isfile(self._path):
|
|
28
|
+
with open(self._path) as fd:
|
|
29
|
+
self._start_pos = fd.seek(0, SEEK_END)
|
|
30
|
+
|
|
31
|
+
def get_recent(self, advance=True) -> List[str]:
|
|
32
|
+
lines = []
|
|
33
|
+
if os.path.isfile(self._path):
|
|
34
|
+
with open(self._path) as fd:
|
|
35
|
+
fd.seek(self._last_pos, os.SEEK_SET)
|
|
36
|
+
for line in fd:
|
|
37
|
+
lines.append(line)
|
|
38
|
+
if advance:
|
|
39
|
+
self._last_pos = fd.tell()
|
|
40
|
+
return lines
|
|
41
|
+
|
|
42
|
+
def scan_recent(self, pattern: re, timeout=10) -> bool:
|
|
43
|
+
if not os.path.isfile(self.path):
|
|
44
|
+
return False
|
|
45
|
+
with open(self.path) as fd:
|
|
46
|
+
end = datetime.now() + timedelta(seconds=timeout)
|
|
47
|
+
while True:
|
|
48
|
+
fd.seek(self._last_pos, os.SEEK_SET)
|
|
49
|
+
for line in fd:
|
|
50
|
+
if pattern.match(line):
|
|
51
|
+
return True
|
|
52
|
+
if datetime.now() > end:
|
|
53
|
+
raise TimeoutError(f"pattern not found in error log after {timeout} seconds")
|
|
54
|
+
time.sleep(.1)
|
|
55
|
+
return False
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class HexDumpScanner:
|
|
59
|
+
|
|
60
|
+
def __init__(self, source, leading_regex=None):
|
|
61
|
+
self._source = source
|
|
62
|
+
self._leading_regex = leading_regex
|
|
63
|
+
|
|
64
|
+
def __iter__(self):
|
|
65
|
+
data = b''
|
|
66
|
+
offset = 0 if self._leading_regex is None else -1
|
|
67
|
+
idx = 0
|
|
68
|
+
for l in self._source:
|
|
69
|
+
if offset == -1:
|
|
70
|
+
pass
|
|
71
|
+
elif offset == 0:
|
|
72
|
+
# possible start of a hex dump
|
|
73
|
+
m = re.match(r'^\s*0+(\s+-)?((\s+[0-9a-f]{2}){1,16})(\s+.*)$',
|
|
74
|
+
l, re.IGNORECASE)
|
|
75
|
+
if m:
|
|
76
|
+
data = binascii.unhexlify(re.sub(r'\s+', '', m.group(2)))
|
|
77
|
+
offset = 16
|
|
78
|
+
idx = 1
|
|
79
|
+
continue
|
|
80
|
+
else:
|
|
81
|
+
# possible continuation of a hexdump
|
|
82
|
+
m = re.match(r'^\s*([0-9a-f]+)(\s+-)?((\s+[0-9a-f]{2}){1,16})'
|
|
83
|
+
r'(\s+.*)$', l, re.IGNORECASE)
|
|
84
|
+
if m:
|
|
85
|
+
loffset = int(m.group(1), 16)
|
|
86
|
+
if loffset == offset or loffset == idx:
|
|
87
|
+
data += binascii.unhexlify(re.sub(r'\s+', '',
|
|
88
|
+
m.group(3)))
|
|
89
|
+
offset += 16
|
|
90
|
+
idx += 1
|
|
91
|
+
continue
|
|
92
|
+
else:
|
|
93
|
+
sys.stderr.write(f'wrong offset {loffset}, expected {offset} or {idx}\n')
|
|
94
|
+
# not a hexdump line, produce any collected data
|
|
95
|
+
if len(data) > 0:
|
|
96
|
+
yield data
|
|
97
|
+
data = b''
|
|
98
|
+
offset = 0 if self._leading_regex is None \
|
|
99
|
+
or self._leading_regex.match(l) else -1
|
|
100
|
+
if len(data) > 0:
|
|
101
|
+
yield data
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
import re
|
|
4
|
+
import subprocess
|
|
5
|
+
import time
|
|
6
|
+
from datetime import datetime, timedelta
|
|
7
|
+
from threading import Thread
|
|
8
|
+
|
|
9
|
+
from .tls import HandShake
|
|
10
|
+
from .env import Env, CryptoLib
|
|
11
|
+
from .log import LogFile, HexDumpScanner
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
log = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ServerRun:
|
|
18
|
+
|
|
19
|
+
def __init__(self, env: Env, logfile: LogFile):
|
|
20
|
+
self.env = env
|
|
21
|
+
self._logfile = logfile
|
|
22
|
+
self.log_lines = self._logfile.get_recent()
|
|
23
|
+
self._data_recs = None
|
|
24
|
+
self._hs_recs = None
|
|
25
|
+
if self.env.verbose > 1:
|
|
26
|
+
log.debug(f'read {len(self.log_lines)} lines from {logfile.path}')
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def handshake(self):
|
|
30
|
+
if self._data_recs is None:
|
|
31
|
+
self._data_recs = [data for data in HexDumpScanner(source=self.log_lines)]
|
|
32
|
+
if self.env.verbose > 1:
|
|
33
|
+
log.debug(f'detected {len(self._data_recs)} hexdumps '
|
|
34
|
+
f'in {self._logfile.path}')
|
|
35
|
+
if self._hs_recs is None:
|
|
36
|
+
self._hs_recs = [hrec for hrec in HandShake(source=self._data_recs,
|
|
37
|
+
verbose=self.env.verbose)]
|
|
38
|
+
if self.env.verbose > 1:
|
|
39
|
+
log.debug(f'detected {len(self._hs_recs)} crypto records '
|
|
40
|
+
f'in {self._logfile.path}')
|
|
41
|
+
return self._hs_recs
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def hs_stripe(self):
|
|
45
|
+
return ":".join([hrec.name for hrec in self.handshake])
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def monitor_proc(env: Env, proc):
|
|
49
|
+
_env = env
|
|
50
|
+
proc.wait()
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class ExampleServer:
|
|
54
|
+
|
|
55
|
+
def __init__(self, env: Env, crypto_lib: str, verify_client=False):
|
|
56
|
+
self.env = env
|
|
57
|
+
self._crypto_lib = crypto_lib
|
|
58
|
+
self._path = env.server_path(self._crypto_lib)
|
|
59
|
+
self._logpath = f'{self.env.gen_dir}/{self._crypto_lib}-server.log'
|
|
60
|
+
self._log = LogFile(path=self._logpath)
|
|
61
|
+
self._logfile = None
|
|
62
|
+
self._process = None
|
|
63
|
+
self._verify_client = verify_client
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def path(self):
|
|
67
|
+
return self._path
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def crypto_lib(self):
|
|
71
|
+
return self._crypto_lib
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def uses_cipher_config(self):
|
|
75
|
+
return CryptoLib.uses_cipher_config(self.crypto_lib)
|
|
76
|
+
|
|
77
|
+
def supports_cipher(self, cipher):
|
|
78
|
+
return CryptoLib.supports_cipher(self.crypto_lib, cipher)
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def log(self):
|
|
82
|
+
return self._log
|
|
83
|
+
|
|
84
|
+
def exists(self):
|
|
85
|
+
return os.path.isfile(self.path)
|
|
86
|
+
|
|
87
|
+
def start(self):
|
|
88
|
+
if self._process is not None:
|
|
89
|
+
return False
|
|
90
|
+
creds = self.env.get_server_credentials()
|
|
91
|
+
assert creds
|
|
92
|
+
args = [
|
|
93
|
+
self.path,
|
|
94
|
+
f'--htdocs={self.env.htdocs_dir}',
|
|
95
|
+
]
|
|
96
|
+
if self._verify_client:
|
|
97
|
+
args.append('--verify-client')
|
|
98
|
+
args.extend([
|
|
99
|
+
'*', str(self.env.examples_port),
|
|
100
|
+
creds.pkey_file, creds.cert_file
|
|
101
|
+
])
|
|
102
|
+
self._logfile = open(self._logpath, 'w')
|
|
103
|
+
self._process = subprocess.Popen(args=args, text=True,
|
|
104
|
+
stdout=self._logfile, stderr=self._logfile)
|
|
105
|
+
t = Thread(target=monitor_proc, daemon=True, args=(self.env, self._process))
|
|
106
|
+
t.start()
|
|
107
|
+
timeout = 5
|
|
108
|
+
end = datetime.now() + timedelta(seconds=timeout)
|
|
109
|
+
while True:
|
|
110
|
+
if self._process.poll():
|
|
111
|
+
return False
|
|
112
|
+
try:
|
|
113
|
+
if self.log.scan_recent(pattern=re.compile(r'^Using document root'), timeout=0.5):
|
|
114
|
+
break
|
|
115
|
+
except TimeoutError:
|
|
116
|
+
pass
|
|
117
|
+
if datetime.now() > end:
|
|
118
|
+
raise TimeoutError(f"pattern not found in error log after {timeout} seconds")
|
|
119
|
+
self.log.advance()
|
|
120
|
+
return True
|
|
121
|
+
|
|
122
|
+
def stop(self):
|
|
123
|
+
if self._process:
|
|
124
|
+
self._process.terminate()
|
|
125
|
+
self._process = None
|
|
126
|
+
if self._logfile:
|
|
127
|
+
self._logfile.close()
|
|
128
|
+
self._logfile = None
|
|
129
|
+
return True
|
|
130
|
+
|
|
131
|
+
def restart(self):
|
|
132
|
+
self.stop()
|
|
133
|
+
self._log.reset()
|
|
134
|
+
return self.start()
|
|
135
|
+
|
|
136
|
+
def get_run(self) -> ServerRun:
|
|
137
|
+
return ServerRun(env=self.env, logfile=self.log)
|