protocol-quic 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
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,2419 @@
1
+ /* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
2
+ *
3
+ * Additional changes are licensed under the same terms as NGINX and
4
+ * copyright Joyent, Inc. and other Node contributors. All rights reserved.
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to
8
+ * deal in the Software without restriction, including without limitation the
9
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10
+ * sell copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
+ * IN THE SOFTWARE.
23
+ */
24
+ #include "http_parser.h"
25
+ #include <assert.h>
26
+ #include <stddef.h>
27
+ #include <ctype.h>
28
+ #include <stdlib.h>
29
+ #include <string.h>
30
+ #include <limits.h>
31
+
32
+ #ifndef ULLONG_MAX
33
+ # define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */
34
+ #endif
35
+
36
+ #ifndef MIN
37
+ # define MIN(a,b) ((a) < (b) ? (a) : (b))
38
+ #endif
39
+
40
+ #ifndef ARRAY_SIZE
41
+ # define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
42
+ #endif
43
+
44
+ #ifndef BIT_AT
45
+ # define BIT_AT(a, i) \
46
+ (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \
47
+ (1 << ((unsigned int) (i) & 7))))
48
+ #endif
49
+
50
+ #ifndef ELEM_AT
51
+ # define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v))
52
+ #endif
53
+
54
+ #define SET_ERRNO(e) \
55
+ do { \
56
+ parser->http_errno = (e); \
57
+ } while(0)
58
+
59
+ #define CURRENT_STATE() p_state
60
+ #define UPDATE_STATE(V) p_state = (enum state) (V);
61
+ #define RETURN(V) \
62
+ do { \
63
+ parser->state = CURRENT_STATE(); \
64
+ return (V); \
65
+ } while (0);
66
+ #define REEXECUTE() \
67
+ goto reexecute; \
68
+
69
+
70
+ #ifdef __GNUC__
71
+ # define LIKELY(X) __builtin_expect(!!(X), 1)
72
+ # define UNLIKELY(X) __builtin_expect(!!(X), 0)
73
+ #else
74
+ # define LIKELY(X) (X)
75
+ # define UNLIKELY(X) (X)
76
+ #endif
77
+
78
+
79
+ /* Run the notify callback FOR, returning ER if it fails */
80
+ #define CALLBACK_NOTIFY_(FOR, ER) \
81
+ do { \
82
+ assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \
83
+ \
84
+ if (LIKELY(settings->on_##FOR)) { \
85
+ parser->state = CURRENT_STATE(); \
86
+ if (UNLIKELY(0 != settings->on_##FOR(parser))) { \
87
+ SET_ERRNO(HPE_CB_##FOR); \
88
+ } \
89
+ UPDATE_STATE(parser->state); \
90
+ \
91
+ /* We either errored above or got paused; get out */ \
92
+ if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \
93
+ return (ER); \
94
+ } \
95
+ } \
96
+ } while (0)
97
+
98
+ /* Run the notify callback FOR and consume the current byte */
99
+ #define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1)
100
+
101
+ /* Run the notify callback FOR and don't consume the current byte */
102
+ #define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data)
103
+
104
+ /* Run data callback FOR with LEN bytes, returning ER if it fails */
105
+ #define CALLBACK_DATA_(FOR, LEN, ER) \
106
+ do { \
107
+ assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \
108
+ \
109
+ if (FOR##_mark) { \
110
+ if (LIKELY(settings->on_##FOR)) { \
111
+ parser->state = CURRENT_STATE(); \
112
+ if (UNLIKELY(0 != \
113
+ settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \
114
+ SET_ERRNO(HPE_CB_##FOR); \
115
+ } \
116
+ UPDATE_STATE(parser->state); \
117
+ \
118
+ /* We either errored above or got paused; get out */ \
119
+ if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \
120
+ return (ER); \
121
+ } \
122
+ } \
123
+ FOR##_mark = NULL; \
124
+ } \
125
+ } while (0)
126
+
127
+ /* Run the data callback FOR and consume the current byte */
128
+ #define CALLBACK_DATA(FOR) \
129
+ CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1)
130
+
131
+ /* Run the data callback FOR and don't consume the current byte */
132
+ #define CALLBACK_DATA_NOADVANCE(FOR) \
133
+ CALLBACK_DATA_(FOR, p - FOR##_mark, p - data)
134
+
135
+ /* Set the mark FOR; non-destructive if mark is already set */
136
+ #define MARK(FOR) \
137
+ do { \
138
+ if (!FOR##_mark) { \
139
+ FOR##_mark = p; \
140
+ } \
141
+ } while (0)
142
+
143
+ /* Don't allow the total size of the HTTP headers (including the status
144
+ * line) to exceed HTTP_MAX_HEADER_SIZE. This check is here to protect
145
+ * embedders against denial-of-service attacks where the attacker feeds
146
+ * us a never-ending header that the embedder keeps buffering.
147
+ *
148
+ * This check is arguably the responsibility of embedders but we're doing
149
+ * it on the embedder's behalf because most won't bother and this way we
150
+ * make the web a little safer. HTTP_MAX_HEADER_SIZE is still far bigger
151
+ * than any reasonable request or response so this should never affect
152
+ * day-to-day operation.
153
+ */
154
+ #define COUNT_HEADER_SIZE(V) \
155
+ do { \
156
+ parser->nread += (V); \
157
+ if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) { \
158
+ SET_ERRNO(HPE_HEADER_OVERFLOW); \
159
+ goto error; \
160
+ } \
161
+ } while (0)
162
+
163
+
164
+ #define PROXY_CONNECTION "proxy-connection"
165
+ #define CONNECTION "connection"
166
+ #define CONTENT_LENGTH "content-length"
167
+ #define TRANSFER_ENCODING "transfer-encoding"
168
+ #define UPGRADE "upgrade"
169
+ #define CHUNKED "chunked"
170
+ #define KEEP_ALIVE "keep-alive"
171
+ #define CLOSE "close"
172
+
173
+
174
+ static const char *method_strings[] =
175
+ {
176
+ #define XX(num, name, string) #string,
177
+ HTTP_METHOD_MAP(XX)
178
+ #undef XX
179
+ };
180
+
181
+
182
+ /* Tokens as defined by rfc 2616. Also lowercases them.
183
+ * token = 1*<any CHAR except CTLs or separators>
184
+ * separators = "(" | ")" | "<" | ">" | "@"
185
+ * | "," | ";" | ":" | "\" | <">
186
+ * | "/" | "[" | "]" | "?" | "="
187
+ * | "{" | "}" | SP | HT
188
+ */
189
+ static const char tokens[256] = {
190
+ /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
191
+ 0, 0, 0, 0, 0, 0, 0, 0,
192
+ /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
193
+ 0, 0, 0, 0, 0, 0, 0, 0,
194
+ /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
195
+ 0, 0, 0, 0, 0, 0, 0, 0,
196
+ /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
197
+ 0, 0, 0, 0, 0, 0, 0, 0,
198
+ /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
199
+ 0, '!', 0, '#', '$', '%', '&', '\'',
200
+ /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
201
+ 0, 0, '*', '+', 0, '-', '.', 0,
202
+ /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
203
+ '0', '1', '2', '3', '4', '5', '6', '7',
204
+ /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
205
+ '8', '9', 0, 0, 0, 0, 0, 0,
206
+ /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
207
+ 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
208
+ /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
209
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
210
+ /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
211
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
212
+ /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
213
+ 'x', 'y', 'z', 0, 0, 0, '^', '_',
214
+ /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
215
+ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
216
+ /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
217
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
218
+ /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
219
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
220
+ /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
221
+ 'x', 'y', 'z', 0, '|', 0, '~', 0 };
222
+
223
+
224
+ static const int8_t unhex[256] =
225
+ {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
226
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
227
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
228
+ , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
229
+ ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
230
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
231
+ ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
232
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
233
+ };
234
+
235
+
236
+ #if HTTP_PARSER_STRICT
237
+ # define T(v) 0
238
+ #else
239
+ # define T(v) v
240
+ #endif
241
+
242
+
243
+ static const uint8_t normal_url_char[32] = {
244
+ /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
245
+ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
246
+ /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
247
+ 0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0,
248
+ /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
249
+ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
250
+ /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
251
+ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
252
+ /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
253
+ 0 | 2 | 4 | 0 | 16 | 32 | 64 | 128,
254
+ /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
255
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
256
+ /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
257
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
258
+ /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
259
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0,
260
+ /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
261
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
262
+ /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
263
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
264
+ /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
265
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
266
+ /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
267
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
268
+ /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
269
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
270
+ /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
271
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
272
+ /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
273
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
274
+ /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
275
+ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, };
276
+
277
+ #undef T
278
+
279
+ enum state
280
+ { s_dead = 1 /* important that this is > 0 */
281
+
282
+ , s_start_req_or_res
283
+ , s_res_or_resp_H
284
+ , s_start_res
285
+ , s_res_H
286
+ , s_res_HT
287
+ , s_res_HTT
288
+ , s_res_HTTP
289
+ , s_res_http_major
290
+ , s_res_http_dot
291
+ , s_res_http_minor
292
+ , s_res_http_end
293
+ , s_res_first_status_code
294
+ , s_res_status_code
295
+ , s_res_status_start
296
+ , s_res_status
297
+ , s_res_line_almost_done
298
+
299
+ , s_start_req
300
+
301
+ , s_req_method
302
+ , s_req_spaces_before_url
303
+ , s_req_schema
304
+ , s_req_schema_slash
305
+ , s_req_schema_slash_slash
306
+ , s_req_server_start
307
+ , s_req_server
308
+ , s_req_server_with_at
309
+ , s_req_path
310
+ , s_req_query_string_start
311
+ , s_req_query_string
312
+ , s_req_fragment_start
313
+ , s_req_fragment
314
+ , s_req_http_start
315
+ , s_req_http_H
316
+ , s_req_http_HT
317
+ , s_req_http_HTT
318
+ , s_req_http_HTTP
319
+ , s_req_http_major
320
+ , s_req_http_dot
321
+ , s_req_http_minor
322
+ , s_req_http_end
323
+ , s_req_line_almost_done
324
+
325
+ , s_header_field_start
326
+ , s_header_field
327
+ , s_header_value_discard_ws
328
+ , s_header_value_discard_ws_almost_done
329
+ , s_header_value_discard_lws
330
+ , s_header_value_start
331
+ , s_header_value
332
+ , s_header_value_lws
333
+
334
+ , s_header_almost_done
335
+
336
+ , s_chunk_size_start
337
+ , s_chunk_size
338
+ , s_chunk_parameters
339
+ , s_chunk_size_almost_done
340
+
341
+ , s_headers_almost_done
342
+ , s_headers_done
343
+
344
+ /* Important: 's_headers_done' must be the last 'header' state. All
345
+ * states beyond this must be 'body' states. It is used for overflow
346
+ * checking. See the PARSING_HEADER() macro.
347
+ */
348
+
349
+ , s_chunk_data
350
+ , s_chunk_data_almost_done
351
+ , s_chunk_data_done
352
+
353
+ , s_body_identity
354
+ , s_body_identity_eof
355
+
356
+ , s_message_done
357
+ };
358
+
359
+
360
+ #define PARSING_HEADER(state) (state <= s_headers_done)
361
+
362
+
363
+ enum header_states
364
+ { h_general = 0
365
+ , h_C
366
+ , h_CO
367
+ , h_CON
368
+
369
+ , h_matching_connection
370
+ , h_matching_proxy_connection
371
+ , h_matching_content_length
372
+ , h_matching_transfer_encoding
373
+ , h_matching_upgrade
374
+
375
+ , h_connection
376
+ , h_content_length
377
+ , h_transfer_encoding
378
+ , h_upgrade
379
+
380
+ , h_matching_transfer_encoding_chunked
381
+ , h_matching_connection_token_start
382
+ , h_matching_connection_keep_alive
383
+ , h_matching_connection_close
384
+ , h_matching_connection_upgrade
385
+ , h_matching_connection_token
386
+
387
+ , h_transfer_encoding_chunked
388
+ , h_connection_keep_alive
389
+ , h_connection_close
390
+ , h_connection_upgrade
391
+ };
392
+
393
+ enum http_host_state
394
+ {
395
+ s_http_host_dead = 1
396
+ , s_http_userinfo_start
397
+ , s_http_userinfo
398
+ , s_http_host_start
399
+ , s_http_host_v6_start
400
+ , s_http_host
401
+ , s_http_host_v6
402
+ , s_http_host_v6_end
403
+ , s_http_host_v6_zone_start
404
+ , s_http_host_v6_zone
405
+ , s_http_host_port_start
406
+ , s_http_host_port
407
+ };
408
+
409
+ /* Macros for character classes; depends on strict-mode */
410
+ #define CR '\r'
411
+ #define LF '\n'
412
+ #define LOWER(c) (unsigned char)(c | 0x20)
413
+ #define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z')
414
+ #define IS_NUM(c) ((c) >= '0' && (c) <= '9')
415
+ #define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c))
416
+ #define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f'))
417
+ #define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \
418
+ (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \
419
+ (c) == ')')
420
+ #define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \
421
+ (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \
422
+ (c) == '$' || (c) == ',')
423
+
424
+ #define STRICT_TOKEN(c) (tokens[(unsigned char)c])
425
+
426
+ #if HTTP_PARSER_STRICT
427
+ #define TOKEN(c) (tokens[(unsigned char)c])
428
+ #define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c))
429
+ #define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
430
+ #else
431
+ #define TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c])
432
+ #define IS_URL_CHAR(c) \
433
+ (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80))
434
+ #define IS_HOST_CHAR(c) \
435
+ (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_')
436
+ #endif
437
+
438
+ /**
439
+ * Verify that a char is a valid visible (printable) US-ASCII
440
+ * character or %x80-FF
441
+ **/
442
+ #define IS_HEADER_CHAR(ch) \
443
+ (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127))
444
+
445
+ #define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)
446
+
447
+
448
+ #if HTTP_PARSER_STRICT
449
+ # define STRICT_CHECK(cond) \
450
+ do { \
451
+ if (cond) { \
452
+ SET_ERRNO(HPE_STRICT); \
453
+ goto error; \
454
+ } \
455
+ } while (0)
456
+ # define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)
457
+ #else
458
+ # define STRICT_CHECK(cond)
459
+ # define NEW_MESSAGE() start_state
460
+ #endif
461
+
462
+
463
+ /* Map errno values to strings for human-readable output */
464
+ #define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s },
465
+ static struct {
466
+ const char *name;
467
+ const char *description;
468
+ } http_strerror_tab[] = {
469
+ HTTP_ERRNO_MAP(HTTP_STRERROR_GEN)
470
+ };
471
+ #undef HTTP_STRERROR_GEN
472
+
473
+ int http_message_needs_eof(const http_parser *parser);
474
+
475
+ /* Our URL parser.
476
+ *
477
+ * This is designed to be shared by http_parser_execute() for URL validation,
478
+ * hence it has a state transition + byte-for-byte interface. In addition, it
479
+ * is meant to be embedded in http_parser_parse_url(), which does the dirty
480
+ * work of turning state transitions URL components for its API.
481
+ *
482
+ * This function should only be invoked with non-space characters. It is
483
+ * assumed that the caller cares about (and can detect) the transition between
484
+ * URL and non-URL states by looking for these.
485
+ */
486
+ static enum state
487
+ parse_url_char(enum state s, const char ch)
488
+ {
489
+ if (ch == ' ' || ch == '\r' || ch == '\n') {
490
+ return s_dead;
491
+ }
492
+
493
+ #if HTTP_PARSER_STRICT
494
+ if (ch == '\t' || ch == '\f') {
495
+ return s_dead;
496
+ }
497
+ #endif
498
+
499
+ switch (s) {
500
+ case s_req_spaces_before_url:
501
+ /* Proxied requests are followed by scheme of an absolute URI (alpha).
502
+ * All methods except CONNECT are followed by '/' or '*'.
503
+ */
504
+
505
+ if (ch == '/' || ch == '*') {
506
+ return s_req_path;
507
+ }
508
+
509
+ if (IS_ALPHA(ch)) {
510
+ return s_req_schema;
511
+ }
512
+
513
+ break;
514
+
515
+ case s_req_schema:
516
+ if (IS_ALPHA(ch)) {
517
+ return s;
518
+ }
519
+
520
+ if (ch == ':') {
521
+ return s_req_schema_slash;
522
+ }
523
+
524
+ break;
525
+
526
+ case s_req_schema_slash:
527
+ if (ch == '/') {
528
+ return s_req_schema_slash_slash;
529
+ }
530
+
531
+ break;
532
+
533
+ case s_req_schema_slash_slash:
534
+ if (ch == '/') {
535
+ return s_req_server_start;
536
+ }
537
+
538
+ break;
539
+
540
+ case s_req_server_with_at:
541
+ if (ch == '@') {
542
+ return s_dead;
543
+ }
544
+
545
+ /* FALLTHROUGH */
546
+ case s_req_server_start:
547
+ case s_req_server:
548
+ if (ch == '/') {
549
+ return s_req_path;
550
+ }
551
+
552
+ if (ch == '?') {
553
+ return s_req_query_string_start;
554
+ }
555
+
556
+ if (ch == '@') {
557
+ return s_req_server_with_at;
558
+ }
559
+
560
+ if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') {
561
+ return s_req_server;
562
+ }
563
+
564
+ break;
565
+
566
+ case s_req_path:
567
+ if (IS_URL_CHAR(ch)) {
568
+ return s;
569
+ }
570
+
571
+ switch (ch) {
572
+ case '?':
573
+ return s_req_query_string_start;
574
+
575
+ case '#':
576
+ return s_req_fragment_start;
577
+ }
578
+
579
+ break;
580
+
581
+ case s_req_query_string_start:
582
+ case s_req_query_string:
583
+ if (IS_URL_CHAR(ch)) {
584
+ return s_req_query_string;
585
+ }
586
+
587
+ switch (ch) {
588
+ case '?':
589
+ /* allow extra '?' in query string */
590
+ return s_req_query_string;
591
+
592
+ case '#':
593
+ return s_req_fragment_start;
594
+ }
595
+
596
+ break;
597
+
598
+ case s_req_fragment_start:
599
+ if (IS_URL_CHAR(ch)) {
600
+ return s_req_fragment;
601
+ }
602
+
603
+ switch (ch) {
604
+ case '?':
605
+ return s_req_fragment;
606
+
607
+ case '#':
608
+ return s;
609
+ }
610
+
611
+ break;
612
+
613
+ case s_req_fragment:
614
+ if (IS_URL_CHAR(ch)) {
615
+ return s;
616
+ }
617
+
618
+ switch (ch) {
619
+ case '?':
620
+ case '#':
621
+ return s;
622
+ }
623
+
624
+ break;
625
+
626
+ default:
627
+ break;
628
+ }
629
+
630
+ /* We should never fall out of the switch above unless there's an error */
631
+ return s_dead;
632
+ }
633
+
634
+ size_t http_parser_execute (http_parser *parser,
635
+ const http_parser_settings *settings,
636
+ const char *data,
637
+ size_t len)
638
+ {
639
+ char c, ch;
640
+ int8_t unhex_val;
641
+ const char *p = data;
642
+ const char *header_field_mark = 0;
643
+ const char *header_value_mark = 0;
644
+ const char *url_mark = 0;
645
+ const char *body_mark = 0;
646
+ const char *status_mark = 0;
647
+ enum state p_state = (enum state) parser->state;
648
+ const unsigned int lenient = parser->lenient_http_headers;
649
+
650
+ /* We're in an error state. Don't bother doing anything. */
651
+ if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
652
+ return 0;
653
+ }
654
+
655
+ if (len == 0) {
656
+ switch (CURRENT_STATE()) {
657
+ case s_body_identity_eof:
658
+ /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if
659
+ * we got paused.
660
+ */
661
+ CALLBACK_NOTIFY_NOADVANCE(message_complete);
662
+ return 0;
663
+
664
+ case s_dead:
665
+ case s_start_req_or_res:
666
+ case s_start_res:
667
+ case s_start_req:
668
+ return 0;
669
+
670
+ default:
671
+ SET_ERRNO(HPE_INVALID_EOF_STATE);
672
+ return 1;
673
+ }
674
+ }
675
+
676
+
677
+ if (CURRENT_STATE() == s_header_field)
678
+ header_field_mark = data;
679
+ if (CURRENT_STATE() == s_header_value)
680
+ header_value_mark = data;
681
+ switch (CURRENT_STATE()) {
682
+ case s_req_path:
683
+ case s_req_schema:
684
+ case s_req_schema_slash:
685
+ case s_req_schema_slash_slash:
686
+ case s_req_server_start:
687
+ case s_req_server:
688
+ case s_req_server_with_at:
689
+ case s_req_query_string_start:
690
+ case s_req_query_string:
691
+ case s_req_fragment_start:
692
+ case s_req_fragment:
693
+ url_mark = data;
694
+ break;
695
+ case s_res_status:
696
+ status_mark = data;
697
+ break;
698
+ default:
699
+ break;
700
+ }
701
+
702
+ for (p=data; p != data + len; p++) {
703
+ ch = *p;
704
+
705
+ if (PARSING_HEADER(CURRENT_STATE()))
706
+ COUNT_HEADER_SIZE(1);
707
+
708
+ reexecute:
709
+ switch (CURRENT_STATE()) {
710
+
711
+ case s_dead:
712
+ /* this state is used after a 'Connection: close' message
713
+ * the parser will error out if it reads another message
714
+ */
715
+ if (LIKELY(ch == CR || ch == LF))
716
+ break;
717
+
718
+ SET_ERRNO(HPE_CLOSED_CONNECTION);
719
+ goto error;
720
+
721
+ case s_start_req_or_res:
722
+ {
723
+ if (ch == CR || ch == LF)
724
+ break;
725
+ parser->flags = 0;
726
+ parser->content_length = ULLONG_MAX;
727
+
728
+ if (ch == 'H') {
729
+ UPDATE_STATE(s_res_or_resp_H);
730
+
731
+ CALLBACK_NOTIFY(message_begin);
732
+ } else {
733
+ parser->type = HTTP_REQUEST;
734
+ UPDATE_STATE(s_start_req);
735
+ REEXECUTE();
736
+ }
737
+
738
+ break;
739
+ }
740
+
741
+ case s_res_or_resp_H:
742
+ if (ch == 'T') {
743
+ parser->type = HTTP_RESPONSE;
744
+ UPDATE_STATE(s_res_HT);
745
+ } else {
746
+ if (UNLIKELY(ch != 'E')) {
747
+ SET_ERRNO(HPE_INVALID_CONSTANT);
748
+ goto error;
749
+ }
750
+
751
+ parser->type = HTTP_REQUEST;
752
+ parser->method = HTTP_HEAD;
753
+ parser->index = 2;
754
+ UPDATE_STATE(s_req_method);
755
+ }
756
+ break;
757
+
758
+ case s_start_res:
759
+ {
760
+ parser->flags = 0;
761
+ parser->content_length = ULLONG_MAX;
762
+
763
+ switch (ch) {
764
+ case 'H':
765
+ UPDATE_STATE(s_res_H);
766
+ break;
767
+
768
+ case CR:
769
+ case LF:
770
+ break;
771
+
772
+ default:
773
+ SET_ERRNO(HPE_INVALID_CONSTANT);
774
+ goto error;
775
+ }
776
+
777
+ CALLBACK_NOTIFY(message_begin);
778
+ break;
779
+ }
780
+
781
+ case s_res_H:
782
+ STRICT_CHECK(ch != 'T');
783
+ UPDATE_STATE(s_res_HT);
784
+ break;
785
+
786
+ case s_res_HT:
787
+ STRICT_CHECK(ch != 'T');
788
+ UPDATE_STATE(s_res_HTT);
789
+ break;
790
+
791
+ case s_res_HTT:
792
+ STRICT_CHECK(ch != 'P');
793
+ UPDATE_STATE(s_res_HTTP);
794
+ break;
795
+
796
+ case s_res_HTTP:
797
+ STRICT_CHECK(ch != '/');
798
+ UPDATE_STATE(s_res_http_major);
799
+ break;
800
+
801
+ case s_res_http_major:
802
+ if (UNLIKELY(!IS_NUM(ch))) {
803
+ SET_ERRNO(HPE_INVALID_VERSION);
804
+ goto error;
805
+ }
806
+
807
+ parser->http_major = ch - '0';
808
+ UPDATE_STATE(s_res_http_dot);
809
+ break;
810
+
811
+ case s_res_http_dot:
812
+ {
813
+ if (UNLIKELY(ch != '.')) {
814
+ SET_ERRNO(HPE_INVALID_VERSION);
815
+ goto error;
816
+ }
817
+
818
+ UPDATE_STATE(s_res_http_minor);
819
+ break;
820
+ }
821
+
822
+ case s_res_http_minor:
823
+ if (UNLIKELY(!IS_NUM(ch))) {
824
+ SET_ERRNO(HPE_INVALID_VERSION);
825
+ goto error;
826
+ }
827
+
828
+ parser->http_minor = ch - '0';
829
+ UPDATE_STATE(s_res_http_end);
830
+ break;
831
+
832
+ case s_res_http_end:
833
+ {
834
+ if (UNLIKELY(ch != ' ')) {
835
+ SET_ERRNO(HPE_INVALID_VERSION);
836
+ goto error;
837
+ }
838
+
839
+ UPDATE_STATE(s_res_first_status_code);
840
+ break;
841
+ }
842
+
843
+ case s_res_first_status_code:
844
+ {
845
+ if (!IS_NUM(ch)) {
846
+ if (ch == ' ') {
847
+ break;
848
+ }
849
+
850
+ SET_ERRNO(HPE_INVALID_STATUS);
851
+ goto error;
852
+ }
853
+ parser->status_code = ch - '0';
854
+ UPDATE_STATE(s_res_status_code);
855
+ break;
856
+ }
857
+
858
+ case s_res_status_code:
859
+ {
860
+ if (!IS_NUM(ch)) {
861
+ switch (ch) {
862
+ case ' ':
863
+ UPDATE_STATE(s_res_status_start);
864
+ break;
865
+ case CR:
866
+ case LF:
867
+ UPDATE_STATE(s_res_status_start);
868
+ REEXECUTE();
869
+ break;
870
+ default:
871
+ SET_ERRNO(HPE_INVALID_STATUS);
872
+ goto error;
873
+ }
874
+ break;
875
+ }
876
+
877
+ parser->status_code *= 10;
878
+ parser->status_code += ch - '0';
879
+
880
+ if (UNLIKELY(parser->status_code > 999)) {
881
+ SET_ERRNO(HPE_INVALID_STATUS);
882
+ goto error;
883
+ }
884
+
885
+ break;
886
+ }
887
+
888
+ case s_res_status_start:
889
+ {
890
+ MARK(status);
891
+ UPDATE_STATE(s_res_status);
892
+ parser->index = 0;
893
+
894
+ if (ch == CR || ch == LF)
895
+ REEXECUTE();
896
+
897
+ break;
898
+ }
899
+
900
+ case s_res_status:
901
+ if (ch == CR) {
902
+ UPDATE_STATE(s_res_line_almost_done);
903
+ CALLBACK_DATA(status);
904
+ break;
905
+ }
906
+
907
+ if (ch == LF) {
908
+ UPDATE_STATE(s_header_field_start);
909
+ CALLBACK_DATA(status);
910
+ break;
911
+ }
912
+
913
+ break;
914
+
915
+ case s_res_line_almost_done:
916
+ STRICT_CHECK(ch != LF);
917
+ UPDATE_STATE(s_header_field_start);
918
+ break;
919
+
920
+ case s_start_req:
921
+ {
922
+ if (ch == CR || ch == LF)
923
+ break;
924
+ parser->flags = 0;
925
+ parser->content_length = ULLONG_MAX;
926
+
927
+ if (UNLIKELY(!IS_ALPHA(ch))) {
928
+ SET_ERRNO(HPE_INVALID_METHOD);
929
+ goto error;
930
+ }
931
+
932
+ parser->method = (enum http_method) 0;
933
+ parser->index = 1;
934
+ switch (ch) {
935
+ case 'A': parser->method = HTTP_ACL; break;
936
+ case 'B': parser->method = HTTP_BIND; break;
937
+ case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break;
938
+ case 'D': parser->method = HTTP_DELETE; break;
939
+ case 'G': parser->method = HTTP_GET; break;
940
+ case 'H': parser->method = HTTP_HEAD; break;
941
+ case 'L': parser->method = HTTP_LOCK; /* or LINK */ break;
942
+ case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break;
943
+ case 'N': parser->method = HTTP_NOTIFY; break;
944
+ case 'O': parser->method = HTTP_OPTIONS; break;
945
+ case 'P': parser->method = HTTP_POST;
946
+ /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */
947
+ break;
948
+ case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break;
949
+ case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break;
950
+ case 'T': parser->method = HTTP_TRACE; break;
951
+ case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break;
952
+ default:
953
+ SET_ERRNO(HPE_INVALID_METHOD);
954
+ goto error;
955
+ }
956
+ UPDATE_STATE(s_req_method);
957
+
958
+ CALLBACK_NOTIFY(message_begin);
959
+
960
+ break;
961
+ }
962
+
963
+ case s_req_method:
964
+ {
965
+ const char *matcher;
966
+ if (UNLIKELY(ch == '\0')) {
967
+ SET_ERRNO(HPE_INVALID_METHOD);
968
+ goto error;
969
+ }
970
+
971
+ matcher = method_strings[parser->method];
972
+ if (ch == ' ' && matcher[parser->index] == '\0') {
973
+ UPDATE_STATE(s_req_spaces_before_url);
974
+ } else if (ch == matcher[parser->index]) {
975
+ ; /* nada */
976
+ } else if ((ch >= 'A' && ch <= 'Z') || ch == '-') {
977
+
978
+ switch (parser->method << 16 | parser->index << 8 | ch) {
979
+ #define XX(meth, pos, ch, new_meth) \
980
+ case (HTTP_##meth << 16 | pos << 8 | ch): \
981
+ parser->method = HTTP_##new_meth; break;
982
+
983
+ XX(POST, 1, 'U', PUT)
984
+ XX(POST, 1, 'A', PATCH)
985
+ XX(POST, 1, 'R', PROPFIND)
986
+ XX(PUT, 2, 'R', PURGE)
987
+ XX(CONNECT, 1, 'H', CHECKOUT)
988
+ XX(CONNECT, 2, 'P', COPY)
989
+ XX(MKCOL, 1, 'O', MOVE)
990
+ XX(MKCOL, 1, 'E', MERGE)
991
+ XX(MKCOL, 1, '-', MSEARCH)
992
+ XX(MKCOL, 2, 'A', MKACTIVITY)
993
+ XX(MKCOL, 3, 'A', MKCALENDAR)
994
+ XX(SUBSCRIBE, 1, 'E', SEARCH)
995
+ XX(REPORT, 2, 'B', REBIND)
996
+ XX(PROPFIND, 4, 'P', PROPPATCH)
997
+ XX(LOCK, 1, 'I', LINK)
998
+ XX(UNLOCK, 2, 'S', UNSUBSCRIBE)
999
+ XX(UNLOCK, 2, 'B', UNBIND)
1000
+ XX(UNLOCK, 3, 'I', UNLINK)
1001
+ #undef XX
1002
+ default:
1003
+ SET_ERRNO(HPE_INVALID_METHOD);
1004
+ goto error;
1005
+ }
1006
+ } else {
1007
+ SET_ERRNO(HPE_INVALID_METHOD);
1008
+ goto error;
1009
+ }
1010
+
1011
+ ++parser->index;
1012
+ break;
1013
+ }
1014
+
1015
+ case s_req_spaces_before_url:
1016
+ {
1017
+ if (ch == ' ') break;
1018
+
1019
+ MARK(url);
1020
+ if (parser->method == HTTP_CONNECT) {
1021
+ UPDATE_STATE(s_req_server_start);
1022
+ }
1023
+
1024
+ UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
1025
+ if (UNLIKELY(CURRENT_STATE() == s_dead)) {
1026
+ SET_ERRNO(HPE_INVALID_URL);
1027
+ goto error;
1028
+ }
1029
+
1030
+ break;
1031
+ }
1032
+
1033
+ case s_req_schema:
1034
+ case s_req_schema_slash:
1035
+ case s_req_schema_slash_slash:
1036
+ case s_req_server_start:
1037
+ {
1038
+ switch (ch) {
1039
+ /* No whitespace allowed here */
1040
+ case ' ':
1041
+ case CR:
1042
+ case LF:
1043
+ SET_ERRNO(HPE_INVALID_URL);
1044
+ goto error;
1045
+ default:
1046
+ UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
1047
+ if (UNLIKELY(CURRENT_STATE() == s_dead)) {
1048
+ SET_ERRNO(HPE_INVALID_URL);
1049
+ goto error;
1050
+ }
1051
+ }
1052
+
1053
+ break;
1054
+ }
1055
+
1056
+ case s_req_server:
1057
+ case s_req_server_with_at:
1058
+ case s_req_path:
1059
+ case s_req_query_string_start:
1060
+ case s_req_query_string:
1061
+ case s_req_fragment_start:
1062
+ case s_req_fragment:
1063
+ {
1064
+ switch (ch) {
1065
+ case ' ':
1066
+ UPDATE_STATE(s_req_http_start);
1067
+ CALLBACK_DATA(url);
1068
+ break;
1069
+ case CR:
1070
+ case LF:
1071
+ parser->http_major = 0;
1072
+ parser->http_minor = 9;
1073
+ CALLBACK_DATA(url);
1074
+ if (ch == CR) {
1075
+ UPDATE_STATE(s_req_line_almost_done);
1076
+ } else {
1077
+ UPDATE_STATE(s_headers_almost_done);
1078
+ REEXECUTE();
1079
+ }
1080
+ break;
1081
+ default:
1082
+ UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
1083
+ if (UNLIKELY(CURRENT_STATE() == s_dead)) {
1084
+ SET_ERRNO(HPE_INVALID_URL);
1085
+ goto error;
1086
+ }
1087
+ }
1088
+ break;
1089
+ }
1090
+
1091
+ case s_req_http_start:
1092
+ switch (ch) {
1093
+ case 'H':
1094
+ UPDATE_STATE(s_req_http_H);
1095
+ break;
1096
+ case ' ':
1097
+ break;
1098
+ default:
1099
+ SET_ERRNO(HPE_INVALID_CONSTANT);
1100
+ goto error;
1101
+ }
1102
+ break;
1103
+
1104
+ case s_req_http_H:
1105
+ STRICT_CHECK(ch != 'T');
1106
+ UPDATE_STATE(s_req_http_HT);
1107
+ break;
1108
+
1109
+ case s_req_http_HT:
1110
+ STRICT_CHECK(ch != 'T');
1111
+ UPDATE_STATE(s_req_http_HTT);
1112
+ break;
1113
+
1114
+ case s_req_http_HTT:
1115
+ STRICT_CHECK(ch != 'P');
1116
+ UPDATE_STATE(s_req_http_HTTP);
1117
+ break;
1118
+
1119
+ case s_req_http_HTTP:
1120
+ STRICT_CHECK(ch != '/');
1121
+ UPDATE_STATE(s_req_http_major);
1122
+ break;
1123
+
1124
+ case s_req_http_major:
1125
+ if (UNLIKELY(!IS_NUM(ch))) {
1126
+ SET_ERRNO(HPE_INVALID_VERSION);
1127
+ goto error;
1128
+ }
1129
+
1130
+ parser->http_major = ch - '0';
1131
+ UPDATE_STATE(s_req_http_dot);
1132
+ break;
1133
+
1134
+ case s_req_http_dot:
1135
+ {
1136
+ if (UNLIKELY(ch != '.')) {
1137
+ SET_ERRNO(HPE_INVALID_VERSION);
1138
+ goto error;
1139
+ }
1140
+
1141
+ UPDATE_STATE(s_req_http_minor);
1142
+ break;
1143
+ }
1144
+
1145
+ case s_req_http_minor:
1146
+ if (UNLIKELY(!IS_NUM(ch))) {
1147
+ SET_ERRNO(HPE_INVALID_VERSION);
1148
+ goto error;
1149
+ }
1150
+
1151
+ parser->http_minor = ch - '0';
1152
+ UPDATE_STATE(s_req_http_end);
1153
+ break;
1154
+
1155
+ case s_req_http_end:
1156
+ {
1157
+ if (ch == CR) {
1158
+ UPDATE_STATE(s_req_line_almost_done);
1159
+ break;
1160
+ }
1161
+
1162
+ if (ch == LF) {
1163
+ UPDATE_STATE(s_header_field_start);
1164
+ break;
1165
+ }
1166
+
1167
+ SET_ERRNO(HPE_INVALID_VERSION);
1168
+ goto error;
1169
+ break;
1170
+ }
1171
+
1172
+ /* end of request line */
1173
+ case s_req_line_almost_done:
1174
+ {
1175
+ if (UNLIKELY(ch != LF)) {
1176
+ SET_ERRNO(HPE_LF_EXPECTED);
1177
+ goto error;
1178
+ }
1179
+
1180
+ if (parser->http_major == 0) {
1181
+ UPDATE_STATE(s_headers_almost_done);
1182
+ REEXECUTE();
1183
+ } else {
1184
+ UPDATE_STATE(s_header_field_start);
1185
+ }
1186
+ break;
1187
+ }
1188
+
1189
+ case s_header_field_start:
1190
+ {
1191
+ if (ch == CR) {
1192
+ UPDATE_STATE(s_headers_almost_done);
1193
+ break;
1194
+ }
1195
+
1196
+ if (ch == LF) {
1197
+ /* they might be just sending \n instead of \r\n so this would be
1198
+ * the second \n to denote the end of headers*/
1199
+ UPDATE_STATE(s_headers_almost_done);
1200
+ REEXECUTE();
1201
+ }
1202
+
1203
+ c = TOKEN(ch);
1204
+
1205
+ if (UNLIKELY(!c)) {
1206
+ SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
1207
+ goto error;
1208
+ }
1209
+
1210
+ MARK(header_field);
1211
+
1212
+ parser->index = 0;
1213
+ UPDATE_STATE(s_header_field);
1214
+
1215
+ switch (c) {
1216
+ case 'c':
1217
+ parser->header_state = h_C;
1218
+ break;
1219
+
1220
+ case 'p':
1221
+ parser->header_state = h_matching_proxy_connection;
1222
+ break;
1223
+
1224
+ case 't':
1225
+ parser->header_state = h_matching_transfer_encoding;
1226
+ break;
1227
+
1228
+ case 'u':
1229
+ parser->header_state = h_matching_upgrade;
1230
+ break;
1231
+
1232
+ default:
1233
+ parser->header_state = h_general;
1234
+ break;
1235
+ }
1236
+ break;
1237
+ }
1238
+
1239
+ case s_header_field:
1240
+ {
1241
+ const char* start = p;
1242
+ for (; p != data + len; p++) {
1243
+ ch = *p;
1244
+ c = TOKEN(ch);
1245
+
1246
+ if (!c)
1247
+ break;
1248
+
1249
+ switch (parser->header_state) {
1250
+ case h_general:
1251
+ break;
1252
+
1253
+ case h_C:
1254
+ parser->index++;
1255
+ parser->header_state = (c == 'o' ? h_CO : h_general);
1256
+ break;
1257
+
1258
+ case h_CO:
1259
+ parser->index++;
1260
+ parser->header_state = (c == 'n' ? h_CON : h_general);
1261
+ break;
1262
+
1263
+ case h_CON:
1264
+ parser->index++;
1265
+ switch (c) {
1266
+ case 'n':
1267
+ parser->header_state = h_matching_connection;
1268
+ break;
1269
+ case 't':
1270
+ parser->header_state = h_matching_content_length;
1271
+ break;
1272
+ default:
1273
+ parser->header_state = h_general;
1274
+ break;
1275
+ }
1276
+ break;
1277
+
1278
+ /* connection */
1279
+
1280
+ case h_matching_connection:
1281
+ parser->index++;
1282
+ if (parser->index > sizeof(CONNECTION)-1
1283
+ || c != CONNECTION[parser->index]) {
1284
+ parser->header_state = h_general;
1285
+ } else if (parser->index == sizeof(CONNECTION)-2) {
1286
+ parser->header_state = h_connection;
1287
+ }
1288
+ break;
1289
+
1290
+ /* proxy-connection */
1291
+
1292
+ case h_matching_proxy_connection:
1293
+ parser->index++;
1294
+ if (parser->index > sizeof(PROXY_CONNECTION)-1
1295
+ || c != PROXY_CONNECTION[parser->index]) {
1296
+ parser->header_state = h_general;
1297
+ } else if (parser->index == sizeof(PROXY_CONNECTION)-2) {
1298
+ parser->header_state = h_connection;
1299
+ }
1300
+ break;
1301
+
1302
+ /* content-length */
1303
+
1304
+ case h_matching_content_length:
1305
+ parser->index++;
1306
+ if (parser->index > sizeof(CONTENT_LENGTH)-1
1307
+ || c != CONTENT_LENGTH[parser->index]) {
1308
+ parser->header_state = h_general;
1309
+ } else if (parser->index == sizeof(CONTENT_LENGTH)-2) {
1310
+ parser->header_state = h_content_length;
1311
+ }
1312
+ break;
1313
+
1314
+ /* transfer-encoding */
1315
+
1316
+ case h_matching_transfer_encoding:
1317
+ parser->index++;
1318
+ if (parser->index > sizeof(TRANSFER_ENCODING)-1
1319
+ || c != TRANSFER_ENCODING[parser->index]) {
1320
+ parser->header_state = h_general;
1321
+ } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) {
1322
+ parser->header_state = h_transfer_encoding;
1323
+ }
1324
+ break;
1325
+
1326
+ /* upgrade */
1327
+
1328
+ case h_matching_upgrade:
1329
+ parser->index++;
1330
+ if (parser->index > sizeof(UPGRADE)-1
1331
+ || c != UPGRADE[parser->index]) {
1332
+ parser->header_state = h_general;
1333
+ } else if (parser->index == sizeof(UPGRADE)-2) {
1334
+ parser->header_state = h_upgrade;
1335
+ }
1336
+ break;
1337
+
1338
+ case h_connection:
1339
+ case h_content_length:
1340
+ case h_transfer_encoding:
1341
+ case h_upgrade:
1342
+ if (ch != ' ') parser->header_state = h_general;
1343
+ break;
1344
+
1345
+ default:
1346
+ assert(0 && "Unknown header_state");
1347
+ break;
1348
+ }
1349
+ }
1350
+
1351
+ COUNT_HEADER_SIZE(p - start);
1352
+
1353
+ if (p == data + len) {
1354
+ --p;
1355
+ break;
1356
+ }
1357
+
1358
+ if (ch == ':') {
1359
+ UPDATE_STATE(s_header_value_discard_ws);
1360
+ CALLBACK_DATA(header_field);
1361
+ break;
1362
+ }
1363
+
1364
+ SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
1365
+ goto error;
1366
+ }
1367
+
1368
+ case s_header_value_discard_ws:
1369
+ if (ch == ' ' || ch == '\t') break;
1370
+
1371
+ if (ch == CR) {
1372
+ UPDATE_STATE(s_header_value_discard_ws_almost_done);
1373
+ break;
1374
+ }
1375
+
1376
+ if (ch == LF) {
1377
+ UPDATE_STATE(s_header_value_discard_lws);
1378
+ break;
1379
+ }
1380
+
1381
+ /* FALLTHROUGH */
1382
+
1383
+ case s_header_value_start:
1384
+ {
1385
+ MARK(header_value);
1386
+
1387
+ UPDATE_STATE(s_header_value);
1388
+ parser->index = 0;
1389
+
1390
+ c = LOWER(ch);
1391
+
1392
+ switch (parser->header_state) {
1393
+ case h_upgrade:
1394
+ parser->flags |= F_UPGRADE;
1395
+ parser->header_state = h_general;
1396
+ break;
1397
+
1398
+ case h_transfer_encoding:
1399
+ /* looking for 'Transfer-Encoding: chunked' */
1400
+ if ('c' == c) {
1401
+ parser->header_state = h_matching_transfer_encoding_chunked;
1402
+ } else {
1403
+ parser->header_state = h_general;
1404
+ }
1405
+ break;
1406
+
1407
+ case h_content_length:
1408
+ if (UNLIKELY(!IS_NUM(ch))) {
1409
+ SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1410
+ goto error;
1411
+ }
1412
+
1413
+ if (parser->flags & F_CONTENTLENGTH) {
1414
+ SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
1415
+ goto error;
1416
+ }
1417
+
1418
+ parser->flags |= F_CONTENTLENGTH;
1419
+ parser->content_length = ch - '0';
1420
+ break;
1421
+
1422
+ case h_connection:
1423
+ /* looking for 'Connection: keep-alive' */
1424
+ if (c == 'k') {
1425
+ parser->header_state = h_matching_connection_keep_alive;
1426
+ /* looking for 'Connection: close' */
1427
+ } else if (c == 'c') {
1428
+ parser->header_state = h_matching_connection_close;
1429
+ } else if (c == 'u') {
1430
+ parser->header_state = h_matching_connection_upgrade;
1431
+ } else {
1432
+ parser->header_state = h_matching_connection_token;
1433
+ }
1434
+ break;
1435
+
1436
+ /* Multi-value `Connection` header */
1437
+ case h_matching_connection_token_start:
1438
+ break;
1439
+
1440
+ default:
1441
+ parser->header_state = h_general;
1442
+ break;
1443
+ }
1444
+ break;
1445
+ }
1446
+
1447
+ case s_header_value:
1448
+ {
1449
+ const char* start = p;
1450
+ enum header_states h_state = (enum header_states) parser->header_state;
1451
+ for (; p != data + len; p++) {
1452
+ ch = *p;
1453
+ if (ch == CR) {
1454
+ UPDATE_STATE(s_header_almost_done);
1455
+ parser->header_state = h_state;
1456
+ CALLBACK_DATA(header_value);
1457
+ break;
1458
+ }
1459
+
1460
+ if (ch == LF) {
1461
+ UPDATE_STATE(s_header_almost_done);
1462
+ COUNT_HEADER_SIZE(p - start);
1463
+ parser->header_state = h_state;
1464
+ CALLBACK_DATA_NOADVANCE(header_value);
1465
+ REEXECUTE();
1466
+ }
1467
+
1468
+ if (!lenient && !IS_HEADER_CHAR(ch)) {
1469
+ SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
1470
+ goto error;
1471
+ }
1472
+
1473
+ c = LOWER(ch);
1474
+
1475
+ switch (h_state) {
1476
+ case h_general:
1477
+ {
1478
+ const char* p_cr;
1479
+ const char* p_lf;
1480
+ size_t limit = data + len - p;
1481
+
1482
+ limit = MIN(limit, HTTP_MAX_HEADER_SIZE);
1483
+
1484
+ p_cr = (const char*) memchr(p, CR, limit);
1485
+ p_lf = (const char*) memchr(p, LF, limit);
1486
+ if (p_cr != NULL) {
1487
+ if (p_lf != NULL && p_cr >= p_lf)
1488
+ p = p_lf;
1489
+ else
1490
+ p = p_cr;
1491
+ } else if (UNLIKELY(p_lf != NULL)) {
1492
+ p = p_lf;
1493
+ } else {
1494
+ p = data + len;
1495
+ }
1496
+ --p;
1497
+
1498
+ break;
1499
+ }
1500
+
1501
+ case h_connection:
1502
+ case h_transfer_encoding:
1503
+ assert(0 && "Shouldn't get here.");
1504
+ break;
1505
+
1506
+ case h_content_length:
1507
+ {
1508
+ uint64_t t;
1509
+
1510
+ if (ch == ' ') break;
1511
+
1512
+ if (UNLIKELY(!IS_NUM(ch))) {
1513
+ SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1514
+ parser->header_state = h_state;
1515
+ goto error;
1516
+ }
1517
+
1518
+ t = parser->content_length;
1519
+ t *= 10;
1520
+ t += ch - '0';
1521
+
1522
+ /* Overflow? Test against a conservative limit for simplicity. */
1523
+ if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) {
1524
+ SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1525
+ parser->header_state = h_state;
1526
+ goto error;
1527
+ }
1528
+
1529
+ parser->content_length = t;
1530
+ break;
1531
+ }
1532
+
1533
+ /* Transfer-Encoding: chunked */
1534
+ case h_matching_transfer_encoding_chunked:
1535
+ parser->index++;
1536
+ if (parser->index > sizeof(CHUNKED)-1
1537
+ || c != CHUNKED[parser->index]) {
1538
+ h_state = h_general;
1539
+ } else if (parser->index == sizeof(CHUNKED)-2) {
1540
+ h_state = h_transfer_encoding_chunked;
1541
+ }
1542
+ break;
1543
+
1544
+ case h_matching_connection_token_start:
1545
+ /* looking for 'Connection: keep-alive' */
1546
+ if (c == 'k') {
1547
+ h_state = h_matching_connection_keep_alive;
1548
+ /* looking for 'Connection: close' */
1549
+ } else if (c == 'c') {
1550
+ h_state = h_matching_connection_close;
1551
+ } else if (c == 'u') {
1552
+ h_state = h_matching_connection_upgrade;
1553
+ } else if (STRICT_TOKEN(c)) {
1554
+ h_state = h_matching_connection_token;
1555
+ } else if (c == ' ' || c == '\t') {
1556
+ /* Skip lws */
1557
+ } else {
1558
+ h_state = h_general;
1559
+ }
1560
+ break;
1561
+
1562
+ /* looking for 'Connection: keep-alive' */
1563
+ case h_matching_connection_keep_alive:
1564
+ parser->index++;
1565
+ if (parser->index > sizeof(KEEP_ALIVE)-1
1566
+ || c != KEEP_ALIVE[parser->index]) {
1567
+ h_state = h_matching_connection_token;
1568
+ } else if (parser->index == sizeof(KEEP_ALIVE)-2) {
1569
+ h_state = h_connection_keep_alive;
1570
+ }
1571
+ break;
1572
+
1573
+ /* looking for 'Connection: close' */
1574
+ case h_matching_connection_close:
1575
+ parser->index++;
1576
+ if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) {
1577
+ h_state = h_matching_connection_token;
1578
+ } else if (parser->index == sizeof(CLOSE)-2) {
1579
+ h_state = h_connection_close;
1580
+ }
1581
+ break;
1582
+
1583
+ /* looking for 'Connection: upgrade' */
1584
+ case h_matching_connection_upgrade:
1585
+ parser->index++;
1586
+ if (parser->index > sizeof(UPGRADE) - 1 ||
1587
+ c != UPGRADE[parser->index]) {
1588
+ h_state = h_matching_connection_token;
1589
+ } else if (parser->index == sizeof(UPGRADE)-2) {
1590
+ h_state = h_connection_upgrade;
1591
+ }
1592
+ break;
1593
+
1594
+ case h_matching_connection_token:
1595
+ if (ch == ',') {
1596
+ h_state = h_matching_connection_token_start;
1597
+ parser->index = 0;
1598
+ }
1599
+ break;
1600
+
1601
+ case h_transfer_encoding_chunked:
1602
+ if (ch != ' ') h_state = h_general;
1603
+ break;
1604
+
1605
+ case h_connection_keep_alive:
1606
+ case h_connection_close:
1607
+ case h_connection_upgrade:
1608
+ if (ch == ',') {
1609
+ if (h_state == h_connection_keep_alive) {
1610
+ parser->flags |= F_CONNECTION_KEEP_ALIVE;
1611
+ } else if (h_state == h_connection_close) {
1612
+ parser->flags |= F_CONNECTION_CLOSE;
1613
+ } else if (h_state == h_connection_upgrade) {
1614
+ parser->flags |= F_CONNECTION_UPGRADE;
1615
+ }
1616
+ h_state = h_matching_connection_token_start;
1617
+ parser->index = 0;
1618
+ } else if (ch != ' ') {
1619
+ h_state = h_matching_connection_token;
1620
+ }
1621
+ break;
1622
+
1623
+ default:
1624
+ UPDATE_STATE(s_header_value);
1625
+ h_state = h_general;
1626
+ break;
1627
+ }
1628
+ }
1629
+ parser->header_state = h_state;
1630
+
1631
+ COUNT_HEADER_SIZE(p - start);
1632
+
1633
+ if (p == data + len)
1634
+ --p;
1635
+ break;
1636
+ }
1637
+
1638
+ case s_header_almost_done:
1639
+ {
1640
+ if (UNLIKELY(ch != LF)) {
1641
+ SET_ERRNO(HPE_LF_EXPECTED);
1642
+ goto error;
1643
+ }
1644
+
1645
+ UPDATE_STATE(s_header_value_lws);
1646
+ break;
1647
+ }
1648
+
1649
+ case s_header_value_lws:
1650
+ {
1651
+ if (ch == ' ' || ch == '\t') {
1652
+ UPDATE_STATE(s_header_value_start);
1653
+ REEXECUTE();
1654
+ }
1655
+
1656
+ /* finished the header */
1657
+ switch (parser->header_state) {
1658
+ case h_connection_keep_alive:
1659
+ parser->flags |= F_CONNECTION_KEEP_ALIVE;
1660
+ break;
1661
+ case h_connection_close:
1662
+ parser->flags |= F_CONNECTION_CLOSE;
1663
+ break;
1664
+ case h_transfer_encoding_chunked:
1665
+ parser->flags |= F_CHUNKED;
1666
+ break;
1667
+ case h_connection_upgrade:
1668
+ parser->flags |= F_CONNECTION_UPGRADE;
1669
+ break;
1670
+ default:
1671
+ break;
1672
+ }
1673
+
1674
+ UPDATE_STATE(s_header_field_start);
1675
+ REEXECUTE();
1676
+ }
1677
+
1678
+ case s_header_value_discard_ws_almost_done:
1679
+ {
1680
+ STRICT_CHECK(ch != LF);
1681
+ UPDATE_STATE(s_header_value_discard_lws);
1682
+ break;
1683
+ }
1684
+
1685
+ case s_header_value_discard_lws:
1686
+ {
1687
+ if (ch == ' ' || ch == '\t') {
1688
+ UPDATE_STATE(s_header_value_discard_ws);
1689
+ break;
1690
+ } else {
1691
+ switch (parser->header_state) {
1692
+ case h_connection_keep_alive:
1693
+ parser->flags |= F_CONNECTION_KEEP_ALIVE;
1694
+ break;
1695
+ case h_connection_close:
1696
+ parser->flags |= F_CONNECTION_CLOSE;
1697
+ break;
1698
+ case h_connection_upgrade:
1699
+ parser->flags |= F_CONNECTION_UPGRADE;
1700
+ break;
1701
+ case h_transfer_encoding_chunked:
1702
+ parser->flags |= F_CHUNKED;
1703
+ break;
1704
+ default:
1705
+ break;
1706
+ }
1707
+
1708
+ /* header value was empty */
1709
+ MARK(header_value);
1710
+ UPDATE_STATE(s_header_field_start);
1711
+ CALLBACK_DATA_NOADVANCE(header_value);
1712
+ REEXECUTE();
1713
+ }
1714
+ }
1715
+
1716
+ case s_headers_almost_done:
1717
+ {
1718
+ STRICT_CHECK(ch != LF);
1719
+
1720
+ if (parser->flags & F_TRAILING) {
1721
+ /* End of a chunked request */
1722
+ UPDATE_STATE(s_message_done);
1723
+ CALLBACK_NOTIFY_NOADVANCE(chunk_complete);
1724
+ REEXECUTE();
1725
+ }
1726
+
1727
+ /* Cannot use chunked encoding and a content-length header together
1728
+ per the HTTP specification. */
1729
+ if ((parser->flags & F_CHUNKED) &&
1730
+ (parser->flags & F_CONTENTLENGTH)) {
1731
+ SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
1732
+ goto error;
1733
+ }
1734
+
1735
+ UPDATE_STATE(s_headers_done);
1736
+
1737
+ /* Set this here so that on_headers_complete() callbacks can see it */
1738
+ if ((parser->flags & F_UPGRADE) &&
1739
+ (parser->flags & F_CONNECTION_UPGRADE)) {
1740
+ /* For responses, "Upgrade: foo" and "Connection: upgrade" are
1741
+ * mandatory only when it is a 101 Switching Protocols response,
1742
+ * otherwise it is purely informational, to announce support.
1743
+ */
1744
+ parser->upgrade =
1745
+ (parser->type == HTTP_REQUEST || parser->status_code == 101);
1746
+ } else {
1747
+ parser->upgrade = (parser->method == HTTP_CONNECT);
1748
+ }
1749
+
1750
+ /* Here we call the headers_complete callback. This is somewhat
1751
+ * different than other callbacks because if the user returns 1, we
1752
+ * will interpret that as saying that this message has no body. This
1753
+ * is needed for the annoying case of recieving a response to a HEAD
1754
+ * request.
1755
+ *
1756
+ * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so
1757
+ * we have to simulate it by handling a change in errno below.
1758
+ */
1759
+ if (settings->on_headers_complete) {
1760
+ switch (settings->on_headers_complete(parser)) {
1761
+ case 0:
1762
+ break;
1763
+
1764
+ case 2:
1765
+ parser->upgrade = 1;
1766
+
1767
+ /* FALLTHROUGH */
1768
+ case 1:
1769
+ parser->flags |= F_SKIPBODY;
1770
+ break;
1771
+
1772
+ default:
1773
+ SET_ERRNO(HPE_CB_headers_complete);
1774
+ RETURN(p - data); /* Error */
1775
+ }
1776
+ }
1777
+
1778
+ if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
1779
+ RETURN(p - data);
1780
+ }
1781
+
1782
+ REEXECUTE();
1783
+ }
1784
+
1785
+ case s_headers_done:
1786
+ {
1787
+ int hasBody;
1788
+ STRICT_CHECK(ch != LF);
1789
+
1790
+ parser->nread = 0;
1791
+
1792
+ hasBody = parser->flags & F_CHUNKED ||
1793
+ (parser->content_length > 0 && parser->content_length != ULLONG_MAX);
1794
+ if (parser->upgrade && (parser->method == HTTP_CONNECT ||
1795
+ (parser->flags & F_SKIPBODY) || !hasBody)) {
1796
+ /* Exit, the rest of the message is in a different protocol. */
1797
+ UPDATE_STATE(NEW_MESSAGE());
1798
+ CALLBACK_NOTIFY(message_complete);
1799
+ RETURN((p - data) + 1);
1800
+ }
1801
+
1802
+ if (parser->flags & F_SKIPBODY) {
1803
+ UPDATE_STATE(NEW_MESSAGE());
1804
+ CALLBACK_NOTIFY(message_complete);
1805
+ } else if (parser->flags & F_CHUNKED) {
1806
+ /* chunked encoding - ignore Content-Length header */
1807
+ UPDATE_STATE(s_chunk_size_start);
1808
+ } else {
1809
+ if (parser->content_length == 0) {
1810
+ /* Content-Length header given but zero: Content-Length: 0\r\n */
1811
+ UPDATE_STATE(NEW_MESSAGE());
1812
+ CALLBACK_NOTIFY(message_complete);
1813
+ } else if (parser->content_length != ULLONG_MAX) {
1814
+ /* Content-Length header given and non-zero */
1815
+ UPDATE_STATE(s_body_identity);
1816
+ } else {
1817
+ if (!http_message_needs_eof(parser)) {
1818
+ /* Assume content-length 0 - read the next */
1819
+ UPDATE_STATE(NEW_MESSAGE());
1820
+ CALLBACK_NOTIFY(message_complete);
1821
+ } else {
1822
+ /* Read body until EOF */
1823
+ UPDATE_STATE(s_body_identity_eof);
1824
+ }
1825
+ }
1826
+ }
1827
+
1828
+ break;
1829
+ }
1830
+
1831
+ case s_body_identity:
1832
+ {
1833
+ uint64_t to_read = MIN(parser->content_length,
1834
+ (uint64_t) ((data + len) - p));
1835
+
1836
+ assert(parser->content_length != 0
1837
+ && parser->content_length != ULLONG_MAX);
1838
+
1839
+ /* The difference between advancing content_length and p is because
1840
+ * the latter will automaticaly advance on the next loop iteration.
1841
+ * Further, if content_length ends up at 0, we want to see the last
1842
+ * byte again for our message complete callback.
1843
+ */
1844
+ MARK(body);
1845
+ parser->content_length -= to_read;
1846
+ p += to_read - 1;
1847
+
1848
+ if (parser->content_length == 0) {
1849
+ UPDATE_STATE(s_message_done);
1850
+
1851
+ /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte.
1852
+ *
1853
+ * The alternative to doing this is to wait for the next byte to
1854
+ * trigger the data callback, just as in every other case. The
1855
+ * problem with this is that this makes it difficult for the test
1856
+ * harness to distinguish between complete-on-EOF and
1857
+ * complete-on-length. It's not clear that this distinction is
1858
+ * important for applications, but let's keep it for now.
1859
+ */
1860
+ CALLBACK_DATA_(body, p - body_mark + 1, p - data);
1861
+ REEXECUTE();
1862
+ }
1863
+
1864
+ break;
1865
+ }
1866
+
1867
+ /* read until EOF */
1868
+ case s_body_identity_eof:
1869
+ MARK(body);
1870
+ p = data + len - 1;
1871
+
1872
+ break;
1873
+
1874
+ case s_message_done:
1875
+ UPDATE_STATE(NEW_MESSAGE());
1876
+ CALLBACK_NOTIFY(message_complete);
1877
+ if (parser->upgrade) {
1878
+ /* Exit, the rest of the message is in a different protocol. */
1879
+ RETURN((p - data) + 1);
1880
+ }
1881
+ break;
1882
+
1883
+ case s_chunk_size_start:
1884
+ {
1885
+ assert(parser->nread == 1);
1886
+ assert(parser->flags & F_CHUNKED);
1887
+
1888
+ unhex_val = unhex[(unsigned char)ch];
1889
+ if (UNLIKELY(unhex_val == -1)) {
1890
+ SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
1891
+ goto error;
1892
+ }
1893
+
1894
+ parser->content_length = unhex_val;
1895
+ UPDATE_STATE(s_chunk_size);
1896
+ break;
1897
+ }
1898
+
1899
+ case s_chunk_size:
1900
+ {
1901
+ uint64_t t;
1902
+
1903
+ assert(parser->flags & F_CHUNKED);
1904
+
1905
+ if (ch == CR) {
1906
+ UPDATE_STATE(s_chunk_size_almost_done);
1907
+ break;
1908
+ }
1909
+
1910
+ unhex_val = unhex[(unsigned char)ch];
1911
+
1912
+ if (unhex_val == -1) {
1913
+ if (ch == ';' || ch == ' ') {
1914
+ UPDATE_STATE(s_chunk_parameters);
1915
+ break;
1916
+ }
1917
+
1918
+ SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
1919
+ goto error;
1920
+ }
1921
+
1922
+ t = parser->content_length;
1923
+ t *= 16;
1924
+ t += unhex_val;
1925
+
1926
+ /* Overflow? Test against a conservative limit for simplicity. */
1927
+ if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) {
1928
+ SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1929
+ goto error;
1930
+ }
1931
+
1932
+ parser->content_length = t;
1933
+ break;
1934
+ }
1935
+
1936
+ case s_chunk_parameters:
1937
+ {
1938
+ assert(parser->flags & F_CHUNKED);
1939
+ /* just ignore this shit. TODO check for overflow */
1940
+ if (ch == CR) {
1941
+ UPDATE_STATE(s_chunk_size_almost_done);
1942
+ break;
1943
+ }
1944
+ break;
1945
+ }
1946
+
1947
+ case s_chunk_size_almost_done:
1948
+ {
1949
+ assert(parser->flags & F_CHUNKED);
1950
+ STRICT_CHECK(ch != LF);
1951
+
1952
+ parser->nread = 0;
1953
+
1954
+ if (parser->content_length == 0) {
1955
+ parser->flags |= F_TRAILING;
1956
+ UPDATE_STATE(s_header_field_start);
1957
+ } else {
1958
+ UPDATE_STATE(s_chunk_data);
1959
+ }
1960
+ CALLBACK_NOTIFY(chunk_header);
1961
+ break;
1962
+ }
1963
+
1964
+ case s_chunk_data:
1965
+ {
1966
+ uint64_t to_read = MIN(parser->content_length,
1967
+ (uint64_t) ((data + len) - p));
1968
+
1969
+ assert(parser->flags & F_CHUNKED);
1970
+ assert(parser->content_length != 0
1971
+ && parser->content_length != ULLONG_MAX);
1972
+
1973
+ /* See the explanation in s_body_identity for why the content
1974
+ * length and data pointers are managed this way.
1975
+ */
1976
+ MARK(body);
1977
+ parser->content_length -= to_read;
1978
+ p += to_read - 1;
1979
+
1980
+ if (parser->content_length == 0) {
1981
+ UPDATE_STATE(s_chunk_data_almost_done);
1982
+ }
1983
+
1984
+ break;
1985
+ }
1986
+
1987
+ case s_chunk_data_almost_done:
1988
+ assert(parser->flags & F_CHUNKED);
1989
+ assert(parser->content_length == 0);
1990
+ STRICT_CHECK(ch != CR);
1991
+ UPDATE_STATE(s_chunk_data_done);
1992
+ CALLBACK_DATA(body);
1993
+ break;
1994
+
1995
+ case s_chunk_data_done:
1996
+ assert(parser->flags & F_CHUNKED);
1997
+ STRICT_CHECK(ch != LF);
1998
+ parser->nread = 0;
1999
+ UPDATE_STATE(s_chunk_size_start);
2000
+ CALLBACK_NOTIFY(chunk_complete);
2001
+ break;
2002
+
2003
+ default:
2004
+ assert(0 && "unhandled state");
2005
+ SET_ERRNO(HPE_INVALID_INTERNAL_STATE);
2006
+ goto error;
2007
+ }
2008
+ }
2009
+
2010
+ /* Run callbacks for any marks that we have leftover after we ran our of
2011
+ * bytes. There should be at most one of these set, so it's OK to invoke
2012
+ * them in series (unset marks will not result in callbacks).
2013
+ *
2014
+ * We use the NOADVANCE() variety of callbacks here because 'p' has already
2015
+ * overflowed 'data' and this allows us to correct for the off-by-one that
2016
+ * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p'
2017
+ * value that's in-bounds).
2018
+ */
2019
+
2020
+ assert(((header_field_mark ? 1 : 0) +
2021
+ (header_value_mark ? 1 : 0) +
2022
+ (url_mark ? 1 : 0) +
2023
+ (body_mark ? 1 : 0) +
2024
+ (status_mark ? 1 : 0)) <= 1);
2025
+
2026
+ CALLBACK_DATA_NOADVANCE(header_field);
2027
+ CALLBACK_DATA_NOADVANCE(header_value);
2028
+ CALLBACK_DATA_NOADVANCE(url);
2029
+ CALLBACK_DATA_NOADVANCE(body);
2030
+ CALLBACK_DATA_NOADVANCE(status);
2031
+
2032
+ RETURN(len);
2033
+
2034
+ error:
2035
+ if (HTTP_PARSER_ERRNO(parser) == HPE_OK) {
2036
+ SET_ERRNO(HPE_UNKNOWN);
2037
+ }
2038
+
2039
+ RETURN(p - data);
2040
+ }
2041
+
2042
+
2043
+ /* Does the parser need to see an EOF to find the end of the message? */
2044
+ int
2045
+ http_message_needs_eof (const http_parser *parser)
2046
+ {
2047
+ if (parser->type == HTTP_REQUEST) {
2048
+ return 0;
2049
+ }
2050
+
2051
+ /* See RFC 2616 section 4.4 */
2052
+ if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
2053
+ parser->status_code == 204 || /* No Content */
2054
+ parser->status_code == 304 || /* Not Modified */
2055
+ parser->flags & F_SKIPBODY) { /* response to a HEAD request */
2056
+ return 0;
2057
+ }
2058
+
2059
+ if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) {
2060
+ return 0;
2061
+ }
2062
+
2063
+ return 1;
2064
+ }
2065
+
2066
+
2067
+ int
2068
+ http_should_keep_alive (const http_parser *parser)
2069
+ {
2070
+ if (parser->http_major > 0 && parser->http_minor > 0) {
2071
+ /* HTTP/1.1 */
2072
+ if (parser->flags & F_CONNECTION_CLOSE) {
2073
+ return 0;
2074
+ }
2075
+ } else {
2076
+ /* HTTP/1.0 or earlier */
2077
+ if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
2078
+ return 0;
2079
+ }
2080
+ }
2081
+
2082
+ return !http_message_needs_eof(parser);
2083
+ }
2084
+
2085
+
2086
+ const char *
2087
+ http_method_str (enum http_method m)
2088
+ {
2089
+ return ELEM_AT(method_strings, m, "<unknown>");
2090
+ }
2091
+
2092
+
2093
+ void
2094
+ http_parser_init (http_parser *parser, enum http_parser_type t)
2095
+ {
2096
+ void *data = parser->data; /* preserve application data */
2097
+ memset(parser, 0, sizeof(*parser));
2098
+ parser->data = data;
2099
+ parser->type = t;
2100
+ parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res));
2101
+ parser->http_errno = HPE_OK;
2102
+ }
2103
+
2104
+ void
2105
+ http_parser_settings_init(http_parser_settings *settings)
2106
+ {
2107
+ memset(settings, 0, sizeof(*settings));
2108
+ }
2109
+
2110
+ const char *
2111
+ http_errno_name(enum http_errno err) {
2112
+ assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
2113
+ return http_strerror_tab[err].name;
2114
+ }
2115
+
2116
+ const char *
2117
+ http_errno_description(enum http_errno err) {
2118
+ assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
2119
+ return http_strerror_tab[err].description;
2120
+ }
2121
+
2122
+ static enum http_host_state
2123
+ http_parse_host_char(enum http_host_state s, const char ch) {
2124
+ switch(s) {
2125
+ case s_http_userinfo:
2126
+ case s_http_userinfo_start:
2127
+ if (ch == '@') {
2128
+ return s_http_host_start;
2129
+ }
2130
+
2131
+ if (IS_USERINFO_CHAR(ch)) {
2132
+ return s_http_userinfo;
2133
+ }
2134
+ break;
2135
+
2136
+ case s_http_host_start:
2137
+ if (ch == '[') {
2138
+ return s_http_host_v6_start;
2139
+ }
2140
+
2141
+ if (IS_HOST_CHAR(ch)) {
2142
+ return s_http_host;
2143
+ }
2144
+
2145
+ break;
2146
+
2147
+ case s_http_host:
2148
+ if (IS_HOST_CHAR(ch)) {
2149
+ return s_http_host;
2150
+ }
2151
+
2152
+ /* FALLTHROUGH */
2153
+ case s_http_host_v6_end:
2154
+ if (ch == ':') {
2155
+ return s_http_host_port_start;
2156
+ }
2157
+
2158
+ break;
2159
+
2160
+ case s_http_host_v6:
2161
+ if (ch == ']') {
2162
+ return s_http_host_v6_end;
2163
+ }
2164
+
2165
+ /* FALLTHROUGH */
2166
+ case s_http_host_v6_start:
2167
+ if (IS_HEX(ch) || ch == ':' || ch == '.') {
2168
+ return s_http_host_v6;
2169
+ }
2170
+
2171
+ if (s == s_http_host_v6 && ch == '%') {
2172
+ return s_http_host_v6_zone_start;
2173
+ }
2174
+ break;
2175
+
2176
+ case s_http_host_v6_zone:
2177
+ if (ch == ']') {
2178
+ return s_http_host_v6_end;
2179
+ }
2180
+
2181
+ /* FALLTHROUGH */
2182
+ case s_http_host_v6_zone_start:
2183
+ /* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */
2184
+ if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' ||
2185
+ ch == '~') {
2186
+ return s_http_host_v6_zone;
2187
+ }
2188
+ break;
2189
+
2190
+ case s_http_host_port:
2191
+ case s_http_host_port_start:
2192
+ if (IS_NUM(ch)) {
2193
+ return s_http_host_port;
2194
+ }
2195
+
2196
+ break;
2197
+
2198
+ default:
2199
+ break;
2200
+ }
2201
+ return s_http_host_dead;
2202
+ }
2203
+
2204
+ static int
2205
+ http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
2206
+ enum http_host_state s;
2207
+
2208
+ const char *p;
2209
+ size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len;
2210
+
2211
+ assert(u->field_set & (1 << UF_HOST));
2212
+
2213
+ u->field_data[UF_HOST].len = 0;
2214
+
2215
+ s = found_at ? s_http_userinfo_start : s_http_host_start;
2216
+
2217
+ for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) {
2218
+ enum http_host_state new_s = http_parse_host_char(s, *p);
2219
+
2220
+ if (new_s == s_http_host_dead) {
2221
+ return 1;
2222
+ }
2223
+
2224
+ switch(new_s) {
2225
+ case s_http_host:
2226
+ if (s != s_http_host) {
2227
+ u->field_data[UF_HOST].off = p - buf;
2228
+ }
2229
+ u->field_data[UF_HOST].len++;
2230
+ break;
2231
+
2232
+ case s_http_host_v6:
2233
+ if (s != s_http_host_v6) {
2234
+ u->field_data[UF_HOST].off = p - buf;
2235
+ }
2236
+ u->field_data[UF_HOST].len++;
2237
+ break;
2238
+
2239
+ case s_http_host_v6_zone_start:
2240
+ case s_http_host_v6_zone:
2241
+ u->field_data[UF_HOST].len++;
2242
+ break;
2243
+
2244
+ case s_http_host_port:
2245
+ if (s != s_http_host_port) {
2246
+ u->field_data[UF_PORT].off = p - buf;
2247
+ u->field_data[UF_PORT].len = 0;
2248
+ u->field_set |= (1 << UF_PORT);
2249
+ }
2250
+ u->field_data[UF_PORT].len++;
2251
+ break;
2252
+
2253
+ case s_http_userinfo:
2254
+ if (s != s_http_userinfo) {
2255
+ u->field_data[UF_USERINFO].off = p - buf ;
2256
+ u->field_data[UF_USERINFO].len = 0;
2257
+ u->field_set |= (1 << UF_USERINFO);
2258
+ }
2259
+ u->field_data[UF_USERINFO].len++;
2260
+ break;
2261
+
2262
+ default:
2263
+ break;
2264
+ }
2265
+ s = new_s;
2266
+ }
2267
+
2268
+ /* Make sure we don't end somewhere unexpected */
2269
+ switch (s) {
2270
+ case s_http_host_start:
2271
+ case s_http_host_v6_start:
2272
+ case s_http_host_v6:
2273
+ case s_http_host_v6_zone_start:
2274
+ case s_http_host_v6_zone:
2275
+ case s_http_host_port_start:
2276
+ case s_http_userinfo:
2277
+ case s_http_userinfo_start:
2278
+ return 1;
2279
+ default:
2280
+ break;
2281
+ }
2282
+
2283
+ return 0;
2284
+ }
2285
+
2286
+ void
2287
+ http_parser_url_init(struct http_parser_url *u) {
2288
+ memset(u, 0, sizeof(*u));
2289
+ }
2290
+
2291
+ int
2292
+ http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
2293
+ struct http_parser_url *u)
2294
+ {
2295
+ enum state s;
2296
+ const char *p;
2297
+ enum http_parser_url_fields uf, old_uf;
2298
+ int found_at = 0;
2299
+
2300
+ u->port = u->field_set = 0;
2301
+ s = is_connect ? s_req_server_start : s_req_spaces_before_url;
2302
+ old_uf = UF_MAX;
2303
+
2304
+ for (p = buf; p < buf + buflen; p++) {
2305
+ s = parse_url_char(s, *p);
2306
+
2307
+ /* Figure out the next field that we're operating on */
2308
+ switch (s) {
2309
+ case s_dead:
2310
+ return 1;
2311
+
2312
+ /* Skip delimeters */
2313
+ case s_req_schema_slash:
2314
+ case s_req_schema_slash_slash:
2315
+ case s_req_server_start:
2316
+ case s_req_query_string_start:
2317
+ case s_req_fragment_start:
2318
+ continue;
2319
+
2320
+ case s_req_schema:
2321
+ uf = UF_SCHEMA;
2322
+ break;
2323
+
2324
+ case s_req_server_with_at:
2325
+ found_at = 1;
2326
+
2327
+ /* FALLTHROUGH */
2328
+ case s_req_server:
2329
+ uf = UF_HOST;
2330
+ break;
2331
+
2332
+ case s_req_path:
2333
+ uf = UF_PATH;
2334
+ break;
2335
+
2336
+ case s_req_query_string:
2337
+ uf = UF_QUERY;
2338
+ break;
2339
+
2340
+ case s_req_fragment:
2341
+ uf = UF_FRAGMENT;
2342
+ break;
2343
+
2344
+ default:
2345
+ assert(!"Unexpected state");
2346
+ return 1;
2347
+ }
2348
+
2349
+ /* Nothing's changed; soldier on */
2350
+ if (uf == old_uf) {
2351
+ u->field_data[uf].len++;
2352
+ continue;
2353
+ }
2354
+
2355
+ u->field_data[uf].off = p - buf;
2356
+ u->field_data[uf].len = 1;
2357
+
2358
+ u->field_set |= (1 << uf);
2359
+ old_uf = uf;
2360
+ }
2361
+
2362
+ /* host must be present if there is a schema */
2363
+ /* parsing http:///toto will fail */
2364
+ if ((u->field_set & (1 << UF_SCHEMA)) &&
2365
+ (u->field_set & (1 << UF_HOST)) == 0) {
2366
+ return 1;
2367
+ }
2368
+
2369
+ if (u->field_set & (1 << UF_HOST)) {
2370
+ if (http_parse_host(buf, u, found_at) != 0) {
2371
+ return 1;
2372
+ }
2373
+ }
2374
+
2375
+ /* CONNECT requests can only contain "hostname:port" */
2376
+ if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) {
2377
+ return 1;
2378
+ }
2379
+
2380
+ if (u->field_set & (1 << UF_PORT)) {
2381
+ /* Don't bother with endp; we've already validated the string */
2382
+ unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10);
2383
+
2384
+ /* Ports have a max value of 2^16 */
2385
+ if (v > 0xffff) {
2386
+ return 1;
2387
+ }
2388
+
2389
+ u->port = (uint16_t) v;
2390
+ }
2391
+
2392
+ return 0;
2393
+ }
2394
+
2395
+ void
2396
+ http_parser_pause(http_parser *parser, int paused) {
2397
+ /* Users should only be pausing/unpausing a parser that is not in an error
2398
+ * state. In non-debug builds, there's not much that we can do about this
2399
+ * other than ignore it.
2400
+ */
2401
+ if (HTTP_PARSER_ERRNO(parser) == HPE_OK ||
2402
+ HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) {
2403
+ SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK);
2404
+ } else {
2405
+ assert(0 && "Attempting to pause parser in error state");
2406
+ }
2407
+ }
2408
+
2409
+ int
2410
+ http_body_is_final(const struct http_parser *parser) {
2411
+ return parser->state == s_message_done;
2412
+ }
2413
+
2414
+ unsigned long
2415
+ http_parser_version(void) {
2416
+ return HTTP_PARSER_VERSION_MAJOR * 0x10000 |
2417
+ HTTP_PARSER_VERSION_MINOR * 0x00100 |
2418
+ HTTP_PARSER_VERSION_PATCH * 0x00001;
2419
+ }