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.
Files changed (343) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/ext/ngtcp2/AUTHORS +44 -0
  4. data/ext/ngtcp2/CMakeLists.txt +431 -0
  5. data/ext/ngtcp2/CMakeOptions.txt +17 -0
  6. data/ext/ngtcp2/COPYING +22 -0
  7. data/ext/ngtcp2/ChangeLog +0 -0
  8. data/ext/ngtcp2/Makefile.am +60 -0
  9. data/ext/ngtcp2/NEWS +0 -0
  10. data/ext/ngtcp2/README +1 -0
  11. data/ext/ngtcp2/README.rst +258 -0
  12. data/ext/ngtcp2/ci/build_boringssl.sh +10 -0
  13. data/ext/ngtcp2/ci/build_nghttp3.sh +9 -0
  14. data/ext/ngtcp2/ci/build_openssl1.sh +8 -0
  15. data/ext/ngtcp2/ci/build_openssl1_cross.sh +9 -0
  16. data/ext/ngtcp2/ci/build_openssl3.sh +8 -0
  17. data/ext/ngtcp2/ci/build_picotls.sh +26 -0
  18. data/ext/ngtcp2/ci/build_wolfssl.sh +9 -0
  19. data/ext/ngtcp2/ci/gen-certificate.sh +8 -0
  20. data/ext/ngtcp2/cmake/ExtractValidFlags.cmake +31 -0
  21. data/ext/ngtcp2/cmake/FindCUnit.cmake +40 -0
  22. data/ext/ngtcp2/cmake/FindJemalloc.cmake +40 -0
  23. data/ext/ngtcp2/cmake/FindLibev.cmake +38 -0
  24. data/ext/ngtcp2/cmake/FindLibnghttp3.cmake +41 -0
  25. data/ext/ngtcp2/cmake/Findwolfssl.cmake +41 -0
  26. data/ext/ngtcp2/cmake/Version.cmake +11 -0
  27. data/ext/ngtcp2/cmakeconfig.h.in +36 -0
  28. data/ext/ngtcp2/configure.ac +755 -0
  29. data/ext/ngtcp2/crypto/CMakeLists.txt +56 -0
  30. data/ext/ngtcp2/crypto/Makefile.am +49 -0
  31. data/ext/ngtcp2/crypto/boringssl/CMakeLists.txt +64 -0
  32. data/ext/ngtcp2/crypto/boringssl/Makefile.am +39 -0
  33. data/ext/ngtcp2/crypto/boringssl/boringssl.c +630 -0
  34. data/ext/ngtcp2/crypto/boringssl/libngtcp2_crypto_boringssl.pc.in +33 -0
  35. data/ext/ngtcp2/crypto/gnutls/CMakeLists.txt +86 -0
  36. data/ext/ngtcp2/crypto/gnutls/Makefile.am +43 -0
  37. data/ext/ngtcp2/crypto/gnutls/gnutls.c +644 -0
  38. data/ext/ngtcp2/crypto/gnutls/libngtcp2_crypto_gnutls.pc.in +33 -0
  39. data/ext/ngtcp2/crypto/includes/CMakeLists.txt +56 -0
  40. data/ext/ngtcp2/crypto/includes/Makefile.am +45 -0
  41. data/ext/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h +893 -0
  42. data/ext/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_boringssl.h +104 -0
  43. data/ext/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_gnutls.h +107 -0
  44. data/ext/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_openssl.h +132 -0
  45. data/ext/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_picotls.h +246 -0
  46. data/ext/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_wolfssl.h +106 -0
  47. data/ext/ngtcp2/crypto/openssl/CMakeLists.txt +86 -0
  48. data/ext/ngtcp2/crypto/openssl/Makefile.am +43 -0
  49. data/ext/ngtcp2/crypto/openssl/libngtcp2_crypto_openssl.pc.in +33 -0
  50. data/ext/ngtcp2/crypto/openssl/openssl.c +807 -0
  51. data/ext/ngtcp2/crypto/picotls/CMakeLists.txt +65 -0
  52. data/ext/ngtcp2/crypto/picotls/Makefile.am +39 -0
  53. data/ext/ngtcp2/crypto/picotls/libngtcp2_crypto_picotls.pc.in +33 -0
  54. data/ext/ngtcp2/crypto/picotls/picotls.c +707 -0
  55. data/ext/ngtcp2/crypto/shared.c +1431 -0
  56. data/ext/ngtcp2/crypto/shared.h +350 -0
  57. data/ext/ngtcp2/crypto/wolfssl/CMakeLists.txt +84 -0
  58. data/ext/ngtcp2/crypto/wolfssl/Makefile.am +43 -0
  59. data/ext/ngtcp2/crypto/wolfssl/libngtcp2_crypto_wolfssl.pc.in +33 -0
  60. data/ext/ngtcp2/crypto/wolfssl/wolfssl.c +534 -0
  61. data/ext/ngtcp2/doc/Makefile.am +65 -0
  62. data/ext/ngtcp2/doc/make.bat +35 -0
  63. data/ext/ngtcp2/doc/mkapiref.py +356 -0
  64. data/ext/ngtcp2/doc/source/conf.py.in +94 -0
  65. data/ext/ngtcp2/doc/source/index.rst +22 -0
  66. data/ext/ngtcp2/doc/source/programmers-guide.rst +476 -0
  67. data/ext/ngtcp2/docker/Dockerfile +39 -0
  68. data/ext/ngtcp2/examples/CMakeLists.txt +361 -0
  69. data/ext/ngtcp2/examples/Makefile.am +228 -0
  70. data/ext/ngtcp2/examples/client.cc +3049 -0
  71. data/ext/ngtcp2/examples/client.h +192 -0
  72. data/ext/ngtcp2/examples/client_base.cc +202 -0
  73. data/ext/ngtcp2/examples/client_base.h +213 -0
  74. data/ext/ngtcp2/examples/debug.cc +298 -0
  75. data/ext/ngtcp2/examples/debug.h +124 -0
  76. data/ext/ngtcp2/examples/examplestest.cc +84 -0
  77. data/ext/ngtcp2/examples/gtlssimpleclient.c +720 -0
  78. data/ext/ngtcp2/examples/h09client.cc +2601 -0
  79. data/ext/ngtcp2/examples/h09client.h +196 -0
  80. data/ext/ngtcp2/examples/h09server.cc +3024 -0
  81. data/ext/ngtcp2/examples/h09server.h +237 -0
  82. data/ext/ngtcp2/examples/http.cc +138 -0
  83. data/ext/ngtcp2/examples/http.h +44 -0
  84. data/ext/ngtcp2/examples/network.h +80 -0
  85. data/ext/ngtcp2/examples/server.cc +3731 -0
  86. data/ext/ngtcp2/examples/server.h +256 -0
  87. data/ext/ngtcp2/examples/server_base.cc +58 -0
  88. data/ext/ngtcp2/examples/server_base.h +195 -0
  89. data/ext/ngtcp2/examples/shared.cc +385 -0
  90. data/ext/ngtcp2/examples/shared.h +96 -0
  91. data/ext/ngtcp2/examples/simpleclient.c +683 -0
  92. data/ext/ngtcp2/examples/template.h +71 -0
  93. data/ext/ngtcp2/examples/tests/README.rst +60 -0
  94. data/ext/ngtcp2/examples/tests/__init__.py +0 -0
  95. data/ext/ngtcp2/examples/tests/config.ini.in +32 -0
  96. data/ext/ngtcp2/examples/tests/conftest.py +28 -0
  97. data/ext/ngtcp2/examples/tests/ngtcp2test/__init__.py +6 -0
  98. data/ext/ngtcp2/examples/tests/ngtcp2test/certs.py +476 -0
  99. data/ext/ngtcp2/examples/tests/ngtcp2test/client.py +187 -0
  100. data/ext/ngtcp2/examples/tests/ngtcp2test/env.py +191 -0
  101. data/ext/ngtcp2/examples/tests/ngtcp2test/log.py +101 -0
  102. data/ext/ngtcp2/examples/tests/ngtcp2test/server.py +137 -0
  103. data/ext/ngtcp2/examples/tests/ngtcp2test/tls.py +983 -0
  104. data/ext/ngtcp2/examples/tests/test_01_handshake.py +30 -0
  105. data/ext/ngtcp2/examples/tests/test_02_resume.py +46 -0
  106. data/ext/ngtcp2/examples/tests/test_03_earlydata.py +56 -0
  107. data/ext/ngtcp2/examples/tests/test_04_clientcert.py +57 -0
  108. data/ext/ngtcp2/examples/tests/test_05_ciphers.py +46 -0
  109. data/ext/ngtcp2/examples/tls_client_context.h +52 -0
  110. data/ext/ngtcp2/examples/tls_client_context_boringssl.cc +126 -0
  111. data/ext/ngtcp2/examples/tls_client_context_boringssl.h +49 -0
  112. data/ext/ngtcp2/examples/tls_client_context_gnutls.cc +74 -0
  113. data/ext/ngtcp2/examples/tls_client_context_gnutls.h +50 -0
  114. data/ext/ngtcp2/examples/tls_client_context_openssl.cc +137 -0
  115. data/ext/ngtcp2/examples/tls_client_context_openssl.h +49 -0
  116. data/ext/ngtcp2/examples/tls_client_context_picotls.cc +158 -0
  117. data/ext/ngtcp2/examples/tls_client_context_picotls.h +53 -0
  118. data/ext/ngtcp2/examples/tls_client_context_wolfssl.cc +177 -0
  119. data/ext/ngtcp2/examples/tls_client_context_wolfssl.h +51 -0
  120. data/ext/ngtcp2/examples/tls_client_session.h +52 -0
  121. data/ext/ngtcp2/examples/tls_client_session_boringssl.cc +110 -0
  122. data/ext/ngtcp2/examples/tls_client_session_boringssl.h +52 -0
  123. data/ext/ngtcp2/examples/tls_client_session_gnutls.cc +190 -0
  124. data/ext/ngtcp2/examples/tls_client_session_gnutls.h +52 -0
  125. data/ext/ngtcp2/examples/tls_client_session_openssl.cc +113 -0
  126. data/ext/ngtcp2/examples/tls_client_session_openssl.h +52 -0
  127. data/ext/ngtcp2/examples/tls_client_session_picotls.cc +147 -0
  128. data/ext/ngtcp2/examples/tls_client_session_picotls.h +52 -0
  129. data/ext/ngtcp2/examples/tls_client_session_wolfssl.cc +160 -0
  130. data/ext/ngtcp2/examples/tls_client_session_wolfssl.h +52 -0
  131. data/ext/ngtcp2/examples/tls_server_context.h +52 -0
  132. data/ext/ngtcp2/examples/tls_server_context_boringssl.cc +257 -0
  133. data/ext/ngtcp2/examples/tls_server_context_boringssl.h +54 -0
  134. data/ext/ngtcp2/examples/tls_server_context_gnutls.cc +99 -0
  135. data/ext/ngtcp2/examples/tls_server_context_gnutls.h +59 -0
  136. data/ext/ngtcp2/examples/tls_server_context_openssl.cc +338 -0
  137. data/ext/ngtcp2/examples/tls_server_context_openssl.h +54 -0
  138. data/ext/ngtcp2/examples/tls_server_context_picotls.cc +321 -0
  139. data/ext/ngtcp2/examples/tls_server_context_picotls.h +58 -0
  140. data/ext/ngtcp2/examples/tls_server_context_wolfssl.cc +284 -0
  141. data/ext/ngtcp2/examples/tls_server_context_wolfssl.h +55 -0
  142. data/ext/ngtcp2/examples/tls_server_session.h +52 -0
  143. data/ext/ngtcp2/examples/tls_server_session_boringssl.cc +84 -0
  144. data/ext/ngtcp2/examples/tls_server_session_boringssl.h +47 -0
  145. data/ext/ngtcp2/examples/tls_server_session_gnutls.cc +155 -0
  146. data/ext/ngtcp2/examples/tls_server_session_gnutls.h +46 -0
  147. data/ext/ngtcp2/examples/tls_server_session_openssl.cc +54 -0
  148. data/ext/ngtcp2/examples/tls_server_session_openssl.h +47 -0
  149. data/ext/ngtcp2/examples/tls_server_session_picotls.cc +70 -0
  150. data/ext/ngtcp2/examples/tls_server_session_picotls.h +47 -0
  151. data/ext/ngtcp2/examples/tls_server_session_wolfssl.cc +55 -0
  152. data/ext/ngtcp2/examples/tls_server_session_wolfssl.h +47 -0
  153. data/ext/ngtcp2/examples/tls_session_base_gnutls.cc +87 -0
  154. data/ext/ngtcp2/examples/tls_session_base_gnutls.h +51 -0
  155. data/ext/ngtcp2/examples/tls_session_base_openssl.cc +54 -0
  156. data/ext/ngtcp2/examples/tls_session_base_openssl.h +52 -0
  157. data/ext/ngtcp2/examples/tls_session_base_picotls.cc +56 -0
  158. data/ext/ngtcp2/examples/tls_session_base_picotls.h +54 -0
  159. data/ext/ngtcp2/examples/tls_session_base_wolfssl.cc +54 -0
  160. data/ext/ngtcp2/examples/tls_session_base_wolfssl.h +54 -0
  161. data/ext/ngtcp2/examples/tls_shared_picotls.cc +59 -0
  162. data/ext/ngtcp2/examples/tls_shared_picotls.h +36 -0
  163. data/ext/ngtcp2/examples/util.cc +646 -0
  164. data/ext/ngtcp2/examples/util.h +361 -0
  165. data/ext/ngtcp2/examples/util_gnutls.cc +136 -0
  166. data/ext/ngtcp2/examples/util_openssl.cc +131 -0
  167. data/ext/ngtcp2/examples/util_test.cc +237 -0
  168. data/ext/ngtcp2/examples/util_test.h +45 -0
  169. data/ext/ngtcp2/examples/util_wolfssl.cc +130 -0
  170. data/ext/ngtcp2/fuzz/corpus/decode_frame/ack +0 -0
  171. data/ext/ngtcp2/fuzz/corpus/decode_frame/ack_ecn +0 -0
  172. data/ext/ngtcp2/fuzz/corpus/decode_frame/connection_close +0 -0
  173. data/ext/ngtcp2/fuzz/corpus/decode_frame/crypto +1 -0
  174. data/ext/ngtcp2/fuzz/corpus/decode_frame/data_blocked +1 -0
  175. data/ext/ngtcp2/fuzz/corpus/decode_frame/datagram +1 -0
  176. data/ext/ngtcp2/fuzz/corpus/decode_frame/datagram_len +1 -0
  177. data/ext/ngtcp2/fuzz/corpus/decode_frame/max_data +1 -0
  178. data/ext/ngtcp2/fuzz/corpus/decode_frame/max_stream_data +0 -0
  179. data/ext/ngtcp2/fuzz/corpus/decode_frame/max_streams +0 -0
  180. data/ext/ngtcp2/fuzz/corpus/decode_frame/new_connection_id +1 -0
  181. data/ext/ngtcp2/fuzz/corpus/decode_frame/new_token +1 -0
  182. data/ext/ngtcp2/fuzz/corpus/decode_frame/path_challenge +1 -0
  183. data/ext/ngtcp2/fuzz/corpus/decode_frame/path_response +1 -0
  184. data/ext/ngtcp2/fuzz/corpus/decode_frame/reset_stream +0 -0
  185. data/ext/ngtcp2/fuzz/corpus/decode_frame/retire_connection_id +1 -0
  186. data/ext/ngtcp2/fuzz/corpus/decode_frame/stop_sending +0 -0
  187. data/ext/ngtcp2/fuzz/corpus/decode_frame/stream +0 -0
  188. data/ext/ngtcp2/fuzz/corpus/decode_frame/stream_data_blocked +0 -0
  189. data/ext/ngtcp2/fuzz/corpus/decode_frame/stream_len +0 -0
  190. data/ext/ngtcp2/fuzz/corpus/decode_frame/streams_blocked +0 -0
  191. data/ext/ngtcp2/fuzz/corpus/ksl/random +0 -0
  192. data/ext/ngtcp2/fuzz/decode_frame.cc +25 -0
  193. data/ext/ngtcp2/fuzz/ksl.cc +77 -0
  194. data/ext/ngtcp2/interop/Dockerfile +39 -0
  195. data/ext/ngtcp2/interop/run_endpoint.sh +93 -0
  196. data/ext/ngtcp2/lib/CMakeLists.txt +110 -0
  197. data/ext/ngtcp2/lib/Makefile.am +122 -0
  198. data/ext/ngtcp2/lib/includes/CMakeLists.txt +4 -0
  199. data/ext/ngtcp2/lib/includes/Makefile.am +25 -0
  200. data/ext/ngtcp2/lib/includes/ngtcp2/ngtcp2.h +5843 -0
  201. data/ext/ngtcp2/lib/includes/ngtcp2/version.h.in +51 -0
  202. data/ext/ngtcp2/lib/libngtcp2.pc.in +33 -0
  203. data/ext/ngtcp2/lib/ngtcp2_acktr.c +335 -0
  204. data/ext/ngtcp2/lib/ngtcp2_acktr.h +221 -0
  205. data/ext/ngtcp2/lib/ngtcp2_addr.c +117 -0
  206. data/ext/ngtcp2/lib/ngtcp2_addr.h +69 -0
  207. data/ext/ngtcp2/lib/ngtcp2_balloc.c +90 -0
  208. data/ext/ngtcp2/lib/ngtcp2_balloc.h +91 -0
  209. data/ext/ngtcp2/lib/ngtcp2_bbr.c +693 -0
  210. data/ext/ngtcp2/lib/ngtcp2_bbr.h +157 -0
  211. data/ext/ngtcp2/lib/ngtcp2_bbr2.c +1490 -0
  212. data/ext/ngtcp2/lib/ngtcp2_bbr2.h +149 -0
  213. data/ext/ngtcp2/lib/ngtcp2_buf.c +56 -0
  214. data/ext/ngtcp2/lib/ngtcp2_buf.h +108 -0
  215. data/ext/ngtcp2/lib/ngtcp2_cc.c +616 -0
  216. data/ext/ngtcp2/lib/ngtcp2_cc.h +422 -0
  217. data/ext/ngtcp2/lib/ngtcp2_cid.c +147 -0
  218. data/ext/ngtcp2/lib/ngtcp2_cid.h +175 -0
  219. data/ext/ngtcp2/lib/ngtcp2_conn.c +13731 -0
  220. data/ext/ngtcp2/lib/ngtcp2_conn.h +1119 -0
  221. data/ext/ngtcp2/lib/ngtcp2_conn_stat.h +131 -0
  222. data/ext/ngtcp2/lib/ngtcp2_conv.c +291 -0
  223. data/ext/ngtcp2/lib/ngtcp2_conv.h +208 -0
  224. data/ext/ngtcp2/lib/ngtcp2_crypto.c +895 -0
  225. data/ext/ngtcp2/lib/ngtcp2_crypto.h +148 -0
  226. data/ext/ngtcp2/lib/ngtcp2_err.c +154 -0
  227. data/ext/ngtcp2/lib/ngtcp2_err.h +34 -0
  228. data/ext/ngtcp2/lib/ngtcp2_gaptr.c +167 -0
  229. data/ext/ngtcp2/lib/ngtcp2_gaptr.h +98 -0
  230. data/ext/ngtcp2/lib/ngtcp2_idtr.c +79 -0
  231. data/ext/ngtcp2/lib/ngtcp2_idtr.h +89 -0
  232. data/ext/ngtcp2/lib/ngtcp2_ksl.c +819 -0
  233. data/ext/ngtcp2/lib/ngtcp2_ksl.h +345 -0
  234. data/ext/ngtcp2/lib/ngtcp2_log.c +822 -0
  235. data/ext/ngtcp2/lib/ngtcp2_log.h +123 -0
  236. data/ext/ngtcp2/lib/ngtcp2_macro.h +58 -0
  237. data/ext/ngtcp2/lib/ngtcp2_map.c +336 -0
  238. data/ext/ngtcp2/lib/ngtcp2_map.h +136 -0
  239. data/ext/ngtcp2/lib/ngtcp2_mem.c +113 -0
  240. data/ext/ngtcp2/lib/ngtcp2_mem.h +72 -0
  241. data/ext/ngtcp2/lib/ngtcp2_net.h +136 -0
  242. data/ext/ngtcp2/lib/ngtcp2_objalloc.c +40 -0
  243. data/ext/ngtcp2/lib/ngtcp2_objalloc.h +140 -0
  244. data/ext/ngtcp2/lib/ngtcp2_opl.c +46 -0
  245. data/ext/ngtcp2/lib/ngtcp2_opl.h +65 -0
  246. data/ext/ngtcp2/lib/ngtcp2_path.c +77 -0
  247. data/ext/ngtcp2/lib/ngtcp2_path.h +49 -0
  248. data/ext/ngtcp2/lib/ngtcp2_pkt.c +2527 -0
  249. data/ext/ngtcp2/lib/ngtcp2_pkt.h +1235 -0
  250. data/ext/ngtcp2/lib/ngtcp2_pmtud.c +160 -0
  251. data/ext/ngtcp2/lib/ngtcp2_pmtud.h +123 -0
  252. data/ext/ngtcp2/lib/ngtcp2_ppe.c +230 -0
  253. data/ext/ngtcp2/lib/ngtcp2_ppe.h +153 -0
  254. data/ext/ngtcp2/lib/ngtcp2_pq.c +164 -0
  255. data/ext/ngtcp2/lib/ngtcp2_pq.h +126 -0
  256. data/ext/ngtcp2/lib/ngtcp2_pv.c +172 -0
  257. data/ext/ngtcp2/lib/ngtcp2_pv.h +194 -0
  258. data/ext/ngtcp2/lib/ngtcp2_qlog.c +1219 -0
  259. data/ext/ngtcp2/lib/ngtcp2_qlog.h +161 -0
  260. data/ext/ngtcp2/lib/ngtcp2_range.c +61 -0
  261. data/ext/ngtcp2/lib/ngtcp2_range.h +80 -0
  262. data/ext/ngtcp2/lib/ngtcp2_rcvry.h +40 -0
  263. data/ext/ngtcp2/lib/ngtcp2_ringbuf.c +121 -0
  264. data/ext/ngtcp2/lib/ngtcp2_ringbuf.h +132 -0
  265. data/ext/ngtcp2/lib/ngtcp2_rob.c +319 -0
  266. data/ext/ngtcp2/lib/ngtcp2_rob.h +197 -0
  267. data/ext/ngtcp2/lib/ngtcp2_rst.c +138 -0
  268. data/ext/ngtcp2/lib/ngtcp2_rst.h +86 -0
  269. data/ext/ngtcp2/lib/ngtcp2_rtb.c +1676 -0
  270. data/ext/ngtcp2/lib/ngtcp2_rtb.h +468 -0
  271. data/ext/ngtcp2/lib/ngtcp2_str.c +233 -0
  272. data/ext/ngtcp2/lib/ngtcp2_str.h +94 -0
  273. data/ext/ngtcp2/lib/ngtcp2_strm.c +698 -0
  274. data/ext/ngtcp2/lib/ngtcp2_strm.h +310 -0
  275. data/ext/ngtcp2/lib/ngtcp2_unreachable.c +71 -0
  276. data/ext/ngtcp2/lib/ngtcp2_unreachable.h +46 -0
  277. data/ext/ngtcp2/lib/ngtcp2_vec.c +243 -0
  278. data/ext/ngtcp2/lib/ngtcp2_vec.h +120 -0
  279. data/ext/ngtcp2/lib/ngtcp2_version.c +39 -0
  280. data/ext/ngtcp2/lib/ngtcp2_window_filter.c +99 -0
  281. data/ext/ngtcp2/lib/ngtcp2_window_filter.h +65 -0
  282. data/ext/ngtcp2/m4/ax_check_compile_flag.m4 +74 -0
  283. data/ext/ngtcp2/m4/ax_cxx_compile_stdcxx.m4 +1009 -0
  284. data/ext/ngtcp2/tests/CMakeLists.txt +68 -0
  285. data/ext/ngtcp2/tests/Makefile.am +94 -0
  286. data/ext/ngtcp2/tests/main.c +358 -0
  287. data/ext/ngtcp2/tests/ngtcp2_acktr_test.c +367 -0
  288. data/ext/ngtcp2/tests/ngtcp2_acktr_test.h +37 -0
  289. data/ext/ngtcp2/tests/ngtcp2_conn_test.c +9821 -0
  290. data/ext/ngtcp2/tests/ngtcp2_conn_test.h +104 -0
  291. data/ext/ngtcp2/tests/ngtcp2_conv_test.c +430 -0
  292. data/ext/ngtcp2/tests/ngtcp2_conv_test.h +46 -0
  293. data/ext/ngtcp2/tests/ngtcp2_crypto_test.c +667 -0
  294. data/ext/ngtcp2/tests/ngtcp2_crypto_test.h +35 -0
  295. data/ext/ngtcp2/tests/ngtcp2_gaptr_test.c +127 -0
  296. data/ext/ngtcp2/tests/ngtcp2_gaptr_test.h +36 -0
  297. data/ext/ngtcp2/tests/ngtcp2_idtr_test.c +79 -0
  298. data/ext/ngtcp2/tests/ngtcp2_idtr_test.h +34 -0
  299. data/ext/ngtcp2/tests/ngtcp2_ksl_test.c +502 -0
  300. data/ext/ngtcp2/tests/ngtcp2_ksl_test.h +39 -0
  301. data/ext/ngtcp2/tests/ngtcp2_map_test.c +206 -0
  302. data/ext/ngtcp2/tests/ngtcp2_map_test.h +38 -0
  303. data/ext/ngtcp2/tests/ngtcp2_pkt_test.c +1645 -0
  304. data/ext/ngtcp2/tests/ngtcp2_pkt_test.h +68 -0
  305. data/ext/ngtcp2/tests/ngtcp2_pmtud_test.c +153 -0
  306. data/ext/ngtcp2/tests/ngtcp2_pmtud_test.h +34 -0
  307. data/ext/ngtcp2/tests/ngtcp2_pv_test.c +129 -0
  308. data/ext/ngtcp2/tests/ngtcp2_pv_test.h +35 -0
  309. data/ext/ngtcp2/tests/ngtcp2_range_test.c +105 -0
  310. data/ext/ngtcp2/tests/ngtcp2_range_test.h +36 -0
  311. data/ext/ngtcp2/tests/ngtcp2_ringbuf_test.c +91 -0
  312. data/ext/ngtcp2/tests/ngtcp2_ringbuf_test.h +35 -0
  313. data/ext/ngtcp2/tests/ngtcp2_rob_test.c +552 -0
  314. data/ext/ngtcp2/tests/ngtcp2_rob_test.h +37 -0
  315. data/ext/ngtcp2/tests/ngtcp2_rtb_test.c +470 -0
  316. data/ext/ngtcp2/tests/ngtcp2_rtb_test.h +38 -0
  317. data/ext/ngtcp2/tests/ngtcp2_str_test.c +96 -0
  318. data/ext/ngtcp2/tests/ngtcp2_str_test.h +36 -0
  319. data/ext/ngtcp2/tests/ngtcp2_strm_test.c +575 -0
  320. data/ext/ngtcp2/tests/ngtcp2_strm_test.h +36 -0
  321. data/ext/ngtcp2/tests/ngtcp2_test_helper.c +404 -0
  322. data/ext/ngtcp2/tests/ngtcp2_test_helper.h +191 -0
  323. data/ext/ngtcp2/tests/ngtcp2_vec_test.c +426 -0
  324. data/ext/ngtcp2/tests/ngtcp2_vec_test.h +36 -0
  325. data/ext/ngtcp2/third-party/CMakeLists.txt +34 -0
  326. data/ext/ngtcp2/third-party/Makefile.am +31 -0
  327. data/ext/ngtcp2/third-party/http-parser/AUTHORS +68 -0
  328. data/ext/ngtcp2/third-party/http-parser/LICENSE-MIT +23 -0
  329. data/ext/ngtcp2/third-party/http-parser/Makefile +157 -0
  330. data/ext/ngtcp2/third-party/http-parser/README.md +246 -0
  331. data/ext/ngtcp2/third-party/http-parser/bench.c +111 -0
  332. data/ext/ngtcp2/third-party/http-parser/contrib/parsertrace.c +160 -0
  333. data/ext/ngtcp2/third-party/http-parser/contrib/url_parser.c +47 -0
  334. data/ext/ngtcp2/third-party/http-parser/http_parser.c +2419 -0
  335. data/ext/ngtcp2/third-party/http-parser/http_parser.gyp +111 -0
  336. data/ext/ngtcp2/third-party/http-parser/http_parser.h +431 -0
  337. data/ext/ngtcp2/third-party/http-parser/test.c +4411 -0
  338. data/lib/protocol/quic/version.rb +10 -0
  339. data/lib/protocol/quic.rb +9 -0
  340. data/license.md +21 -0
  341. data.tar.gz.sig +1 -0
  342. metadata +424 -0
  343. 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)