nginxtra 1.8.1.12 → 1.10.1.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (238) hide show
  1. checksums.yaml +4 -4
  2. data/bin/nginxtra +1 -1
  3. data/bin/nginxtra_rails +1 -1
  4. data/lib/nginxtra/version.rb +1 -1
  5. data/vendor/nginx/CHANGES +363 -25
  6. data/vendor/nginx/CHANGES.ru +365 -21
  7. data/vendor/nginx/LICENSE +2 -2
  8. data/vendor/nginx/auto/cc/conf +32 -0
  9. data/vendor/nginx/auto/cc/gcc +1 -1
  10. data/vendor/nginx/auto/cc/icc +2 -2
  11. data/vendor/nginx/auto/cc/msvc +29 -8
  12. data/vendor/nginx/auto/cc/name +2 -25
  13. data/vendor/nginx/auto/cc/sunc +3 -0
  14. data/vendor/nginx/auto/endianness +7 -2
  15. data/vendor/nginx/auto/install +60 -26
  16. data/vendor/nginx/auto/lib/conf +4 -4
  17. data/vendor/nginx/auto/lib/geoip/conf +6 -1
  18. data/vendor/nginx/auto/lib/libgd/conf +6 -1
  19. data/vendor/nginx/auto/lib/libxslt/conf +11 -2
  20. data/vendor/nginx/auto/lib/make +1 -1
  21. data/vendor/nginx/auto/lib/md5/conf +2 -2
  22. data/vendor/nginx/auto/lib/md5/make +2 -2
  23. data/vendor/nginx/auto/lib/openssl/conf +52 -3
  24. data/vendor/nginx/auto/lib/openssl/make +1 -1
  25. data/vendor/nginx/auto/lib/pcre/conf +2 -2
  26. data/vendor/nginx/auto/lib/pcre/make +2 -2
  27. data/vendor/nginx/auto/lib/perl/conf +6 -3
  28. data/vendor/nginx/auto/lib/perl/make +4 -1
  29. data/vendor/nginx/auto/lib/sha1/conf +2 -2
  30. data/vendor/nginx/auto/lib/sha1/make +2 -2
  31. data/vendor/nginx/auto/lib/zlib/conf +2 -2
  32. data/vendor/nginx/auto/lib/zlib/make +2 -2
  33. data/vendor/nginx/auto/make +281 -16
  34. data/vendor/nginx/auto/module +122 -0
  35. data/vendor/nginx/auto/modules +909 -178
  36. data/vendor/nginx/auto/options +81 -19
  37. data/vendor/nginx/auto/os/conf +9 -0
  38. data/vendor/nginx/auto/os/darwin +3 -0
  39. data/vendor/nginx/auto/os/freebsd +0 -20
  40. data/vendor/nginx/auto/os/linux +0 -12
  41. data/vendor/nginx/auto/os/win32 +5 -1
  42. data/vendor/nginx/auto/sources +11 -311
  43. data/vendor/nginx/auto/summary +1 -0
  44. data/vendor/nginx/auto/types/sizeof +5 -3
  45. data/vendor/nginx/auto/types/typedef +9 -4
  46. data/vendor/nginx/auto/types/uintptr_t +7 -2
  47. data/vendor/nginx/auto/unix +72 -12
  48. data/vendor/nginx/conf/fastcgi.conf +1 -0
  49. data/vendor/nginx/conf/fastcgi_params +1 -0
  50. data/vendor/nginx/conf/scgi_params +1 -0
  51. data/vendor/nginx/conf/uwsgi_params +1 -0
  52. data/vendor/nginx/configure +1 -1
  53. data/vendor/nginx/contrib/vim/syntax/nginx.vim +2 -2
  54. data/vendor/nginx/man/nginx.8 +6 -2
  55. data/vendor/nginx/src/core/nginx.c +281 -114
  56. data/vendor/nginx/src/core/nginx.h +2 -2
  57. data/vendor/nginx/src/core/ngx_conf_file.c +54 -13
  58. data/vendor/nginx/src/core/ngx_conf_file.h +8 -52
  59. data/vendor/nginx/src/core/ngx_config.h +0 -5
  60. data/vendor/nginx/src/core/ngx_connection.c +270 -37
  61. data/vendor/nginx/src/core/ngx_connection.h +35 -12
  62. data/vendor/nginx/src/core/ngx_core.h +4 -0
  63. data/vendor/nginx/src/core/ngx_crypt.c +2 -2
  64. data/vendor/nginx/src/core/ngx_cycle.c +72 -25
  65. data/vendor/nginx/src/core/ngx_cycle.h +28 -39
  66. data/vendor/nginx/src/core/ngx_file.c +14 -5
  67. data/vendor/nginx/src/core/ngx_file.h +2 -0
  68. data/vendor/nginx/src/core/ngx_hash.c +13 -1
  69. data/vendor/nginx/src/core/ngx_inet.c +20 -18
  70. data/vendor/nginx/src/core/ngx_log.c +12 -12
  71. data/vendor/nginx/src/core/ngx_log.h +13 -6
  72. data/vendor/nginx/src/core/ngx_module.c +360 -0
  73. data/vendor/nginx/src/core/ngx_module.h +307 -0
  74. data/vendor/nginx/src/core/ngx_open_file_cache.c +2 -2
  75. data/vendor/nginx/src/core/ngx_output_chain.c +8 -4
  76. data/vendor/nginx/src/core/ngx_palloc.c +42 -44
  77. data/vendor/nginx/src/{http/ngx_http_parse_time.c → core/ngx_parse_time.c} +2 -3
  78. data/vendor/nginx/src/core/ngx_parse_time.h +22 -0
  79. data/vendor/nginx/src/core/ngx_proxy_protocol.c +50 -1
  80. data/vendor/nginx/src/core/ngx_proxy_protocol.h +3 -1
  81. data/vendor/nginx/src/core/ngx_regex.c +1 -38
  82. data/vendor/nginx/src/core/ngx_resolver.c +1814 -320
  83. data/vendor/nginx/src/core/ngx_resolver.h +67 -10
  84. data/vendor/nginx/src/core/ngx_rwlock.c +120 -0
  85. data/vendor/nginx/src/core/ngx_rwlock.h +21 -0
  86. data/vendor/nginx/src/core/ngx_slab.c +6 -5
  87. data/vendor/nginx/src/core/ngx_string.c +1 -1
  88. data/vendor/nginx/src/core/ngx_syslog.c +11 -3
  89. data/vendor/nginx/src/core/ngx_syslog.h +2 -1
  90. data/vendor/nginx/src/core/ngx_thread_pool.c +4 -0
  91. data/vendor/nginx/src/core/ngx_times.c +2 -2
  92. data/vendor/nginx/src/event/modules/ngx_devpoll_module.c +3 -1
  93. data/vendor/nginx/src/event/modules/ngx_epoll_module.c +5 -2
  94. data/vendor/nginx/src/event/modules/ngx_eventport_module.c +5 -5
  95. data/vendor/nginx/src/event/modules/ngx_kqueue_module.c +15 -8
  96. data/vendor/nginx/src/event/modules/ngx_poll_module.c +0 -10
  97. data/vendor/nginx/src/event/modules/ngx_select_module.c +0 -10
  98. data/vendor/nginx/src/event/ngx_event.c +60 -103
  99. data/vendor/nginx/src/event/ngx_event.h +22 -26
  100. data/vendor/nginx/src/event/ngx_event_accept.c +414 -88
  101. data/vendor/nginx/src/event/ngx_event_connect.c +27 -18
  102. data/vendor/nginx/src/event/ngx_event_connect.h +1 -0
  103. data/vendor/nginx/src/event/ngx_event_openssl.c +65 -25
  104. data/vendor/nginx/src/event/ngx_event_openssl.h +17 -0
  105. data/vendor/nginx/src/event/ngx_event_openssl_stapling.c +73 -7
  106. data/vendor/nginx/src/event/ngx_event_pipe.c +85 -27
  107. data/vendor/nginx/src/event/ngx_event_pipe.h +10 -0
  108. data/vendor/nginx/src/http/modules/ngx_http_auth_basic_module.c +1 -1
  109. data/vendor/nginx/src/http/modules/ngx_http_auth_request_module.c +2 -2
  110. data/vendor/nginx/src/http/modules/ngx_http_chunked_filter_module.c +2 -2
  111. data/vendor/nginx/src/http/modules/ngx_http_dav_module.c +6 -6
  112. data/vendor/nginx/src/http/modules/ngx_http_fastcgi_module.c +17 -11
  113. data/vendor/nginx/src/http/modules/ngx_http_gzip_filter_module.c +2 -2
  114. data/vendor/nginx/src/http/modules/ngx_http_headers_filter_module.c +9 -9
  115. data/vendor/nginx/src/http/modules/ngx_http_image_filter_module.c +2 -2
  116. data/vendor/nginx/src/http/modules/ngx_http_limit_conn_module.c +2 -2
  117. data/vendor/nginx/src/http/modules/ngx_http_limit_req_module.c +0 -7
  118. data/vendor/nginx/src/http/modules/ngx_http_map_module.c +6 -6
  119. data/vendor/nginx/src/http/modules/ngx_http_memcached_module.c +2 -1
  120. data/vendor/nginx/src/http/modules/ngx_http_mp4_module.c +13 -13
  121. data/vendor/nginx/src/http/modules/ngx_http_not_modified_filter_module.c +2 -2
  122. data/vendor/nginx/src/http/modules/ngx_http_proxy_module.c +26 -21
  123. data/vendor/nginx/src/http/modules/ngx_http_random_index_module.c +1 -1
  124. data/vendor/nginx/src/http/modules/ngx_http_range_filter_module.c +26 -8
  125. data/vendor/nginx/src/http/modules/ngx_http_realip_module.c +73 -3
  126. data/vendor/nginx/src/http/modules/ngx_http_referer_module.c +1 -1
  127. data/vendor/nginx/src/http/modules/ngx_http_rewrite_module.c +6 -6
  128. data/vendor/nginx/src/http/modules/ngx_http_scgi_module.c +5 -3
  129. data/vendor/nginx/src/http/modules/ngx_http_slice_filter_module.c +526 -0
  130. data/vendor/nginx/src/http/modules/ngx_http_ssi_filter_module.c +7 -7
  131. data/vendor/nginx/src/http/modules/ngx_http_ssl_module.c +19 -16
  132. data/vendor/nginx/src/http/modules/ngx_http_static_module.c +1 -1
  133. data/vendor/nginx/src/http/modules/ngx_http_stub_status_module.c +1 -1
  134. data/vendor/nginx/src/http/modules/ngx_http_sub_filter_module.c +373 -173
  135. data/vendor/nginx/src/http/modules/ngx_http_upstream_hash_module.c +72 -46
  136. data/vendor/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c +18 -30
  137. data/vendor/nginx/src/http/modules/ngx_http_upstream_keepalive_module.c +50 -39
  138. data/vendor/nginx/src/http/modules/ngx_http_upstream_least_conn_module.c +38 -129
  139. data/vendor/nginx/src/http/modules/ngx_http_upstream_zone_module.c +246 -0
  140. data/vendor/nginx/src/http/modules/ngx_http_uwsgi_module.c +6 -5
  141. data/vendor/nginx/src/http/modules/perl/nginx.xs +9 -9
  142. data/vendor/nginx/src/http/ngx_http.c +46 -43
  143. data/vendor/nginx/src/http/ngx_http.h +4 -9
  144. data/vendor/nginx/src/http/ngx_http_cache.h +4 -0
  145. data/vendor/nginx/src/http/ngx_http_copy_filter_module.c +13 -5
  146. data/vendor/nginx/src/http/ngx_http_core_module.c +92 -91
  147. data/vendor/nginx/src/http/ngx_http_core_module.h +12 -8
  148. data/vendor/nginx/src/http/ngx_http_file_cache.c +61 -10
  149. data/vendor/nginx/src/http/ngx_http_request.c +37 -50
  150. data/vendor/nginx/src/http/ngx_http_request.h +10 -15
  151. data/vendor/nginx/src/http/ngx_http_request_body.c +64 -88
  152. data/vendor/nginx/src/http/ngx_http_script.c +3 -3
  153. data/vendor/nginx/src/http/ngx_http_special_response.c +1 -4
  154. data/vendor/nginx/src/http/ngx_http_upstream.c +245 -109
  155. data/vendor/nginx/src/http/ngx_http_upstream.h +11 -5
  156. data/vendor/nginx/src/http/ngx_http_upstream_round_robin.c +212 -65
  157. data/vendor/nginx/src/http/ngx_http_upstream_round_robin.h +66 -5
  158. data/vendor/nginx/src/http/ngx_http_variables.c +28 -15
  159. data/vendor/nginx/src/http/ngx_http_write_filter_module.c +1 -1
  160. data/vendor/nginx/src/http/v2/ngx_http_v2.c +4349 -0
  161. data/vendor/nginx/src/http/v2/ngx_http_v2.h +337 -0
  162. data/vendor/nginx/src/http/v2/ngx_http_v2_filter_module.c +1391 -0
  163. data/vendor/nginx/src/http/v2/ngx_http_v2_huff_decode.c +2714 -0
  164. data/vendor/nginx/src/http/v2/ngx_http_v2_huff_encode.c +254 -0
  165. data/vendor/nginx/src/http/v2/ngx_http_v2_module.c +469 -0
  166. data/vendor/nginx/src/http/{ngx_http_spdy_module.h → v2/ngx_http_v2_module.h} +10 -9
  167. data/vendor/nginx/src/http/v2/ngx_http_v2_table.c +349 -0
  168. data/vendor/nginx/src/mail/ngx_mail.c +49 -82
  169. data/vendor/nginx/src/mail/ngx_mail.h +16 -23
  170. data/vendor/nginx/src/mail/ngx_mail_auth_http_module.c +1 -1
  171. data/vendor/nginx/src/mail/ngx_mail_core_module.c +60 -34
  172. data/vendor/nginx/src/mail/ngx_mail_handler.c +17 -12
  173. data/vendor/nginx/src/mail/ngx_mail_proxy_module.c +1 -14
  174. data/vendor/nginx/src/mail/ngx_mail_smtp_handler.c +1 -1
  175. data/vendor/nginx/src/mail/ngx_mail_ssl_module.c +5 -5
  176. data/vendor/nginx/src/os/unix/ngx_atomic.h +10 -10
  177. data/vendor/nginx/src/os/unix/ngx_channel.h +4 -4
  178. data/vendor/nginx/src/os/unix/ngx_darwin_config.h +2 -0
  179. data/vendor/nginx/src/os/unix/ngx_darwin_init.c +1 -0
  180. data/vendor/nginx/src/os/unix/ngx_dlopen.c +28 -0
  181. data/vendor/nginx/src/os/unix/ngx_dlopen.h +31 -0
  182. data/vendor/nginx/src/os/unix/ngx_errno.h +1 -0
  183. data/vendor/nginx/src/os/unix/ngx_file_aio_read.c +1 -1
  184. data/vendor/nginx/src/os/unix/ngx_files.c +313 -80
  185. data/vendor/nginx/src/os/unix/ngx_files.h +5 -2
  186. data/vendor/nginx/src/os/unix/ngx_freebsd_config.h +3 -1
  187. data/vendor/nginx/src/os/unix/ngx_freebsd_init.c +1 -0
  188. data/vendor/nginx/src/os/unix/ngx_freebsd_sendfile_chain.c +13 -0
  189. data/vendor/nginx/src/os/unix/ngx_linux.h +0 -2
  190. data/vendor/nginx/src/os/unix/ngx_linux_aio_read.c +1 -1
  191. data/vendor/nginx/src/os/unix/ngx_linux_config.h +2 -6
  192. data/vendor/nginx/src/os/unix/ngx_linux_init.c +1 -33
  193. data/vendor/nginx/src/os/unix/ngx_linux_sendfile_chain.c +55 -12
  194. data/vendor/nginx/src/os/unix/ngx_os.h +3 -9
  195. data/vendor/nginx/src/os/unix/ngx_posix_config.h +14 -1
  196. data/vendor/nginx/src/os/unix/ngx_posix_init.c +2 -1
  197. data/vendor/nginx/src/os/unix/ngx_process.c +1 -1
  198. data/vendor/nginx/src/os/unix/ngx_process_cycle.c +25 -51
  199. data/vendor/nginx/src/os/unix/ngx_process_cycle.h +1 -0
  200. data/vendor/nginx/src/os/unix/ngx_readv_chain.c +24 -28
  201. data/vendor/nginx/src/os/unix/ngx_recv.c +30 -79
  202. data/vendor/nginx/src/os/unix/ngx_send.c +1 -1
  203. data/vendor/nginx/src/os/unix/ngx_setaffinity.c +14 -30
  204. data/vendor/nginx/src/os/unix/ngx_setaffinity.h +15 -1
  205. data/vendor/nginx/src/os/unix/ngx_solaris_config.h +2 -0
  206. data/vendor/nginx/src/os/unix/ngx_solaris_init.c +1 -0
  207. data/vendor/nginx/src/os/unix/ngx_solaris_sendfilev_chain.c +23 -0
  208. data/vendor/nginx/src/os/unix/ngx_sunpro_amd64.il +3 -3
  209. data/vendor/nginx/src/os/unix/ngx_sunpro_x86.il +3 -3
  210. data/vendor/nginx/src/os/unix/ngx_udp_recv.c +5 -48
  211. data/vendor/nginx/src/os/unix/ngx_udp_send.c +56 -0
  212. data/vendor/nginx/src/stream/ngx_stream.c +564 -0
  213. data/vendor/nginx/src/stream/ngx_stream.h +212 -0
  214. data/vendor/nginx/src/stream/ngx_stream_access_module.c +451 -0
  215. data/vendor/nginx/src/stream/ngx_stream_core_module.c +562 -0
  216. data/vendor/nginx/src/stream/ngx_stream_handler.c +344 -0
  217. data/vendor/nginx/src/stream/ngx_stream_limit_conn_module.c +632 -0
  218. data/vendor/nginx/src/stream/ngx_stream_proxy_module.c +1674 -0
  219. data/vendor/nginx/src/stream/ngx_stream_ssl_module.c +460 -0
  220. data/vendor/nginx/src/stream/ngx_stream_ssl_module.h +49 -0
  221. data/vendor/nginx/src/stream/ngx_stream_upstream.c +464 -0
  222. data/vendor/nginx/src/stream/ngx_stream_upstream.h +107 -0
  223. data/vendor/nginx/src/stream/ngx_stream_upstream_hash_module.c +656 -0
  224. data/vendor/nginx/src/stream/ngx_stream_upstream_least_conn_module.c +307 -0
  225. data/vendor/nginx/src/stream/ngx_stream_upstream_round_robin.c +702 -0
  226. data/vendor/nginx/src/stream/ngx_stream_upstream_round_robin.h +139 -0
  227. data/vendor/nginx/src/stream/ngx_stream_upstream_zone_module.c +242 -0
  228. metadata +39 -15
  229. data/vendor/nginx/src/event/modules/ngx_aio_module.c +0 -171
  230. data/vendor/nginx/src/event/modules/ngx_rtsig_module.c +0 -735
  231. data/vendor/nginx/src/http/ngx_http_spdy.c +0 -3701
  232. data/vendor/nginx/src/http/ngx_http_spdy.h +0 -261
  233. data/vendor/nginx/src/http/ngx_http_spdy_filter_module.c +0 -1222
  234. data/vendor/nginx/src/http/ngx_http_spdy_module.c +0 -408
  235. data/vendor/nginx/src/os/unix/ngx_aio_read.c +0 -109
  236. data/vendor/nginx/src/os/unix/ngx_aio_read_chain.c +0 -78
  237. data/vendor/nginx/src/os/unix/ngx_aio_write.c +0 -109
  238. data/vendor/nginx/src/os/unix/ngx_aio_write_chain.c +0 -100
@@ -14,7 +14,9 @@
14
14
  #include <ngx_http.h>
15
15
 
16
16
 
17
- typedef struct {
17
+ typedef struct ngx_http_upstream_rr_peer_s ngx_http_upstream_rr_peer_t;
18
+
19
+ struct ngx_http_upstream_rr_peer_s {
18
20
  struct sockaddr *sockaddr;
19
21
  socklen_t socklen;
20
22
  ngx_str_t name;
@@ -24,6 +26,8 @@ typedef struct {
24
26
  ngx_int_t effective_weight;
25
27
  ngx_int_t weight;
26
28
 
29
+ ngx_uint_t conns;
30
+
27
31
  ngx_uint_t fails;
28
32
  time_t accessed;
29
33
  time_t checked;
@@ -34,9 +38,16 @@ typedef struct {
34
38
  ngx_uint_t down; /* unsigned down:1; */
35
39
 
36
40
  #if (NGX_HTTP_SSL)
37
- ngx_ssl_session_t *ssl_session; /* local to a process */
41
+ void *ssl_session;
42
+ int ssl_session_len;
38
43
  #endif
39
- } ngx_http_upstream_rr_peer_t;
44
+
45
+ ngx_http_upstream_rr_peer_t *next;
46
+
47
+ #if (NGX_HTTP_UPSTREAM_ZONE)
48
+ ngx_atomic_t lock;
49
+ #endif
50
+ };
40
51
 
41
52
 
42
53
  typedef struct ngx_http_upstream_rr_peers_s ngx_http_upstream_rr_peers_t;
@@ -44,6 +55,12 @@ typedef struct ngx_http_upstream_rr_peers_s ngx_http_upstream_rr_peers_t;
44
55
  struct ngx_http_upstream_rr_peers_s {
45
56
  ngx_uint_t number;
46
57
 
58
+ #if (NGX_HTTP_UPSTREAM_ZONE)
59
+ ngx_slab_pool_t *shpool;
60
+ ngx_atomic_t rwlock;
61
+ ngx_http_upstream_rr_peers_t *zone_next;
62
+ #endif
63
+
47
64
  ngx_uint_t total_weight;
48
65
 
49
66
  unsigned single:1;
@@ -53,13 +70,57 @@ struct ngx_http_upstream_rr_peers_s {
53
70
 
54
71
  ngx_http_upstream_rr_peers_t *next;
55
72
 
56
- ngx_http_upstream_rr_peer_t peer[1];
73
+ ngx_http_upstream_rr_peer_t *peer;
57
74
  };
58
75
 
59
76
 
77
+ #if (NGX_HTTP_UPSTREAM_ZONE)
78
+
79
+ #define ngx_http_upstream_rr_peers_rlock(peers) \
80
+ \
81
+ if (peers->shpool) { \
82
+ ngx_rwlock_rlock(&peers->rwlock); \
83
+ }
84
+
85
+ #define ngx_http_upstream_rr_peers_wlock(peers) \
86
+ \
87
+ if (peers->shpool) { \
88
+ ngx_rwlock_wlock(&peers->rwlock); \
89
+ }
90
+
91
+ #define ngx_http_upstream_rr_peers_unlock(peers) \
92
+ \
93
+ if (peers->shpool) { \
94
+ ngx_rwlock_unlock(&peers->rwlock); \
95
+ }
96
+
97
+
98
+ #define ngx_http_upstream_rr_peer_lock(peers, peer) \
99
+ \
100
+ if (peers->shpool) { \
101
+ ngx_rwlock_wlock(&peer->lock); \
102
+ }
103
+
104
+ #define ngx_http_upstream_rr_peer_unlock(peers, peer) \
105
+ \
106
+ if (peers->shpool) { \
107
+ ngx_rwlock_unlock(&peer->lock); \
108
+ }
109
+
110
+ #else
111
+
112
+ #define ngx_http_upstream_rr_peers_rlock(peers)
113
+ #define ngx_http_upstream_rr_peers_wlock(peers)
114
+ #define ngx_http_upstream_rr_peers_unlock(peers)
115
+ #define ngx_http_upstream_rr_peer_lock(peers, peer)
116
+ #define ngx_http_upstream_rr_peer_unlock(peers, peer)
117
+
118
+ #endif
119
+
120
+
60
121
  typedef struct {
61
122
  ngx_http_upstream_rr_peers_t *peers;
62
- ngx_uint_t current;
123
+ ngx_http_upstream_rr_peer_t *current;
63
124
  uintptr_t *tried;
64
125
  uintptr_t data;
65
126
  } ngx_http_upstream_rr_peer_data_t;
@@ -575,7 +575,7 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
575
575
  return NULL;
576
576
  }
577
577
 
578
- if (ngx_strncmp(name->data, "http_", 5) == 0) {
578
+ if (name->len >= 5 && ngx_strncmp(name->data, "http_", 5) == 0) {
579
579
 
580
580
  if (ngx_http_variable_unknown_header_in(r, vv, (uintptr_t) name)
581
581
  == NGX_OK)
@@ -586,7 +586,7 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
586
586
  return NULL;
587
587
  }
588
588
 
589
- if (ngx_strncmp(name->data, "sent_http_", 10) == 0) {
589
+ if (name->len >= 10 && ngx_strncmp(name->data, "sent_http_", 10) == 0) {
590
590
 
591
591
  if (ngx_http_variable_unknown_header_out(r, vv, (uintptr_t) name)
592
592
  == NGX_OK)
@@ -597,7 +597,7 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
597
597
  return NULL;
598
598
  }
599
599
 
600
- if (ngx_strncmp(name->data, "upstream_http_", 14) == 0) {
600
+ if (name->len >= 14 && ngx_strncmp(name->data, "upstream_http_", 14) == 0) {
601
601
 
602
602
  if (ngx_http_upstream_header_variable(r, vv, (uintptr_t) name)
603
603
  == NGX_OK)
@@ -608,7 +608,7 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
608
608
  return NULL;
609
609
  }
610
610
 
611
- if (ngx_strncmp(name->data, "cookie_", 7) == 0) {
611
+ if (name->len >= 7 && ngx_strncmp(name->data, "cookie_", 7) == 0) {
612
612
 
613
613
  if (ngx_http_variable_cookie(r, vv, (uintptr_t) name) == NGX_OK) {
614
614
  return vv;
@@ -617,7 +617,9 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
617
617
  return NULL;
618
618
  }
619
619
 
620
- if (ngx_strncmp(name->data, "upstream_cookie_", 16) == 0) {
620
+ if (name->len >= 16
621
+ && ngx_strncmp(name->data, "upstream_cookie_", 16) == 0)
622
+ {
621
623
 
622
624
  if (ngx_http_upstream_cookie_variable(r, vv, (uintptr_t) name)
623
625
  == NGX_OK)
@@ -628,7 +630,7 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
628
630
  return NULL;
629
631
  }
630
632
 
631
- if (ngx_strncmp(name->data, "arg_", 4) == 0) {
633
+ if (name->len >= 4 && ngx_strncmp(name->data, "arg_", 4) == 0) {
632
634
 
633
635
  if (ngx_http_variable_argument(r, vv, (uintptr_t) name) == NGX_OK) {
634
636
  return vv;
@@ -2426,9 +2428,8 @@ ngx_http_regex_exec(ngx_http_request_t *r, ngx_http_regex_t *re, ngx_str_t *s)
2426
2428
 
2427
2429
  v = cmcf->variables.elts;
2428
2430
 
2429
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2430
- "http regex set $%V to \"%*s\"",
2431
- &v[index].name, vv->len, vv->data);
2431
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2432
+ "http regex set $%V to \"%v\"", &v[index].name, vv);
2432
2433
  }
2433
2434
  #endif
2434
2435
  }
@@ -2535,21 +2536,27 @@ ngx_http_variables_init_vars(ngx_conf_t *cf)
2535
2536
  }
2536
2537
  }
2537
2538
 
2538
- if (ngx_strncmp(v[i].name.data, "http_", 5) == 0) {
2539
+ if (v[i].name.len >= 5
2540
+ && ngx_strncmp(v[i].name.data, "http_", 5) == 0)
2541
+ {
2539
2542
  v[i].get_handler = ngx_http_variable_unknown_header_in;
2540
2543
  v[i].data = (uintptr_t) &v[i].name;
2541
2544
 
2542
2545
  continue;
2543
2546
  }
2544
2547
 
2545
- if (ngx_strncmp(v[i].name.data, "sent_http_", 10) == 0) {
2548
+ if (v[i].name.len >= 10
2549
+ && ngx_strncmp(v[i].name.data, "sent_http_", 10) == 0)
2550
+ {
2546
2551
  v[i].get_handler = ngx_http_variable_unknown_header_out;
2547
2552
  v[i].data = (uintptr_t) &v[i].name;
2548
2553
 
2549
2554
  continue;
2550
2555
  }
2551
2556
 
2552
- if (ngx_strncmp(v[i].name.data, "upstream_http_", 14) == 0) {
2557
+ if (v[i].name.len >= 14
2558
+ && ngx_strncmp(v[i].name.data, "upstream_http_", 14) == 0)
2559
+ {
2553
2560
  v[i].get_handler = ngx_http_upstream_header_variable;
2554
2561
  v[i].data = (uintptr_t) &v[i].name;
2555
2562
  v[i].flags = NGX_HTTP_VAR_NOCACHEABLE;
@@ -2557,14 +2564,18 @@ ngx_http_variables_init_vars(ngx_conf_t *cf)
2557
2564
  continue;
2558
2565
  }
2559
2566
 
2560
- if (ngx_strncmp(v[i].name.data, "cookie_", 7) == 0) {
2567
+ if (v[i].name.len >= 7
2568
+ && ngx_strncmp(v[i].name.data, "cookie_", 7) == 0)
2569
+ {
2561
2570
  v[i].get_handler = ngx_http_variable_cookie;
2562
2571
  v[i].data = (uintptr_t) &v[i].name;
2563
2572
 
2564
2573
  continue;
2565
2574
  }
2566
2575
 
2567
- if (ngx_strncmp(v[i].name.data, "upstream_cookie_", 16) == 0) {
2576
+ if (v[i].name.len >= 16
2577
+ && ngx_strncmp(v[i].name.data, "upstream_cookie_", 16) == 0)
2578
+ {
2568
2579
  v[i].get_handler = ngx_http_upstream_cookie_variable;
2569
2580
  v[i].data = (uintptr_t) &v[i].name;
2570
2581
  v[i].flags = NGX_HTTP_VAR_NOCACHEABLE;
@@ -2572,7 +2583,9 @@ ngx_http_variables_init_vars(ngx_conf_t *cf)
2572
2583
  continue;
2573
2584
  }
2574
2585
 
2575
- if (ngx_strncmp(v[i].name.data, "arg_", 4) == 0) {
2586
+ if (v[i].name.len >= 4
2587
+ && ngx_strncmp(v[i].name.data, "arg_", 4) == 0)
2588
+ {
2576
2589
  v[i].get_handler = ngx_http_variable_argument;
2577
2590
  v[i].data = (uintptr_t) &v[i].name;
2578
2591
  v[i].flags = NGX_HTTP_VAR_NOCACHEABLE;
@@ -174,7 +174,7 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
174
174
  *ll = NULL;
175
175
 
176
176
  ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
177
- "http write filter: l:%d f:%d s:%O", last, flush, size);
177
+ "http write filter: l:%ui f:%ui s:%O", last, flush, size);
178
178
 
179
179
  clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
180
180
 
@@ -0,0 +1,4349 @@
1
+
2
+ /*
3
+ * Copyright (C) Nginx, Inc.
4
+ * Copyright (C) Valentin V. Bartenev
5
+ */
6
+
7
+
8
+ #include <ngx_config.h>
9
+ #include <ngx_core.h>
10
+ #include <ngx_http.h>
11
+ #include <ngx_http_v2_module.h>
12
+
13
+
14
+ /* errors */
15
+ #define NGX_HTTP_V2_NO_ERROR 0x0
16
+ #define NGX_HTTP_V2_PROTOCOL_ERROR 0x1
17
+ #define NGX_HTTP_V2_INTERNAL_ERROR 0x2
18
+ #define NGX_HTTP_V2_FLOW_CTRL_ERROR 0x3
19
+ #define NGX_HTTP_V2_SETTINGS_TIMEOUT 0x4
20
+ #define NGX_HTTP_V2_STREAM_CLOSED 0x5
21
+ #define NGX_HTTP_V2_SIZE_ERROR 0x6
22
+ #define NGX_HTTP_V2_REFUSED_STREAM 0x7
23
+ #define NGX_HTTP_V2_CANCEL 0x8
24
+ #define NGX_HTTP_V2_COMP_ERROR 0x9
25
+ #define NGX_HTTP_V2_CONNECT_ERROR 0xa
26
+ #define NGX_HTTP_V2_ENHANCE_YOUR_CALM 0xb
27
+ #define NGX_HTTP_V2_INADEQUATE_SECURITY 0xc
28
+ #define NGX_HTTP_V2_HTTP_1_1_REQUIRED 0xd
29
+
30
+ /* frame sizes */
31
+ #define NGX_HTTP_V2_RST_STREAM_SIZE 4
32
+ #define NGX_HTTP_V2_PRIORITY_SIZE 5
33
+ #define NGX_HTTP_V2_PING_SIZE 8
34
+ #define NGX_HTTP_V2_GOAWAY_SIZE 8
35
+ #define NGX_HTTP_V2_WINDOW_UPDATE_SIZE 4
36
+
37
+ #define NGX_HTTP_V2_STREAM_ID_SIZE 4
38
+
39
+ #define NGX_HTTP_V2_SETTINGS_PARAM_SIZE 6
40
+
41
+ /* settings fields */
42
+ #define NGX_HTTP_V2_HEADER_TABLE_SIZE_SETTING 0x1
43
+ #define NGX_HTTP_V2_MAX_STREAMS_SETTING 0x3
44
+ #define NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING 0x4
45
+ #define NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING 0x5
46
+
47
+ #define NGX_HTTP_V2_FRAME_BUFFER_SIZE 24
48
+
49
+ #define NGX_HTTP_V2_DEFAULT_FRAME_SIZE (1 << 14)
50
+
51
+ #define NGX_HTTP_V2_MAX_WINDOW ((1U << 31) - 1)
52
+ #define NGX_HTTP_V2_DEFAULT_WINDOW 65535
53
+
54
+ #define NGX_HTTP_V2_INITIAL_WINDOW 0
55
+
56
+ #define NGX_HTTP_V2_ROOT (void *) -1
57
+
58
+
59
+ static void ngx_http_v2_read_handler(ngx_event_t *rev);
60
+ static void ngx_http_v2_write_handler(ngx_event_t *wev);
61
+ static void ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c);
62
+
63
+ static u_char *ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c,
64
+ u_char *pos, u_char *end);
65
+ static u_char *ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c,
66
+ u_char *pos, u_char *end);
67
+ static u_char *ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c,
68
+ u_char *pos, u_char *end);
69
+ static u_char *ngx_http_v2_state_head(ngx_http_v2_connection_t *h2c,
70
+ u_char *pos, u_char *end);
71
+ static u_char *ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c,
72
+ u_char *pos, u_char *end);
73
+ static u_char *ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c,
74
+ u_char *pos, u_char *end);
75
+ static u_char *ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c,
76
+ u_char *pos, u_char *end);
77
+ static u_char *ngx_http_v2_state_header_block(ngx_http_v2_connection_t *h2c,
78
+ u_char *pos, u_char *end);
79
+ static u_char *ngx_http_v2_state_field_len(ngx_http_v2_connection_t *h2c,
80
+ u_char *pos, u_char *end);
81
+ static u_char *ngx_http_v2_state_field_huff(ngx_http_v2_connection_t *h2c,
82
+ u_char *pos, u_char *end);
83
+ static u_char *ngx_http_v2_state_field_raw(ngx_http_v2_connection_t *h2c,
84
+ u_char *pos, u_char *end);
85
+ static u_char *ngx_http_v2_state_field_skip(ngx_http_v2_connection_t *h2c,
86
+ u_char *pos, u_char *end);
87
+ static u_char *ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c,
88
+ u_char *pos, u_char *end);
89
+ static u_char *ngx_http_v2_state_header_complete(ngx_http_v2_connection_t *h2c,
90
+ u_char *pos, u_char *end);
91
+ static u_char *ngx_http_v2_handle_continuation(ngx_http_v2_connection_t *h2c,
92
+ u_char *pos, u_char *end, ngx_http_v2_handler_pt handler);
93
+ static u_char *ngx_http_v2_state_priority(ngx_http_v2_connection_t *h2c,
94
+ u_char *pos, u_char *end);
95
+ static u_char *ngx_http_v2_state_rst_stream(ngx_http_v2_connection_t *h2c,
96
+ u_char *pos, u_char *end);
97
+ static u_char *ngx_http_v2_state_settings(ngx_http_v2_connection_t *h2c,
98
+ u_char *pos, u_char *end);
99
+ static u_char *ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c,
100
+ u_char *pos, u_char *end);
101
+ static u_char *ngx_http_v2_state_push_promise(ngx_http_v2_connection_t *h2c,
102
+ u_char *pos, u_char *end);
103
+ static u_char *ngx_http_v2_state_ping(ngx_http_v2_connection_t *h2c,
104
+ u_char *pos, u_char *end);
105
+ static u_char *ngx_http_v2_state_goaway(ngx_http_v2_connection_t *h2c,
106
+ u_char *pos, u_char *end);
107
+ static u_char *ngx_http_v2_state_window_update(ngx_http_v2_connection_t *h2c,
108
+ u_char *pos, u_char *end);
109
+ static u_char *ngx_http_v2_state_continuation(ngx_http_v2_connection_t *h2c,
110
+ u_char *pos, u_char *end);
111
+ static u_char *ngx_http_v2_state_complete(ngx_http_v2_connection_t *h2c,
112
+ u_char *pos, u_char *end);
113
+ static u_char *ngx_http_v2_state_skip_padded(ngx_http_v2_connection_t *h2c,
114
+ u_char *pos, u_char *end);
115
+ static u_char *ngx_http_v2_state_skip(ngx_http_v2_connection_t *h2c,
116
+ u_char *pos, u_char *end);
117
+ static u_char *ngx_http_v2_state_save(ngx_http_v2_connection_t *h2c,
118
+ u_char *pos, u_char *end, ngx_http_v2_handler_pt handler);
119
+ static u_char *ngx_http_v2_state_headers_save(ngx_http_v2_connection_t *h2c,
120
+ u_char *pos, u_char *end, ngx_http_v2_handler_pt handler);
121
+ static u_char *ngx_http_v2_connection_error(ngx_http_v2_connection_t *h2c,
122
+ ngx_uint_t err);
123
+
124
+ static ngx_int_t ngx_http_v2_parse_int(ngx_http_v2_connection_t *h2c,
125
+ u_char **pos, u_char *end, ngx_uint_t prefix);
126
+
127
+ static ngx_http_v2_stream_t *ngx_http_v2_create_stream(
128
+ ngx_http_v2_connection_t *h2c);
129
+ static ngx_http_v2_node_t *ngx_http_v2_get_node_by_id(
130
+ ngx_http_v2_connection_t *h2c, ngx_uint_t sid, ngx_uint_t alloc);
131
+ static ngx_http_v2_node_t *ngx_http_v2_get_closed_node(
132
+ ngx_http_v2_connection_t *h2c);
133
+ #define ngx_http_v2_index_size(h2scf) (h2scf->streams_index_mask + 1)
134
+ #define ngx_http_v2_index(h2scf, sid) ((sid >> 1) & h2scf->streams_index_mask)
135
+
136
+ static ngx_int_t ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c,
137
+ ngx_uint_t ack);
138
+ static ngx_int_t ngx_http_v2_settings_frame_handler(
139
+ ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame);
140
+ static ngx_int_t ngx_http_v2_send_window_update(ngx_http_v2_connection_t *h2c,
141
+ ngx_uint_t sid, size_t window);
142
+ static ngx_int_t ngx_http_v2_send_rst_stream(ngx_http_v2_connection_t *h2c,
143
+ ngx_uint_t sid, ngx_uint_t status);
144
+
145
+ static ngx_http_v2_out_frame_t *ngx_http_v2_get_frame(
146
+ ngx_http_v2_connection_t *h2c, size_t length, ngx_uint_t type,
147
+ u_char flags, ngx_uint_t sid);
148
+ static ngx_int_t ngx_http_v2_frame_handler(ngx_http_v2_connection_t *h2c,
149
+ ngx_http_v2_out_frame_t *frame);
150
+
151
+ static ngx_int_t ngx_http_v2_validate_header(ngx_http_request_t *r,
152
+ ngx_http_v2_header_t *header);
153
+ static ngx_int_t ngx_http_v2_pseudo_header(ngx_http_request_t *r,
154
+ ngx_http_v2_header_t *header);
155
+ static ngx_int_t ngx_http_v2_parse_path(ngx_http_request_t *r,
156
+ ngx_http_v2_header_t *header);
157
+ static ngx_int_t ngx_http_v2_parse_method(ngx_http_request_t *r,
158
+ ngx_http_v2_header_t *header);
159
+ static ngx_int_t ngx_http_v2_parse_scheme(ngx_http_request_t *r,
160
+ ngx_http_v2_header_t *header);
161
+ static ngx_int_t ngx_http_v2_parse_authority(ngx_http_request_t *r,
162
+ ngx_http_v2_header_t *header);
163
+ static ngx_int_t ngx_http_v2_construct_request_line(ngx_http_request_t *r);
164
+ static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r,
165
+ ngx_http_v2_header_t *header);
166
+ static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r);
167
+ static void ngx_http_v2_run_request(ngx_http_request_t *r);
168
+ static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r,
169
+ u_char *pos, size_t size, ngx_uint_t last);
170
+ static ngx_int_t ngx_http_v2_filter_request_body(ngx_http_request_t *r);
171
+ static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r);
172
+
173
+ static ngx_int_t ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c,
174
+ ngx_http_v2_stream_t *stream, ngx_uint_t status);
175
+ static void ngx_http_v2_close_stream_handler(ngx_event_t *ev);
176
+ static void ngx_http_v2_handle_connection_handler(ngx_event_t *rev);
177
+ static void ngx_http_v2_idle_handler(ngx_event_t *rev);
178
+ static void ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c,
179
+ ngx_uint_t status);
180
+
181
+ static ngx_int_t ngx_http_v2_adjust_windows(ngx_http_v2_connection_t *h2c,
182
+ ssize_t delta);
183
+ static void ngx_http_v2_set_dependency(ngx_http_v2_connection_t *h2c,
184
+ ngx_http_v2_node_t *node, ngx_uint_t depend, ngx_uint_t exclusive);
185
+ static void ngx_http_v2_node_children_update(ngx_http_v2_node_t *node);
186
+
187
+ static void ngx_http_v2_pool_cleanup(void *data);
188
+
189
+
190
+ static ngx_http_v2_handler_pt ngx_http_v2_frame_states[] = {
191
+ ngx_http_v2_state_data,
192
+ ngx_http_v2_state_headers,
193
+ ngx_http_v2_state_priority,
194
+ ngx_http_v2_state_rst_stream,
195
+ ngx_http_v2_state_settings,
196
+ ngx_http_v2_state_push_promise,
197
+ ngx_http_v2_state_ping,
198
+ ngx_http_v2_state_goaway,
199
+ ngx_http_v2_state_window_update,
200
+ ngx_http_v2_state_continuation
201
+ };
202
+
203
+ #define NGX_HTTP_V2_FRAME_STATES \
204
+ (sizeof(ngx_http_v2_frame_states) / sizeof(ngx_http_v2_handler_pt))
205
+
206
+
207
+ void
208
+ ngx_http_v2_init(ngx_event_t *rev)
209
+ {
210
+ ngx_connection_t *c;
211
+ ngx_pool_cleanup_t *cln;
212
+ ngx_http_connection_t *hc;
213
+ ngx_http_v2_srv_conf_t *h2scf;
214
+ ngx_http_v2_main_conf_t *h2mcf;
215
+ ngx_http_v2_connection_t *h2c;
216
+
217
+ c = rev->data;
218
+ hc = c->data;
219
+
220
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "init http2 connection");
221
+
222
+ c->log->action = "processing HTTP/2 connection";
223
+
224
+ h2mcf = ngx_http_get_module_main_conf(hc->conf_ctx, ngx_http_v2_module);
225
+
226
+ if (h2mcf->recv_buffer == NULL) {
227
+ h2mcf->recv_buffer = ngx_palloc(ngx_cycle->pool,
228
+ h2mcf->recv_buffer_size);
229
+ if (h2mcf->recv_buffer == NULL) {
230
+ ngx_http_close_connection(c);
231
+ return;
232
+ }
233
+ }
234
+
235
+ h2c = ngx_pcalloc(c->pool, sizeof(ngx_http_v2_connection_t));
236
+ if (h2c == NULL) {
237
+ ngx_http_close_connection(c);
238
+ return;
239
+ }
240
+
241
+ h2c->connection = c;
242
+ h2c->http_connection = hc;
243
+
244
+ h2c->send_window = NGX_HTTP_V2_DEFAULT_WINDOW;
245
+ h2c->recv_window = NGX_HTTP_V2_MAX_WINDOW;
246
+
247
+ h2c->init_window = NGX_HTTP_V2_DEFAULT_WINDOW;
248
+
249
+ h2c->frame_size = NGX_HTTP_V2_DEFAULT_FRAME_SIZE;
250
+
251
+ h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module);
252
+
253
+ h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log);
254
+ if (h2c->pool == NULL) {
255
+ ngx_http_close_connection(c);
256
+ return;
257
+ }
258
+
259
+ cln = ngx_pool_cleanup_add(c->pool, 0);
260
+ if (cln == NULL) {
261
+ ngx_http_close_connection(c);
262
+ return;
263
+ }
264
+
265
+ cln->handler = ngx_http_v2_pool_cleanup;
266
+ cln->data = h2c;
267
+
268
+ h2c->streams_index = ngx_pcalloc(c->pool, ngx_http_v2_index_size(h2scf)
269
+ * sizeof(ngx_http_v2_node_t *));
270
+ if (h2c->streams_index == NULL) {
271
+ ngx_http_close_connection(c);
272
+ return;
273
+ }
274
+
275
+ if (ngx_http_v2_send_settings(h2c, 0) == NGX_ERROR) {
276
+ ngx_http_close_connection(c);
277
+ return;
278
+ }
279
+
280
+ if (ngx_http_v2_send_window_update(h2c, 0, NGX_HTTP_V2_MAX_WINDOW
281
+ - NGX_HTTP_V2_DEFAULT_WINDOW)
282
+ == NGX_ERROR)
283
+ {
284
+ ngx_http_close_connection(c);
285
+ return;
286
+ }
287
+
288
+ h2c->state.handler = hc->proxy_protocol ? ngx_http_v2_state_proxy_protocol
289
+ : ngx_http_v2_state_preface;
290
+
291
+ ngx_queue_init(&h2c->waiting);
292
+ ngx_queue_init(&h2c->posted);
293
+ ngx_queue_init(&h2c->dependencies);
294
+ ngx_queue_init(&h2c->closed);
295
+
296
+ c->data = h2c;
297
+
298
+ rev->handler = ngx_http_v2_read_handler;
299
+ c->write->handler = ngx_http_v2_write_handler;
300
+
301
+ ngx_http_v2_read_handler(rev);
302
+ }
303
+
304
+
305
+ static void
306
+ ngx_http_v2_read_handler(ngx_event_t *rev)
307
+ {
308
+ u_char *p, *end;
309
+ size_t available;
310
+ ssize_t n;
311
+ ngx_connection_t *c;
312
+ ngx_http_v2_main_conf_t *h2mcf;
313
+ ngx_http_v2_connection_t *h2c;
314
+
315
+ c = rev->data;
316
+ h2c = c->data;
317
+
318
+ if (rev->timedout) {
319
+ ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
320
+ ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
321
+ return;
322
+ }
323
+
324
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http2 read handler");
325
+
326
+ h2c->blocked = 1;
327
+
328
+ h2mcf = ngx_http_get_module_main_conf(h2c->http_connection->conf_ctx,
329
+ ngx_http_v2_module);
330
+
331
+ available = h2mcf->recv_buffer_size - 2 * NGX_HTTP_V2_STATE_BUFFER_SIZE;
332
+
333
+ do {
334
+ p = h2mcf->recv_buffer;
335
+
336
+ ngx_memcpy(p, h2c->state.buffer, NGX_HTTP_V2_STATE_BUFFER_SIZE);
337
+ end = p + h2c->state.buffer_used;
338
+
339
+ n = c->recv(c, end, available);
340
+
341
+ if (n == NGX_AGAIN) {
342
+ break;
343
+ }
344
+
345
+ if (n == 0 && (h2c->state.incomplete || h2c->processing)) {
346
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
347
+ "client prematurely closed connection");
348
+ }
349
+
350
+ if (n == 0 || n == NGX_ERROR) {
351
+ c->error = 1;
352
+ ngx_http_v2_finalize_connection(h2c, 0);
353
+ return;
354
+ }
355
+
356
+ end += n;
357
+
358
+ h2c->state.buffer_used = 0;
359
+ h2c->state.incomplete = 0;
360
+
361
+ do {
362
+ p = h2c->state.handler(h2c, p, end);
363
+
364
+ if (p == NULL) {
365
+ return;
366
+ }
367
+
368
+ } while (p != end);
369
+
370
+ } while (rev->ready);
371
+
372
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
373
+ ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
374
+ return;
375
+ }
376
+
377
+ if (h2c->last_out && ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) {
378
+ ngx_http_v2_finalize_connection(h2c, 0);
379
+ return;
380
+ }
381
+
382
+ h2c->blocked = 0;
383
+
384
+ if (h2c->processing) {
385
+ if (rev->timer_set) {
386
+ ngx_del_timer(rev);
387
+ }
388
+
389
+ return;
390
+ }
391
+
392
+ ngx_http_v2_handle_connection(h2c);
393
+ }
394
+
395
+
396
+ static void
397
+ ngx_http_v2_write_handler(ngx_event_t *wev)
398
+ {
399
+ ngx_int_t rc;
400
+ ngx_queue_t *q;
401
+ ngx_connection_t *c;
402
+ ngx_http_v2_stream_t *stream;
403
+ ngx_http_v2_connection_t *h2c;
404
+
405
+ c = wev->data;
406
+ h2c = c->data;
407
+
408
+ if (wev->timedout) {
409
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
410
+ "http2 write event timed out");
411
+ c->error = 1;
412
+ ngx_http_v2_finalize_connection(h2c, 0);
413
+ return;
414
+ }
415
+
416
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http2 write handler");
417
+
418
+ h2c->blocked = 1;
419
+
420
+ rc = ngx_http_v2_send_output_queue(h2c);
421
+
422
+ if (rc == NGX_ERROR) {
423
+ ngx_http_v2_finalize_connection(h2c, 0);
424
+ return;
425
+ }
426
+
427
+ while (!ngx_queue_empty(&h2c->posted)) {
428
+ q = ngx_queue_head(&h2c->posted);
429
+
430
+ ngx_queue_remove(q);
431
+
432
+ stream = ngx_queue_data(q, ngx_http_v2_stream_t, queue);
433
+
434
+ stream->handled = 0;
435
+
436
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
437
+ "run http2 stream %ui", stream->node->id);
438
+
439
+ wev = stream->request->connection->write;
440
+
441
+ wev->active = 0;
442
+ wev->ready = 1;
443
+
444
+ wev->handler(wev);
445
+ }
446
+
447
+ h2c->blocked = 0;
448
+
449
+ if (rc == NGX_AGAIN) {
450
+ return;
451
+ }
452
+
453
+ ngx_http_v2_handle_connection(h2c);
454
+ }
455
+
456
+
457
+ ngx_int_t
458
+ ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c)
459
+ {
460
+ int tcp_nodelay;
461
+ ngx_chain_t *cl;
462
+ ngx_event_t *wev;
463
+ ngx_connection_t *c;
464
+ ngx_http_v2_out_frame_t *out, *frame, *fn;
465
+ ngx_http_core_loc_conf_t *clcf;
466
+
467
+ c = h2c->connection;
468
+
469
+ if (c->error) {
470
+ return NGX_ERROR;
471
+ }
472
+
473
+ wev = c->write;
474
+
475
+ if (!wev->ready) {
476
+ return NGX_OK;
477
+ }
478
+
479
+ cl = NULL;
480
+ out = NULL;
481
+
482
+ for (frame = h2c->last_out; frame; frame = fn) {
483
+ frame->last->next = cl;
484
+ cl = frame->first;
485
+
486
+ fn = frame->next;
487
+ frame->next = out;
488
+ out = frame;
489
+
490
+ ngx_log_debug4(NGX_LOG_DEBUG_HTTP, c->log, 0,
491
+ "http2 frame out: %p sid:%ui bl:%d len:%uz",
492
+ out, out->stream ? out->stream->node->id : 0,
493
+ out->blocked, out->length);
494
+ }
495
+
496
+ cl = c->send_chain(c, cl, 0);
497
+
498
+ if (cl == NGX_CHAIN_ERROR) {
499
+ goto error;
500
+ }
501
+
502
+ clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx,
503
+ ngx_http_core_module);
504
+
505
+ if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
506
+ goto error;
507
+ }
508
+
509
+ if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
510
+ if (ngx_tcp_push(c->fd) == -1) {
511
+ ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
512
+ goto error;
513
+ }
514
+
515
+ c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
516
+ tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
517
+
518
+ } else {
519
+ tcp_nodelay = 1;
520
+ }
521
+
522
+ if (tcp_nodelay
523
+ && clcf->tcp_nodelay
524
+ && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
525
+ {
526
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
527
+
528
+ if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
529
+ (const void *) &tcp_nodelay, sizeof(int))
530
+ == -1)
531
+ {
532
+ #if (NGX_SOLARIS)
533
+ /* Solaris returns EINVAL if a socket has been shut down */
534
+ c->log_error = NGX_ERROR_IGNORE_EINVAL;
535
+ #endif
536
+
537
+ ngx_connection_error(c, ngx_socket_errno,
538
+ "setsockopt(TCP_NODELAY) failed");
539
+
540
+ c->log_error = NGX_ERROR_INFO;
541
+ goto error;
542
+ }
543
+
544
+ c->tcp_nodelay = NGX_TCP_NODELAY_SET;
545
+ }
546
+
547
+ if (cl) {
548
+ ngx_add_timer(wev, clcf->send_timeout);
549
+
550
+ } else {
551
+ if (wev->timer_set) {
552
+ ngx_del_timer(wev);
553
+ }
554
+ }
555
+
556
+ for ( /* void */ ; out; out = fn) {
557
+ fn = out->next;
558
+
559
+ if (out->handler(h2c, out) != NGX_OK) {
560
+ out->blocked = 1;
561
+ break;
562
+ }
563
+
564
+ ngx_log_debug4(NGX_LOG_DEBUG_HTTP, c->log, 0,
565
+ "http2 frame sent: %p sid:%ui bl:%d len:%uz",
566
+ out, out->stream ? out->stream->node->id : 0,
567
+ out->blocked, out->length);
568
+ }
569
+
570
+ frame = NULL;
571
+
572
+ for ( /* void */ ; out; out = fn) {
573
+ fn = out->next;
574
+ out->next = frame;
575
+ frame = out;
576
+ }
577
+
578
+ h2c->last_out = frame;
579
+
580
+ return NGX_OK;
581
+
582
+ error:
583
+
584
+ c->error = 1;
585
+
586
+ if (!h2c->blocked) {
587
+ ngx_post_event(wev, &ngx_posted_events);
588
+ }
589
+
590
+ return NGX_ERROR;
591
+ }
592
+
593
+
594
+ static void
595
+ ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c)
596
+ {
597
+ ngx_connection_t *c;
598
+ ngx_http_v2_srv_conf_t *h2scf;
599
+
600
+ if (h2c->last_out || h2c->processing) {
601
+ return;
602
+ }
603
+
604
+ c = h2c->connection;
605
+
606
+ if (c->error) {
607
+ ngx_http_close_connection(c);
608
+ return;
609
+ }
610
+
611
+ if (c->buffered) {
612
+ return;
613
+ }
614
+
615
+ h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
616
+ ngx_http_v2_module);
617
+ if (h2c->state.incomplete) {
618
+ ngx_add_timer(c->read, h2scf->recv_timeout);
619
+ return;
620
+ }
621
+
622
+ if (ngx_terminate || ngx_exiting) {
623
+ ngx_http_close_connection(c);
624
+ return;
625
+ }
626
+
627
+ ngx_destroy_pool(h2c->pool);
628
+
629
+ h2c->pool = NULL;
630
+ h2c->free_frames = NULL;
631
+ h2c->free_fake_connections = NULL;
632
+
633
+ #if (NGX_HTTP_SSL)
634
+ if (c->ssl) {
635
+ ngx_ssl_free_buffer(c);
636
+ }
637
+ #endif
638
+
639
+ c->destroyed = 1;
640
+ c->idle = 1;
641
+ ngx_reusable_connection(c, 1);
642
+
643
+ c->write->handler = ngx_http_empty_handler;
644
+ c->read->handler = ngx_http_v2_idle_handler;
645
+
646
+ if (c->write->timer_set) {
647
+ ngx_del_timer(c->write);
648
+ }
649
+
650
+ ngx_add_timer(c->read, h2scf->idle_timeout);
651
+ }
652
+
653
+
654
+ static u_char *
655
+ ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, u_char *pos,
656
+ u_char *end)
657
+ {
658
+ ngx_log_t *log;
659
+
660
+ log = h2c->connection->log;
661
+ log->action = "reading PROXY protocol";
662
+
663
+ pos = ngx_proxy_protocol_read(h2c->connection, pos, end);
664
+
665
+ log->action = "processing HTTP/2 connection";
666
+
667
+ if (pos == NULL) {
668
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
669
+ }
670
+
671
+ return ngx_http_v2_state_preface(h2c, pos, end);
672
+ }
673
+
674
+
675
+ static u_char *
676
+ ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, u_char *pos,
677
+ u_char *end)
678
+ {
679
+ static const u_char preface[] = "PRI * HTTP/2.0\r\n";
680
+
681
+ if ((size_t) (end - pos) < sizeof(preface) - 1) {
682
+ return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_preface);
683
+ }
684
+
685
+ if (ngx_memcmp(pos, preface, sizeof(preface) - 1) != 0) {
686
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
687
+ "invalid http2 connection preface \"%*s\"",
688
+ sizeof(preface) - 1, pos);
689
+
690
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
691
+ }
692
+
693
+ return ngx_http_v2_state_preface_end(h2c, pos + sizeof(preface) - 1, end);
694
+ }
695
+
696
+
697
+ static u_char *
698
+ ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, u_char *pos,
699
+ u_char *end)
700
+ {
701
+ static const u_char preface[] = "\r\nSM\r\n\r\n";
702
+
703
+ if ((size_t) (end - pos) < sizeof(preface) - 1) {
704
+ return ngx_http_v2_state_save(h2c, pos, end,
705
+ ngx_http_v2_state_preface_end);
706
+ }
707
+
708
+ if (ngx_memcmp(pos, preface, sizeof(preface) - 1) != 0) {
709
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
710
+ "invalid http2 connection preface \"%*s\"",
711
+ sizeof(preface) - 1, pos);
712
+
713
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
714
+ }
715
+
716
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
717
+ "http2 preface verified");
718
+
719
+ return ngx_http_v2_state_head(h2c, pos + sizeof(preface) - 1, end);
720
+ }
721
+
722
+
723
+ static u_char *
724
+ ngx_http_v2_state_head(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end)
725
+ {
726
+ uint32_t head;
727
+ ngx_uint_t type;
728
+
729
+ if (end - pos < NGX_HTTP_V2_FRAME_HEADER_SIZE) {
730
+ return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_head);
731
+ }
732
+
733
+ head = ngx_http_v2_parse_uint32(pos);
734
+
735
+ h2c->state.length = ngx_http_v2_parse_length(head);
736
+ h2c->state.flags = pos[4];
737
+
738
+ h2c->state.sid = ngx_http_v2_parse_sid(&pos[5]);
739
+
740
+ pos += NGX_HTTP_V2_FRAME_HEADER_SIZE;
741
+
742
+ type = ngx_http_v2_parse_type(head);
743
+
744
+ ngx_log_debug4(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
745
+ "process http2 frame type:%ui f:%Xd l:%uz sid:%ui",
746
+ type, h2c->state.flags, h2c->state.length, h2c->state.sid);
747
+
748
+ if (type >= NGX_HTTP_V2_FRAME_STATES) {
749
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
750
+ "http2 frame with unknown type %ui", type);
751
+ return ngx_http_v2_state_skip(h2c, pos, end);
752
+ }
753
+
754
+ return ngx_http_v2_frame_states[type](h2c, pos, end);
755
+ }
756
+
757
+
758
+ static u_char *
759
+ ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end)
760
+ {
761
+ ngx_http_v2_node_t *node;
762
+ ngx_http_v2_stream_t *stream;
763
+
764
+ if (h2c->state.flags & NGX_HTTP_V2_PADDED_FLAG) {
765
+
766
+ if (h2c->state.length == 0) {
767
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
768
+ "client sent padded DATA frame "
769
+ "with incorrect length: 0");
770
+
771
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
772
+ }
773
+
774
+ if (end - pos == 0) {
775
+ return ngx_http_v2_state_save(h2c, pos, end,
776
+ ngx_http_v2_state_data);
777
+ }
778
+
779
+ h2c->state.padding = *pos++;
780
+ h2c->state.length--;
781
+
782
+ if (h2c->state.padding > h2c->state.length) {
783
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
784
+ "client sent padded DATA frame "
785
+ "with incorrect length: %uz, padding: %uz",
786
+ h2c->state.length, h2c->state.padding);
787
+
788
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
789
+ }
790
+
791
+ h2c->state.length -= h2c->state.padding;
792
+ }
793
+
794
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
795
+ "http2 DATA frame");
796
+
797
+ if (h2c->state.length > h2c->recv_window) {
798
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
799
+ "client violated connection flow control: "
800
+ "received DATA frame length %uz, available window %uz",
801
+ h2c->state.length, h2c->recv_window);
802
+
803
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_FLOW_CTRL_ERROR);
804
+ }
805
+
806
+ h2c->recv_window -= h2c->state.length;
807
+
808
+ if (h2c->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4) {
809
+
810
+ if (ngx_http_v2_send_window_update(h2c, 0, NGX_HTTP_V2_MAX_WINDOW
811
+ - h2c->recv_window)
812
+ == NGX_ERROR)
813
+ {
814
+ return ngx_http_v2_connection_error(h2c,
815
+ NGX_HTTP_V2_INTERNAL_ERROR);
816
+ }
817
+
818
+ h2c->recv_window = NGX_HTTP_V2_MAX_WINDOW;
819
+ }
820
+
821
+ node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 0);
822
+
823
+ if (node == NULL || node->stream == NULL) {
824
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
825
+ "unknown http2 stream");
826
+
827
+ return ngx_http_v2_state_skip_padded(h2c, pos, end);
828
+ }
829
+
830
+ stream = node->stream;
831
+
832
+ if (h2c->state.length > stream->recv_window) {
833
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
834
+ "client violated flow control for stream %ui: "
835
+ "received DATA frame length %uz, available window %uz",
836
+ node->id, h2c->state.length, stream->recv_window);
837
+
838
+ if (ngx_http_v2_terminate_stream(h2c, stream,
839
+ NGX_HTTP_V2_FLOW_CTRL_ERROR)
840
+ == NGX_ERROR)
841
+ {
842
+ return ngx_http_v2_connection_error(h2c,
843
+ NGX_HTTP_V2_INTERNAL_ERROR);
844
+ }
845
+
846
+ return ngx_http_v2_state_skip_padded(h2c, pos, end);
847
+ }
848
+
849
+ stream->recv_window -= h2c->state.length;
850
+
851
+ if (stream->no_flow_control
852
+ && stream->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4)
853
+ {
854
+ if (ngx_http_v2_send_window_update(h2c, node->id,
855
+ NGX_HTTP_V2_MAX_WINDOW
856
+ - stream->recv_window)
857
+ == NGX_ERROR)
858
+ {
859
+ return ngx_http_v2_connection_error(h2c,
860
+ NGX_HTTP_V2_INTERNAL_ERROR);
861
+ }
862
+
863
+ stream->recv_window = NGX_HTTP_V2_MAX_WINDOW;
864
+ }
865
+
866
+ if (stream->in_closed) {
867
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
868
+ "client sent DATA frame for half-closed stream %ui",
869
+ node->id);
870
+
871
+ if (ngx_http_v2_terminate_stream(h2c, stream,
872
+ NGX_HTTP_V2_STREAM_CLOSED)
873
+ == NGX_ERROR)
874
+ {
875
+ return ngx_http_v2_connection_error(h2c,
876
+ NGX_HTTP_V2_INTERNAL_ERROR);
877
+ }
878
+
879
+ return ngx_http_v2_state_skip_padded(h2c, pos, end);
880
+ }
881
+
882
+ stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG;
883
+
884
+ h2c->state.stream = stream;
885
+
886
+ return ngx_http_v2_state_read_data(h2c, pos, end);
887
+ }
888
+
889
+
890
+ static u_char *
891
+ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos,
892
+ u_char *end)
893
+ {
894
+ size_t size;
895
+ ngx_int_t rc;
896
+ ngx_uint_t last;
897
+ ngx_http_v2_stream_t *stream;
898
+
899
+ stream = h2c->state.stream;
900
+
901
+ if (stream == NULL) {
902
+ return ngx_http_v2_state_skip_padded(h2c, pos, end);
903
+ }
904
+
905
+ if (stream->skip_data) {
906
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
907
+ "skipping http2 DATA frame");
908
+
909
+ return ngx_http_v2_state_skip_padded(h2c, pos, end);
910
+ }
911
+
912
+ size = end - pos;
913
+
914
+ if (size >= h2c->state.length) {
915
+ size = h2c->state.length;
916
+ last = stream->in_closed;
917
+
918
+ } else {
919
+ last = 0;
920
+ }
921
+
922
+ rc = ngx_http_v2_process_request_body(stream->request, pos, size, last);
923
+
924
+ if (rc != NGX_OK) {
925
+ stream->skip_data = 1;
926
+ ngx_http_finalize_request(stream->request, rc);
927
+ }
928
+
929
+ pos += size;
930
+ h2c->state.length -= size;
931
+
932
+ if (h2c->state.length) {
933
+ return ngx_http_v2_state_save(h2c, pos, end,
934
+ ngx_http_v2_state_read_data);
935
+ }
936
+
937
+ if (h2c->state.padding) {
938
+ return ngx_http_v2_state_skip_padded(h2c, pos, end);
939
+ }
940
+
941
+ return ngx_http_v2_state_complete(h2c, pos, end);
942
+ }
943
+
944
+
945
+ static u_char *
946
+ ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos,
947
+ u_char *end)
948
+ {
949
+ size_t size;
950
+ ngx_uint_t padded, priority, depend, dependency, excl, weight;
951
+ ngx_uint_t status;
952
+ ngx_http_v2_node_t *node;
953
+ ngx_http_v2_stream_t *stream;
954
+ ngx_http_v2_srv_conf_t *h2scf;
955
+
956
+ padded = h2c->state.flags & NGX_HTTP_V2_PADDED_FLAG;
957
+ priority = h2c->state.flags & NGX_HTTP_V2_PRIORITY_FLAG;
958
+
959
+ size = 0;
960
+
961
+ if (padded) {
962
+ size++;
963
+ }
964
+
965
+ if (priority) {
966
+ size += sizeof(uint32_t) + 1;
967
+ }
968
+
969
+ if (h2c->state.length < size) {
970
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
971
+ "client sent HEADERS frame with incorrect length %uz",
972
+ h2c->state.length);
973
+
974
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
975
+ }
976
+
977
+ if (h2c->state.length == size) {
978
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
979
+ "client sent HEADERS frame with empty header block");
980
+
981
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
982
+ }
983
+
984
+ if ((size_t) (end - pos) < size) {
985
+ return ngx_http_v2_state_save(h2c, pos, end,
986
+ ngx_http_v2_state_headers);
987
+ }
988
+
989
+ h2c->state.length -= size;
990
+
991
+ if (padded) {
992
+ h2c->state.padding = *pos++;
993
+
994
+ if (h2c->state.padding > h2c->state.length) {
995
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
996
+ "client sent padded HEADERS frame "
997
+ "with incorrect length: %uz, padding: %uz",
998
+ h2c->state.length, h2c->state.padding);
999
+
1000
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
1001
+ }
1002
+
1003
+ h2c->state.length -= h2c->state.padding;
1004
+ }
1005
+
1006
+ depend = 0;
1007
+ excl = 0;
1008
+ weight = 16;
1009
+
1010
+ if (priority) {
1011
+ dependency = ngx_http_v2_parse_uint32(pos);
1012
+
1013
+ depend = dependency & 0x7fffffff;
1014
+ excl = dependency >> 31;
1015
+ weight = pos[4] + 1;
1016
+
1017
+ pos += sizeof(uint32_t) + 1;
1018
+ }
1019
+
1020
+ ngx_log_debug4(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
1021
+ "http2 HEADERS frame sid:%ui on %ui excl:%ui weight:%ui",
1022
+ h2c->state.sid, depend, excl, weight);
1023
+
1024
+ if (h2c->state.sid % 2 == 0 || h2c->state.sid <= h2c->last_sid) {
1025
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1026
+ "client sent HEADERS frame with incorrect identifier "
1027
+ "%ui, the last was %ui", h2c->state.sid, h2c->last_sid);
1028
+
1029
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
1030
+ }
1031
+
1032
+ h2c->last_sid = h2c->state.sid;
1033
+
1034
+ h2c->state.pool = ngx_create_pool(1024, h2c->connection->log);
1035
+ if (h2c->state.pool == NULL) {
1036
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
1037
+ }
1038
+
1039
+ if (depend == h2c->state.sid) {
1040
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1041
+ "client sent HEADERS frame for stream %ui "
1042
+ "with incorrect dependency", h2c->state.sid);
1043
+
1044
+ status = NGX_HTTP_V2_PROTOCOL_ERROR;
1045
+ goto rst_stream;
1046
+ }
1047
+
1048
+ h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
1049
+ ngx_http_v2_module);
1050
+
1051
+ h2c->state.header_limit = h2scf->max_header_size;
1052
+
1053
+ if (h2c->processing >= h2scf->concurrent_streams) {
1054
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1055
+ "concurrent streams exceeded %ui", h2c->processing);
1056
+
1057
+ status = NGX_HTTP_V2_REFUSED_STREAM;
1058
+ goto rst_stream;
1059
+ }
1060
+
1061
+ if (!h2c->settings_ack && !(h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG))
1062
+ {
1063
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1064
+ "client sent stream with data "
1065
+ "before settings were acknowledged");
1066
+
1067
+ status = NGX_HTTP_V2_REFUSED_STREAM;
1068
+ goto rst_stream;
1069
+ }
1070
+
1071
+ node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 1);
1072
+
1073
+ if (node == NULL) {
1074
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
1075
+ }
1076
+
1077
+ if (node->parent) {
1078
+ ngx_queue_remove(&node->reuse);
1079
+ h2c->closed_nodes--;
1080
+ }
1081
+
1082
+ stream = ngx_http_v2_create_stream(h2c);
1083
+ if (stream == NULL) {
1084
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
1085
+ }
1086
+
1087
+ h2c->state.stream = stream;
1088
+
1089
+ stream->pool = h2c->state.pool;
1090
+ h2c->state.keep_pool = 1;
1091
+
1092
+ stream->request->request_length = h2c->state.length;
1093
+
1094
+ stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG;
1095
+ stream->node = node;
1096
+
1097
+ node->stream = stream;
1098
+
1099
+ if (priority || node->parent == NULL) {
1100
+ node->weight = weight;
1101
+ ngx_http_v2_set_dependency(h2c, node, depend, excl);
1102
+ }
1103
+
1104
+ return ngx_http_v2_state_header_block(h2c, pos, end);
1105
+
1106
+ rst_stream:
1107
+
1108
+ if (ngx_http_v2_send_rst_stream(h2c, h2c->state.sid, status) != NGX_OK) {
1109
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
1110
+ }
1111
+
1112
+ return ngx_http_v2_state_header_block(h2c, pos, end);
1113
+ }
1114
+
1115
+
1116
+ static u_char *
1117
+ ngx_http_v2_state_header_block(ngx_http_v2_connection_t *h2c, u_char *pos,
1118
+ u_char *end)
1119
+ {
1120
+ u_char ch;
1121
+ ngx_int_t value;
1122
+ ngx_uint_t indexed, size_update, prefix;
1123
+
1124
+ if (end - pos < 1) {
1125
+ return ngx_http_v2_state_headers_save(h2c, pos, end,
1126
+ ngx_http_v2_state_header_block);
1127
+ }
1128
+
1129
+ if (!(h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG)
1130
+ && h2c->state.length < NGX_HTTP_V2_INT_OCTETS)
1131
+ {
1132
+ return ngx_http_v2_handle_continuation(h2c, pos, end,
1133
+ ngx_http_v2_state_header_block);
1134
+ }
1135
+
1136
+ size_update = 0;
1137
+ indexed = 0;
1138
+
1139
+ ch = *pos;
1140
+
1141
+ if (ch >= (1 << 7)) {
1142
+ /* indexed header field */
1143
+ indexed = 1;
1144
+ prefix = ngx_http_v2_prefix(7);
1145
+
1146
+ } else if (ch >= (1 << 6)) {
1147
+ /* literal header field with incremental indexing */
1148
+ h2c->state.index = 1;
1149
+ prefix = ngx_http_v2_prefix(6);
1150
+
1151
+ } else if (ch >= (1 << 5)) {
1152
+ /* dynamic table size update */
1153
+ size_update = 1;
1154
+ prefix = ngx_http_v2_prefix(5);
1155
+
1156
+ } else if (ch >= (1 << 4)) {
1157
+ /* literal header field never indexed */
1158
+ prefix = ngx_http_v2_prefix(4);
1159
+
1160
+ } else {
1161
+ /* literal header field without indexing */
1162
+ prefix = ngx_http_v2_prefix(4);
1163
+ }
1164
+
1165
+ value = ngx_http_v2_parse_int(h2c, &pos, end, prefix);
1166
+
1167
+ if (value < 0) {
1168
+ if (value == NGX_AGAIN) {
1169
+ return ngx_http_v2_state_headers_save(h2c, pos, end,
1170
+ ngx_http_v2_state_header_block);
1171
+ }
1172
+
1173
+ if (value == NGX_DECLINED) {
1174
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1175
+ "client sent header block with too long %s value",
1176
+ size_update ? "size update" : "header index");
1177
+
1178
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_COMP_ERROR);
1179
+ }
1180
+
1181
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1182
+ "client sent header block with incorrect length");
1183
+
1184
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
1185
+ }
1186
+
1187
+ if (indexed) {
1188
+ if (ngx_http_v2_get_indexed_header(h2c, value, 0) != NGX_OK) {
1189
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_COMP_ERROR);
1190
+ }
1191
+
1192
+ return ngx_http_v2_state_process_header(h2c, pos, end);
1193
+ }
1194
+
1195
+ if (size_update) {
1196
+ if (ngx_http_v2_table_size(h2c, value) != NGX_OK) {
1197
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_COMP_ERROR);
1198
+ }
1199
+
1200
+ return ngx_http_v2_state_header_complete(h2c, pos, end);
1201
+ }
1202
+
1203
+ if (value == 0) {
1204
+ h2c->state.parse_name = 1;
1205
+
1206
+ } else if (ngx_http_v2_get_indexed_header(h2c, value, 1) != NGX_OK) {
1207
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_COMP_ERROR);
1208
+ }
1209
+
1210
+ h2c->state.parse_value = 1;
1211
+
1212
+ return ngx_http_v2_state_field_len(h2c, pos, end);
1213
+ }
1214
+
1215
+
1216
+ static u_char *
1217
+ ngx_http_v2_state_field_len(ngx_http_v2_connection_t *h2c, u_char *pos,
1218
+ u_char *end)
1219
+ {
1220
+ size_t alloc;
1221
+ ngx_int_t len;
1222
+ ngx_uint_t huff;
1223
+ ngx_http_v2_srv_conf_t *h2scf;
1224
+
1225
+ if (!(h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG)
1226
+ && h2c->state.length < NGX_HTTP_V2_INT_OCTETS)
1227
+ {
1228
+ return ngx_http_v2_handle_continuation(h2c, pos, end,
1229
+ ngx_http_v2_state_field_len);
1230
+ }
1231
+
1232
+ if (h2c->state.length < 1) {
1233
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1234
+ "client sent header block with incorrect length");
1235
+
1236
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
1237
+ }
1238
+
1239
+ if (end - pos < 1) {
1240
+ return ngx_http_v2_state_headers_save(h2c, pos, end,
1241
+ ngx_http_v2_state_field_len);
1242
+ }
1243
+
1244
+ huff = *pos >> 7;
1245
+ len = ngx_http_v2_parse_int(h2c, &pos, end, ngx_http_v2_prefix(7));
1246
+
1247
+ if (len < 0) {
1248
+ if (len == NGX_AGAIN) {
1249
+ return ngx_http_v2_state_headers_save(h2c, pos, end,
1250
+ ngx_http_v2_state_field_len);
1251
+ }
1252
+
1253
+ if (len == NGX_DECLINED) {
1254
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1255
+ "client sent header field with too long length value");
1256
+
1257
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_COMP_ERROR);
1258
+ }
1259
+
1260
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1261
+ "client sent header block with incorrect length");
1262
+
1263
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
1264
+ }
1265
+
1266
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
1267
+ "http2 hpack %s string length: %i",
1268
+ huff ? "encoded" : "raw", len);
1269
+
1270
+ h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
1271
+ ngx_http_v2_module);
1272
+
1273
+ if ((size_t) len > h2scf->max_field_size) {
1274
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1275
+ "client exceeded http2_max_field_size limit");
1276
+
1277
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_ENHANCE_YOUR_CALM);
1278
+ }
1279
+
1280
+ h2c->state.field_rest = len;
1281
+
1282
+ if (h2c->state.stream == NULL && !h2c->state.index) {
1283
+ return ngx_http_v2_state_field_skip(h2c, pos, end);
1284
+ }
1285
+
1286
+ alloc = (huff ? len * 8 / 5 : len) + 1;
1287
+
1288
+ h2c->state.field_start = ngx_pnalloc(h2c->state.pool, alloc);
1289
+ if (h2c->state.field_start == NULL) {
1290
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
1291
+ }
1292
+
1293
+ h2c->state.field_end = h2c->state.field_start;
1294
+
1295
+ if (huff) {
1296
+ return ngx_http_v2_state_field_huff(h2c, pos, end);
1297
+ }
1298
+
1299
+ return ngx_http_v2_state_field_raw(h2c, pos, end);
1300
+ }
1301
+
1302
+
1303
+ static u_char *
1304
+ ngx_http_v2_state_field_huff(ngx_http_v2_connection_t *h2c, u_char *pos,
1305
+ u_char *end)
1306
+ {
1307
+ size_t size;
1308
+
1309
+ size = end - pos;
1310
+
1311
+ if (size > h2c->state.field_rest) {
1312
+ size = h2c->state.field_rest;
1313
+ }
1314
+
1315
+ if (size > h2c->state.length) {
1316
+ size = h2c->state.length;
1317
+ }
1318
+
1319
+ h2c->state.length -= size;
1320
+ h2c->state.field_rest -= size;
1321
+
1322
+ if (ngx_http_v2_huff_decode(&h2c->state.field_state, pos, size,
1323
+ &h2c->state.field_end,
1324
+ h2c->state.field_rest == 0,
1325
+ h2c->connection->log)
1326
+ != NGX_OK)
1327
+ {
1328
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1329
+ "client sent invalid encoded header field");
1330
+
1331
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_COMP_ERROR);
1332
+ }
1333
+
1334
+ pos += size;
1335
+
1336
+ if (h2c->state.field_rest == 0) {
1337
+ *h2c->state.field_end = '\0';
1338
+ return ngx_http_v2_state_process_header(h2c, pos, end);
1339
+ }
1340
+
1341
+ if (h2c->state.length) {
1342
+ return ngx_http_v2_state_headers_save(h2c, pos, end,
1343
+ ngx_http_v2_state_field_huff);
1344
+ }
1345
+
1346
+ if (h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) {
1347
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1348
+ "client sent header field with incorrect length");
1349
+
1350
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
1351
+ }
1352
+
1353
+ return ngx_http_v2_handle_continuation(h2c, pos, end,
1354
+ ngx_http_v2_state_field_huff);
1355
+ }
1356
+
1357
+
1358
+ static u_char *
1359
+ ngx_http_v2_state_field_raw(ngx_http_v2_connection_t *h2c, u_char *pos,
1360
+ u_char *end)
1361
+ {
1362
+ size_t size;
1363
+
1364
+ size = end - pos;
1365
+
1366
+ if (size > h2c->state.field_rest) {
1367
+ size = h2c->state.field_rest;
1368
+ }
1369
+
1370
+ if (size > h2c->state.length) {
1371
+ size = h2c->state.length;
1372
+ }
1373
+
1374
+ h2c->state.length -= size;
1375
+ h2c->state.field_rest -= size;
1376
+
1377
+ h2c->state.field_end = ngx_cpymem(h2c->state.field_end, pos, size);
1378
+
1379
+ pos += size;
1380
+
1381
+ if (h2c->state.field_rest == 0) {
1382
+ *h2c->state.field_end = '\0';
1383
+ return ngx_http_v2_state_process_header(h2c, pos, end);
1384
+ }
1385
+
1386
+ if (h2c->state.length) {
1387
+ return ngx_http_v2_state_headers_save(h2c, pos, end,
1388
+ ngx_http_v2_state_field_raw);
1389
+ }
1390
+
1391
+ if (h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) {
1392
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1393
+ "client sent header field with incorrect length");
1394
+
1395
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
1396
+ }
1397
+
1398
+ return ngx_http_v2_handle_continuation(h2c, pos, end,
1399
+ ngx_http_v2_state_field_raw);
1400
+ }
1401
+
1402
+
1403
+ static u_char *
1404
+ ngx_http_v2_state_field_skip(ngx_http_v2_connection_t *h2c, u_char *pos,
1405
+ u_char *end)
1406
+ {
1407
+ size_t size;
1408
+
1409
+ size = end - pos;
1410
+
1411
+ if (size > h2c->state.field_rest) {
1412
+ size = h2c->state.field_rest;
1413
+ }
1414
+
1415
+ if (size > h2c->state.length) {
1416
+ size = h2c->state.length;
1417
+ }
1418
+
1419
+ h2c->state.length -= size;
1420
+ h2c->state.field_rest -= size;
1421
+
1422
+ pos += size;
1423
+
1424
+ if (h2c->state.field_rest == 0) {
1425
+ return ngx_http_v2_state_process_header(h2c, pos, end);
1426
+ }
1427
+
1428
+ if (h2c->state.length) {
1429
+ return ngx_http_v2_state_save(h2c, pos, end,
1430
+ ngx_http_v2_state_field_skip);
1431
+ }
1432
+
1433
+ if (h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) {
1434
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1435
+ "client sent header field with incorrect length");
1436
+
1437
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
1438
+ }
1439
+
1440
+ return ngx_http_v2_handle_continuation(h2c, pos, end,
1441
+ ngx_http_v2_state_field_skip);
1442
+ }
1443
+
1444
+
1445
+ static u_char *
1446
+ ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c, u_char *pos,
1447
+ u_char *end)
1448
+ {
1449
+ size_t len;
1450
+ ngx_int_t rc;
1451
+ ngx_table_elt_t *h;
1452
+ ngx_http_header_t *hh;
1453
+ ngx_http_request_t *r;
1454
+ ngx_http_v2_header_t *header;
1455
+ ngx_http_core_srv_conf_t *cscf;
1456
+ ngx_http_core_main_conf_t *cmcf;
1457
+
1458
+ static ngx_str_t cookie = ngx_string("cookie");
1459
+
1460
+ header = &h2c->state.header;
1461
+
1462
+ if (h2c->state.parse_name) {
1463
+ h2c->state.parse_name = 0;
1464
+
1465
+ header->name.len = h2c->state.field_end - h2c->state.field_start;
1466
+ header->name.data = h2c->state.field_start;
1467
+
1468
+ return ngx_http_v2_state_field_len(h2c, pos, end);
1469
+ }
1470
+
1471
+ if (h2c->state.parse_value) {
1472
+ h2c->state.parse_value = 0;
1473
+
1474
+ header->value.len = h2c->state.field_end - h2c->state.field_start;
1475
+ header->value.data = h2c->state.field_start;
1476
+ }
1477
+
1478
+ len = header->name.len + header->value.len;
1479
+
1480
+ if (len > h2c->state.header_limit) {
1481
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1482
+ "client exceeded http2_max_header_size limit");
1483
+
1484
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_ENHANCE_YOUR_CALM);
1485
+ }
1486
+
1487
+ h2c->state.header_limit -= len;
1488
+
1489
+ if (h2c->state.index) {
1490
+ if (ngx_http_v2_add_header(h2c, header) != NGX_OK) {
1491
+ return ngx_http_v2_connection_error(h2c,
1492
+ NGX_HTTP_V2_INTERNAL_ERROR);
1493
+ }
1494
+
1495
+ h2c->state.index = 0;
1496
+ }
1497
+
1498
+ if (h2c->state.stream == NULL) {
1499
+ return ngx_http_v2_state_header_complete(h2c, pos, end);
1500
+ }
1501
+
1502
+ r = h2c->state.stream->request;
1503
+
1504
+ /* TODO Optimization: validate headers while parsing. */
1505
+ if (ngx_http_v2_validate_header(r, header) != NGX_OK) {
1506
+ if (ngx_http_v2_terminate_stream(h2c, h2c->state.stream,
1507
+ NGX_HTTP_V2_PROTOCOL_ERROR)
1508
+ == NGX_ERROR)
1509
+ {
1510
+ return ngx_http_v2_connection_error(h2c,
1511
+ NGX_HTTP_V2_INTERNAL_ERROR);
1512
+ }
1513
+
1514
+ goto error;
1515
+ }
1516
+
1517
+ if (header->name.data[0] == ':') {
1518
+ rc = ngx_http_v2_pseudo_header(r, header);
1519
+
1520
+ if (rc == NGX_OK) {
1521
+ return ngx_http_v2_state_header_complete(h2c, pos, end);
1522
+ }
1523
+
1524
+ if (rc == NGX_ABORT) {
1525
+ goto error;
1526
+ }
1527
+
1528
+ if (rc == NGX_DECLINED) {
1529
+ if (ngx_http_v2_terminate_stream(h2c, h2c->state.stream,
1530
+ NGX_HTTP_V2_PROTOCOL_ERROR)
1531
+ == NGX_ERROR)
1532
+ {
1533
+ return ngx_http_v2_connection_error(h2c,
1534
+ NGX_HTTP_V2_INTERNAL_ERROR);
1535
+ }
1536
+
1537
+ goto error;
1538
+ }
1539
+
1540
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
1541
+ }
1542
+
1543
+ if (r->invalid_header) {
1544
+ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1545
+
1546
+ if (cscf->ignore_invalid_headers) {
1547
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1548
+ "client sent invalid header: \"%V\"", &header->name);
1549
+
1550
+ return ngx_http_v2_state_header_complete(h2c, pos, end);
1551
+ }
1552
+ }
1553
+
1554
+ if (header->name.len == cookie.len
1555
+ && ngx_memcmp(header->name.data, cookie.data, cookie.len) == 0)
1556
+ {
1557
+ if (ngx_http_v2_cookie(r, header) != NGX_OK) {
1558
+ return ngx_http_v2_connection_error(h2c,
1559
+ NGX_HTTP_V2_INTERNAL_ERROR);
1560
+ }
1561
+
1562
+ return ngx_http_v2_state_header_complete(h2c, pos, end);
1563
+ }
1564
+
1565
+ h = ngx_list_push(&r->headers_in.headers);
1566
+ if (h == NULL) {
1567
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
1568
+ }
1569
+
1570
+ h->key.len = header->name.len;
1571
+ h->key.data = header->name.data;
1572
+
1573
+ /* TODO Optimization: precalculate hash and handler for indexed headers. */
1574
+ h->hash = ngx_hash_key(h->key.data, h->key.len);
1575
+
1576
+ h->value.len = header->value.len;
1577
+ h->value.data = header->value.data;
1578
+
1579
+ h->lowcase_key = h->key.data;
1580
+
1581
+ cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
1582
+
1583
+ hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
1584
+ h->lowcase_key, h->key.len);
1585
+
1586
+ if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
1587
+ goto error;
1588
+ }
1589
+
1590
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1591
+ "http2 http header: \"%V: %V\"", &h->key, &h->value);
1592
+
1593
+ return ngx_http_v2_state_header_complete(h2c, pos, end);
1594
+
1595
+ error:
1596
+
1597
+ h2c->state.stream = NULL;
1598
+
1599
+ return ngx_http_v2_state_header_complete(h2c, pos, end);
1600
+ }
1601
+
1602
+
1603
+ static u_char *
1604
+ ngx_http_v2_state_header_complete(ngx_http_v2_connection_t *h2c, u_char *pos,
1605
+ u_char *end)
1606
+ {
1607
+ ngx_http_v2_stream_t *stream;
1608
+
1609
+ if (h2c->state.length) {
1610
+ h2c->state.handler = ngx_http_v2_state_header_block;
1611
+ return pos;
1612
+ }
1613
+
1614
+ if (!(h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG)) {
1615
+ return ngx_http_v2_handle_continuation(h2c, pos, end,
1616
+ ngx_http_v2_state_header_complete);
1617
+ }
1618
+
1619
+ stream = h2c->state.stream;
1620
+
1621
+ if (stream) {
1622
+ ngx_http_v2_run_request(stream->request);
1623
+ }
1624
+
1625
+ if (!h2c->state.keep_pool) {
1626
+ ngx_destroy_pool(h2c->state.pool);
1627
+ }
1628
+
1629
+ h2c->state.pool = NULL;
1630
+ h2c->state.keep_pool = 0;
1631
+
1632
+ if (h2c->state.padding) {
1633
+ return ngx_http_v2_state_skip_padded(h2c, pos, end);
1634
+ }
1635
+
1636
+ return ngx_http_v2_state_complete(h2c, pos, end);
1637
+ }
1638
+
1639
+
1640
+ static u_char *
1641
+ ngx_http_v2_handle_continuation(ngx_http_v2_connection_t *h2c, u_char *pos,
1642
+ u_char *end, ngx_http_v2_handler_pt handler)
1643
+ {
1644
+ u_char *p;
1645
+ size_t len, skip;
1646
+ uint32_t head;
1647
+
1648
+ len = h2c->state.length;
1649
+
1650
+ if (h2c->state.padding && (size_t) (end - pos) > len) {
1651
+ skip = ngx_min(h2c->state.padding, (end - pos) - len);
1652
+
1653
+ h2c->state.padding -= skip;
1654
+
1655
+ p = pos;
1656
+ pos += skip;
1657
+ ngx_memmove(pos, p, len);
1658
+ }
1659
+
1660
+ if ((size_t) (end - pos) < len + NGX_HTTP_V2_FRAME_HEADER_SIZE) {
1661
+ return ngx_http_v2_state_headers_save(h2c, pos, end, handler);
1662
+ }
1663
+
1664
+ p = pos + len;
1665
+
1666
+ head = ngx_http_v2_parse_uint32(p);
1667
+
1668
+ if (ngx_http_v2_parse_type(head) != NGX_HTTP_V2_CONTINUATION_FRAME) {
1669
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1670
+ "client sent inappropriate frame while CONTINUATION was expected");
1671
+
1672
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
1673
+ }
1674
+
1675
+ h2c->state.flags |= p[4];
1676
+
1677
+ if (h2c->state.sid != ngx_http_v2_parse_sid(&p[5])) {
1678
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1679
+ "client sent CONTINUATION frame with incorrect identifier");
1680
+
1681
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
1682
+ }
1683
+
1684
+ p = pos;
1685
+ pos += NGX_HTTP_V2_FRAME_HEADER_SIZE;
1686
+
1687
+ ngx_memcpy(pos, p, len);
1688
+
1689
+ len = ngx_http_v2_parse_length(head);
1690
+
1691
+ h2c->state.length += len;
1692
+
1693
+ if (h2c->state.stream) {
1694
+ h2c->state.stream->request->request_length += len;
1695
+ }
1696
+
1697
+ h2c->state.handler = handler;
1698
+ return pos;
1699
+ }
1700
+
1701
+
1702
+ static u_char *
1703
+ ngx_http_v2_state_priority(ngx_http_v2_connection_t *h2c, u_char *pos,
1704
+ u_char *end)
1705
+ {
1706
+ ngx_uint_t depend, dependency, excl, weight;
1707
+ ngx_http_v2_node_t *node;
1708
+
1709
+ if (h2c->state.length != NGX_HTTP_V2_PRIORITY_SIZE) {
1710
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1711
+ "client sent PRIORITY frame with incorrect length %uz",
1712
+ h2c->state.length);
1713
+
1714
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
1715
+ }
1716
+
1717
+ if (end - pos < NGX_HTTP_V2_PRIORITY_SIZE) {
1718
+ return ngx_http_v2_state_save(h2c, pos, end,
1719
+ ngx_http_v2_state_priority);
1720
+ }
1721
+
1722
+ dependency = ngx_http_v2_parse_uint32(pos);
1723
+
1724
+ depend = dependency & 0x7fffffff;
1725
+ excl = dependency >> 31;
1726
+ weight = pos[4] + 1;
1727
+
1728
+ pos += NGX_HTTP_V2_PRIORITY_SIZE;
1729
+
1730
+ ngx_log_debug4(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
1731
+ "http2 PRIORITY frame sid:%ui on %ui excl:%ui weight:%ui",
1732
+ h2c->state.sid, depend, excl, weight);
1733
+
1734
+ if (h2c->state.sid == 0) {
1735
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1736
+ "client sent PRIORITY frame with incorrect identifier");
1737
+
1738
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
1739
+ }
1740
+
1741
+ if (depend == h2c->state.sid) {
1742
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1743
+ "client sent PRIORITY frame for stream %ui "
1744
+ "with incorrect dependency", h2c->state.sid);
1745
+
1746
+ node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 0);
1747
+
1748
+ if (node && node->stream) {
1749
+ if (ngx_http_v2_terminate_stream(h2c, node->stream,
1750
+ NGX_HTTP_V2_PROTOCOL_ERROR)
1751
+ == NGX_ERROR)
1752
+ {
1753
+ return ngx_http_v2_connection_error(h2c,
1754
+ NGX_HTTP_V2_INTERNAL_ERROR);
1755
+ }
1756
+
1757
+ } else {
1758
+ if (ngx_http_v2_send_rst_stream(h2c, h2c->state.sid,
1759
+ NGX_HTTP_V2_PROTOCOL_ERROR)
1760
+ == NGX_ERROR)
1761
+ {
1762
+ return ngx_http_v2_connection_error(h2c,
1763
+ NGX_HTTP_V2_INTERNAL_ERROR);
1764
+ }
1765
+ }
1766
+
1767
+ return ngx_http_v2_state_complete(h2c, pos, end);
1768
+ }
1769
+
1770
+ node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 1);
1771
+
1772
+ if (node == NULL) {
1773
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
1774
+ }
1775
+
1776
+ node->weight = weight;
1777
+
1778
+ if (node->stream == NULL) {
1779
+ if (node->parent == NULL) {
1780
+ h2c->closed_nodes++;
1781
+
1782
+ } else {
1783
+ ngx_queue_remove(&node->reuse);
1784
+ }
1785
+
1786
+ ngx_queue_insert_tail(&h2c->closed, &node->reuse);
1787
+ }
1788
+
1789
+ ngx_http_v2_set_dependency(h2c, node, depend, excl);
1790
+
1791
+ return ngx_http_v2_state_complete(h2c, pos, end);
1792
+ }
1793
+
1794
+
1795
+ static u_char *
1796
+ ngx_http_v2_state_rst_stream(ngx_http_v2_connection_t *h2c, u_char *pos,
1797
+ u_char *end)
1798
+ {
1799
+ ngx_uint_t status;
1800
+ ngx_event_t *ev;
1801
+ ngx_connection_t *fc;
1802
+ ngx_http_v2_node_t *node;
1803
+ ngx_http_v2_stream_t *stream;
1804
+
1805
+ if (h2c->state.length != NGX_HTTP_V2_RST_STREAM_SIZE) {
1806
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1807
+ "client sent RST_STREAM frame with incorrect length %uz",
1808
+ h2c->state.length);
1809
+
1810
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
1811
+ }
1812
+
1813
+ if (end - pos < NGX_HTTP_V2_RST_STREAM_SIZE) {
1814
+ return ngx_http_v2_state_save(h2c, pos, end,
1815
+ ngx_http_v2_state_rst_stream);
1816
+ }
1817
+
1818
+ status = ngx_http_v2_parse_uint32(pos);
1819
+
1820
+ pos += NGX_HTTP_V2_RST_STREAM_SIZE;
1821
+
1822
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
1823
+ "http2 RST_STREAM frame, sid:%ui status:%ui",
1824
+ h2c->state.sid, status);
1825
+
1826
+ if (h2c->state.sid == 0) {
1827
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1828
+ "client sent RST_STREAM frame with incorrect identifier");
1829
+
1830
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
1831
+ }
1832
+
1833
+ node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 0);
1834
+
1835
+ if (node == NULL || node->stream == NULL) {
1836
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
1837
+ "unknown http2 stream");
1838
+
1839
+ return ngx_http_v2_state_complete(h2c, pos, end);
1840
+ }
1841
+
1842
+ stream = node->stream;
1843
+
1844
+ stream->in_closed = 1;
1845
+ stream->out_closed = 1;
1846
+
1847
+ fc = stream->request->connection;
1848
+ fc->error = 1;
1849
+
1850
+ switch (status) {
1851
+
1852
+ case NGX_HTTP_V2_CANCEL:
1853
+ ngx_log_error(NGX_LOG_INFO, fc->log, 0,
1854
+ "client canceled stream %ui", h2c->state.sid);
1855
+ break;
1856
+
1857
+ case NGX_HTTP_V2_INTERNAL_ERROR:
1858
+ ngx_log_error(NGX_LOG_INFO, fc->log, 0,
1859
+ "client terminated stream %ui due to internal error",
1860
+ h2c->state.sid);
1861
+ break;
1862
+
1863
+ default:
1864
+ ngx_log_error(NGX_LOG_INFO, fc->log, 0,
1865
+ "client terminated stream %ui with status %ui",
1866
+ h2c->state.sid, status);
1867
+ break;
1868
+ }
1869
+
1870
+ ev = fc->read;
1871
+ ev->handler(ev);
1872
+
1873
+ return ngx_http_v2_state_complete(h2c, pos, end);
1874
+ }
1875
+
1876
+
1877
+ static u_char *
1878
+ ngx_http_v2_state_settings(ngx_http_v2_connection_t *h2c, u_char *pos,
1879
+ u_char *end)
1880
+ {
1881
+ if (h2c->state.flags == NGX_HTTP_V2_ACK_FLAG) {
1882
+
1883
+ if (h2c->state.length != 0) {
1884
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1885
+ "client sent SETTINGS frame with the ACK flag "
1886
+ "and nonzero length");
1887
+
1888
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
1889
+ }
1890
+
1891
+ h2c->settings_ack = 1;
1892
+
1893
+ return ngx_http_v2_state_complete(h2c, pos, end);
1894
+ }
1895
+
1896
+ if (h2c->state.length % NGX_HTTP_V2_SETTINGS_PARAM_SIZE) {
1897
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1898
+ "client sent SETTINGS frame with incorrect length %uz",
1899
+ h2c->state.length);
1900
+
1901
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
1902
+ }
1903
+
1904
+ ngx_http_v2_send_settings(h2c, 1);
1905
+
1906
+ return ngx_http_v2_state_settings_params(h2c, pos, end);
1907
+ }
1908
+
1909
+
1910
+ static u_char *
1911
+ ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos,
1912
+ u_char *end)
1913
+ {
1914
+ ngx_uint_t id, value;
1915
+
1916
+ while (h2c->state.length) {
1917
+ if (end - pos < NGX_HTTP_V2_SETTINGS_PARAM_SIZE) {
1918
+ return ngx_http_v2_state_save(h2c, pos, end,
1919
+ ngx_http_v2_state_settings_params);
1920
+ }
1921
+
1922
+ h2c->state.length -= NGX_HTTP_V2_SETTINGS_PARAM_SIZE;
1923
+
1924
+ id = ngx_http_v2_parse_uint16(pos);
1925
+ value = ngx_http_v2_parse_uint32(&pos[2]);
1926
+
1927
+ switch (id) {
1928
+
1929
+ case NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING:
1930
+
1931
+ if (value > NGX_HTTP_V2_MAX_WINDOW) {
1932
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1933
+ "client sent SETTINGS frame with incorrect "
1934
+ "INITIAL_WINDOW_SIZE value %ui", value);
1935
+
1936
+ return ngx_http_v2_connection_error(h2c,
1937
+ NGX_HTTP_V2_FLOW_CTRL_ERROR);
1938
+ }
1939
+
1940
+ if (ngx_http_v2_adjust_windows(h2c, value - h2c->init_window)
1941
+ != NGX_OK)
1942
+ {
1943
+ return ngx_http_v2_connection_error(h2c,
1944
+ NGX_HTTP_V2_INTERNAL_ERROR);
1945
+ }
1946
+
1947
+ h2c->init_window = value;
1948
+ break;
1949
+
1950
+ case NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING:
1951
+ if (value > NGX_HTTP_V2_MAX_FRAME_SIZE
1952
+ || value < NGX_HTTP_V2_DEFAULT_FRAME_SIZE)
1953
+ {
1954
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1955
+ "client sent SETTINGS frame with incorrect "
1956
+ "MAX_FRAME_SIZE value %ui", value);
1957
+
1958
+ return ngx_http_v2_connection_error(h2c,
1959
+ NGX_HTTP_V2_PROTOCOL_ERROR);
1960
+ }
1961
+
1962
+ h2c->frame_size = value;
1963
+ break;
1964
+
1965
+ default:
1966
+ break;
1967
+ }
1968
+
1969
+ pos += NGX_HTTP_V2_SETTINGS_PARAM_SIZE;
1970
+ }
1971
+
1972
+ return ngx_http_v2_state_complete(h2c, pos, end);
1973
+ }
1974
+
1975
+
1976
+ static u_char *
1977
+ ngx_http_v2_state_push_promise(ngx_http_v2_connection_t *h2c, u_char *pos,
1978
+ u_char *end)
1979
+ {
1980
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1981
+ "client sent PUSH_PROMISE frame");
1982
+
1983
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
1984
+ }
1985
+
1986
+
1987
+ static u_char *
1988
+ ngx_http_v2_state_ping(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end)
1989
+ {
1990
+ ngx_buf_t *buf;
1991
+ ngx_http_v2_out_frame_t *frame;
1992
+
1993
+ if (h2c->state.length != NGX_HTTP_V2_PING_SIZE) {
1994
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
1995
+ "client sent PING frame with incorrect length %uz",
1996
+ h2c->state.length);
1997
+
1998
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
1999
+ }
2000
+
2001
+ if (end - pos < NGX_HTTP_V2_PING_SIZE) {
2002
+ return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_ping);
2003
+ }
2004
+
2005
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
2006
+ "http2 PING frame, flags: %ud", h2c->state.flags);
2007
+
2008
+ if (h2c->state.flags & NGX_HTTP_V2_ACK_FLAG) {
2009
+ return ngx_http_v2_state_skip(h2c, pos, end);
2010
+ }
2011
+
2012
+ frame = ngx_http_v2_get_frame(h2c, NGX_HTTP_V2_PING_SIZE,
2013
+ NGX_HTTP_V2_PING_FRAME,
2014
+ NGX_HTTP_V2_ACK_FLAG, 0);
2015
+ if (frame == NULL) {
2016
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
2017
+ }
2018
+
2019
+ buf = frame->first->buf;
2020
+
2021
+ buf->last = ngx_cpymem(buf->last, pos, NGX_HTTP_V2_PING_SIZE);
2022
+
2023
+ ngx_http_v2_queue_blocked_frame(h2c, frame);
2024
+
2025
+ return ngx_http_v2_state_complete(h2c, pos + NGX_HTTP_V2_PING_SIZE, end);
2026
+ }
2027
+
2028
+
2029
+ static u_char *
2030
+ ngx_http_v2_state_goaway(ngx_http_v2_connection_t *h2c, u_char *pos,
2031
+ u_char *end)
2032
+ {
2033
+ #if (NGX_DEBUG)
2034
+ ngx_uint_t last_sid, error;
2035
+ #endif
2036
+
2037
+ if (h2c->state.length < NGX_HTTP_V2_GOAWAY_SIZE) {
2038
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
2039
+ "client sent GOAWAY frame "
2040
+ "with incorrect length %uz", h2c->state.length);
2041
+
2042
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
2043
+ }
2044
+
2045
+ if (end - pos < NGX_HTTP_V2_GOAWAY_SIZE) {
2046
+ return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_goaway);
2047
+ }
2048
+
2049
+ #if (NGX_DEBUG)
2050
+ h2c->state.length -= NGX_HTTP_V2_GOAWAY_SIZE;
2051
+
2052
+ last_sid = ngx_http_v2_parse_sid(pos);
2053
+ error = ngx_http_v2_parse_uint32(&pos[4]);
2054
+
2055
+ pos += NGX_HTTP_V2_GOAWAY_SIZE;
2056
+
2057
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
2058
+ "http2 GOAWAY frame: last sid %ui, error %ui",
2059
+ last_sid, error);
2060
+ #endif
2061
+
2062
+ return ngx_http_v2_state_skip(h2c, pos, end);
2063
+ }
2064
+
2065
+
2066
+ static u_char *
2067
+ ngx_http_v2_state_window_update(ngx_http_v2_connection_t *h2c, u_char *pos,
2068
+ u_char *end)
2069
+ {
2070
+ size_t window;
2071
+ ngx_event_t *wev;
2072
+ ngx_queue_t *q;
2073
+ ngx_http_v2_node_t *node;
2074
+ ngx_http_v2_stream_t *stream;
2075
+
2076
+ if (h2c->state.length != NGX_HTTP_V2_WINDOW_UPDATE_SIZE) {
2077
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
2078
+ "client sent WINDOW_UPDATE frame "
2079
+ "with incorrect length %uz", h2c->state.length);
2080
+
2081
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
2082
+ }
2083
+
2084
+ if (end - pos < NGX_HTTP_V2_WINDOW_UPDATE_SIZE) {
2085
+ return ngx_http_v2_state_save(h2c, pos, end,
2086
+ ngx_http_v2_state_window_update);
2087
+ }
2088
+
2089
+ window = ngx_http_v2_parse_window(pos);
2090
+
2091
+ pos += NGX_HTTP_V2_WINDOW_UPDATE_SIZE;
2092
+
2093
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
2094
+ "http2 WINDOW_UPDATE frame sid:%ui window:%uz",
2095
+ h2c->state.sid, window);
2096
+
2097
+ if (h2c->state.sid) {
2098
+ node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 0);
2099
+
2100
+ if (node == NULL || node->stream == NULL) {
2101
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
2102
+ "unknown http2 stream");
2103
+
2104
+ return ngx_http_v2_state_complete(h2c, pos, end);
2105
+ }
2106
+
2107
+ stream = node->stream;
2108
+
2109
+ if (window > (size_t) (NGX_HTTP_V2_MAX_WINDOW - stream->send_window)) {
2110
+
2111
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
2112
+ "client violated flow control for stream %ui: "
2113
+ "received WINDOW_UPDATE frame "
2114
+ "with window increment %uz "
2115
+ "not allowed for window %z",
2116
+ h2c->state.sid, window, stream->send_window);
2117
+
2118
+ if (ngx_http_v2_terminate_stream(h2c, stream,
2119
+ NGX_HTTP_V2_FLOW_CTRL_ERROR)
2120
+ == NGX_ERROR)
2121
+ {
2122
+ return ngx_http_v2_connection_error(h2c,
2123
+ NGX_HTTP_V2_INTERNAL_ERROR);
2124
+ }
2125
+
2126
+ return ngx_http_v2_state_complete(h2c, pos, end);
2127
+ }
2128
+
2129
+ stream->send_window += window;
2130
+
2131
+ if (stream->exhausted) {
2132
+ stream->exhausted = 0;
2133
+
2134
+ wev = stream->request->connection->write;
2135
+
2136
+ wev->active = 0;
2137
+ wev->ready = 1;
2138
+
2139
+ if (!wev->delayed) {
2140
+ wev->handler(wev);
2141
+ }
2142
+ }
2143
+
2144
+ return ngx_http_v2_state_complete(h2c, pos, end);
2145
+ }
2146
+
2147
+ if (window > NGX_HTTP_V2_MAX_WINDOW - h2c->send_window) {
2148
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
2149
+ "client violated connection flow control: "
2150
+ "received WINDOW_UPDATE frame "
2151
+ "with window increment %uz "
2152
+ "not allowed for window %uz",
2153
+ window, h2c->send_window);
2154
+
2155
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_FLOW_CTRL_ERROR);
2156
+ }
2157
+
2158
+ h2c->send_window += window;
2159
+
2160
+ while (!ngx_queue_empty(&h2c->waiting)) {
2161
+ q = ngx_queue_head(&h2c->waiting);
2162
+
2163
+ ngx_queue_remove(q);
2164
+
2165
+ stream = ngx_queue_data(q, ngx_http_v2_stream_t, queue);
2166
+
2167
+ stream->handled = 0;
2168
+
2169
+ wev = stream->request->connection->write;
2170
+
2171
+ wev->active = 0;
2172
+ wev->ready = 1;
2173
+
2174
+ if (!wev->delayed) {
2175
+ wev->handler(wev);
2176
+
2177
+ if (h2c->send_window == 0) {
2178
+ break;
2179
+ }
2180
+ }
2181
+ }
2182
+
2183
+ return ngx_http_v2_state_complete(h2c, pos, end);
2184
+ }
2185
+
2186
+
2187
+ static u_char *
2188
+ ngx_http_v2_state_continuation(ngx_http_v2_connection_t *h2c, u_char *pos,
2189
+ u_char *end)
2190
+ {
2191
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
2192
+ "client sent unexpected CONTINUATION frame");
2193
+
2194
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
2195
+ }
2196
+
2197
+
2198
+ static u_char *
2199
+ ngx_http_v2_state_complete(ngx_http_v2_connection_t *h2c, u_char *pos,
2200
+ u_char *end)
2201
+ {
2202
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
2203
+ "http2 frame complete pos:%p end:%p", pos, end);
2204
+
2205
+ if (pos > end) {
2206
+ ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0,
2207
+ "receive buffer overrun");
2208
+
2209
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
2210
+ }
2211
+
2212
+ h2c->state.stream = NULL;
2213
+ h2c->state.handler = ngx_http_v2_state_head;
2214
+
2215
+ return pos;
2216
+ }
2217
+
2218
+
2219
+ static u_char *
2220
+ ngx_http_v2_state_skip_padded(ngx_http_v2_connection_t *h2c, u_char *pos,
2221
+ u_char *end)
2222
+ {
2223
+ h2c->state.length += h2c->state.padding;
2224
+ h2c->state.padding = 0;
2225
+
2226
+ return ngx_http_v2_state_skip(h2c, pos, end);
2227
+ }
2228
+
2229
+
2230
+ static u_char *
2231
+ ngx_http_v2_state_skip(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end)
2232
+ {
2233
+ size_t size;
2234
+
2235
+ size = end - pos;
2236
+
2237
+ if (size < h2c->state.length) {
2238
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
2239
+ "http2 frame skip %uz of %uz", size, h2c->state.length);
2240
+
2241
+ h2c->state.length -= size;
2242
+ return ngx_http_v2_state_save(h2c, end, end, ngx_http_v2_state_skip);
2243
+ }
2244
+
2245
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
2246
+ "http2 frame skip %uz", h2c->state.length);
2247
+
2248
+ return ngx_http_v2_state_complete(h2c, pos + h2c->state.length, end);
2249
+ }
2250
+
2251
+
2252
+ static u_char *
2253
+ ngx_http_v2_state_save(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end,
2254
+ ngx_http_v2_handler_pt handler)
2255
+ {
2256
+ size_t size;
2257
+
2258
+ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
2259
+ "http2 frame state save pos:%p end:%p handler:%p",
2260
+ pos, end, handler);
2261
+
2262
+ size = end - pos;
2263
+
2264
+ if (size > NGX_HTTP_V2_STATE_BUFFER_SIZE) {
2265
+ ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0,
2266
+ "state buffer overflow: %uz bytes required", size);
2267
+
2268
+ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
2269
+ }
2270
+
2271
+ ngx_memcpy(h2c->state.buffer, pos, NGX_HTTP_V2_STATE_BUFFER_SIZE);
2272
+
2273
+ h2c->state.buffer_used = size;
2274
+ h2c->state.handler = handler;
2275
+ h2c->state.incomplete = 1;
2276
+
2277
+ return end;
2278
+ }
2279
+
2280
+
2281
+ static u_char *
2282
+ ngx_http_v2_state_headers_save(ngx_http_v2_connection_t *h2c, u_char *pos,
2283
+ u_char *end, ngx_http_v2_handler_pt handler)
2284
+ {
2285
+ ngx_event_t *rev;
2286
+ ngx_http_request_t *r;
2287
+ ngx_http_core_srv_conf_t *cscf;
2288
+
2289
+ if (h2c->state.stream) {
2290
+ r = h2c->state.stream->request;
2291
+ rev = r->connection->read;
2292
+
2293
+ if (!rev->timer_set) {
2294
+ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2295
+ ngx_add_timer(rev, cscf->client_header_timeout);
2296
+ }
2297
+ }
2298
+
2299
+ return ngx_http_v2_state_save(h2c, pos, end, handler);
2300
+ }
2301
+
2302
+
2303
+ static u_char *
2304
+ ngx_http_v2_connection_error(ngx_http_v2_connection_t *h2c,
2305
+ ngx_uint_t err)
2306
+ {
2307
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
2308
+ "http2 state connection error");
2309
+
2310
+ if (err == NGX_HTTP_V2_INTERNAL_ERROR) {
2311
+ ngx_debug_point();
2312
+ }
2313
+
2314
+ ngx_http_v2_finalize_connection(h2c, err);
2315
+
2316
+ return NULL;
2317
+ }
2318
+
2319
+
2320
+ static ngx_int_t
2321
+ ngx_http_v2_parse_int(ngx_http_v2_connection_t *h2c, u_char **pos, u_char *end,
2322
+ ngx_uint_t prefix)
2323
+ {
2324
+ u_char *start, *p;
2325
+ ngx_uint_t value, octet, shift;
2326
+
2327
+ start = *pos;
2328
+ p = start;
2329
+
2330
+ value = *p++ & prefix;
2331
+
2332
+ if (value != prefix) {
2333
+ if (h2c->state.length == 0) {
2334
+ return NGX_ERROR;
2335
+ }
2336
+
2337
+ h2c->state.length--;
2338
+
2339
+ *pos = p;
2340
+ return value;
2341
+ }
2342
+
2343
+ if (end - start > NGX_HTTP_V2_INT_OCTETS) {
2344
+ end = start + NGX_HTTP_V2_INT_OCTETS;
2345
+ }
2346
+
2347
+ for (shift = 0; p != end; shift += 7) {
2348
+ octet = *p++;
2349
+
2350
+ value += (octet & 0x7f) << shift;
2351
+
2352
+ if (octet < 128) {
2353
+ if ((size_t) (p - start) > h2c->state.length) {
2354
+ return NGX_ERROR;
2355
+ }
2356
+
2357
+ h2c->state.length -= p - start;
2358
+
2359
+ *pos = p;
2360
+ return value;
2361
+ }
2362
+ }
2363
+
2364
+ if ((size_t) (end - start) >= h2c->state.length) {
2365
+ return NGX_ERROR;
2366
+ }
2367
+
2368
+ if (end == start + NGX_HTTP_V2_INT_OCTETS) {
2369
+ return NGX_DECLINED;
2370
+ }
2371
+
2372
+ return NGX_AGAIN;
2373
+ }
2374
+
2375
+
2376
+ static ngx_int_t
2377
+ ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c, ngx_uint_t ack)
2378
+ {
2379
+ size_t len;
2380
+ ngx_buf_t *buf;
2381
+ ngx_chain_t *cl;
2382
+ ngx_http_v2_srv_conf_t *h2scf;
2383
+ ngx_http_v2_out_frame_t *frame;
2384
+
2385
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
2386
+ "http2 send SETTINGS frame ack:%ui", ack);
2387
+
2388
+ frame = ngx_palloc(h2c->pool, sizeof(ngx_http_v2_out_frame_t));
2389
+ if (frame == NULL) {
2390
+ return NGX_ERROR;
2391
+ }
2392
+
2393
+ cl = ngx_alloc_chain_link(h2c->pool);
2394
+ if (cl == NULL) {
2395
+ return NGX_ERROR;
2396
+ }
2397
+
2398
+ len = ack ? 0 : (sizeof(uint16_t) + sizeof(uint32_t)) * 3;
2399
+
2400
+ buf = ngx_create_temp_buf(h2c->pool, NGX_HTTP_V2_FRAME_HEADER_SIZE + len);
2401
+ if (buf == NULL) {
2402
+ return NGX_ERROR;
2403
+ }
2404
+
2405
+ buf->last_buf = 1;
2406
+
2407
+ cl->buf = buf;
2408
+ cl->next = NULL;
2409
+
2410
+ frame->first = cl;
2411
+ frame->last = cl;
2412
+ frame->handler = ngx_http_v2_settings_frame_handler;
2413
+ frame->stream = NULL;
2414
+ #if (NGX_DEBUG)
2415
+ frame->length = len;
2416
+ #endif
2417
+ frame->blocked = 0;
2418
+
2419
+ buf->last = ngx_http_v2_write_len_and_type(buf->last, len,
2420
+ NGX_HTTP_V2_SETTINGS_FRAME);
2421
+
2422
+ *buf->last++ = ack ? NGX_HTTP_V2_ACK_FLAG : NGX_HTTP_V2_NO_FLAG;
2423
+
2424
+ buf->last = ngx_http_v2_write_sid(buf->last, 0);
2425
+
2426
+ if (!ack) {
2427
+ h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
2428
+ ngx_http_v2_module);
2429
+
2430
+ buf->last = ngx_http_v2_write_uint16(buf->last,
2431
+ NGX_HTTP_V2_MAX_STREAMS_SETTING);
2432
+ buf->last = ngx_http_v2_write_uint32(buf->last,
2433
+ h2scf->concurrent_streams);
2434
+
2435
+ buf->last = ngx_http_v2_write_uint16(buf->last,
2436
+ NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING);
2437
+ buf->last = ngx_http_v2_write_uint32(buf->last,
2438
+ NGX_HTTP_V2_INITIAL_WINDOW);
2439
+
2440
+ buf->last = ngx_http_v2_write_uint16(buf->last,
2441
+ NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING);
2442
+ buf->last = ngx_http_v2_write_uint32(buf->last,
2443
+ NGX_HTTP_V2_MAX_FRAME_SIZE);
2444
+ }
2445
+
2446
+ ngx_http_v2_queue_blocked_frame(h2c, frame);
2447
+
2448
+ return NGX_OK;
2449
+ }
2450
+
2451
+
2452
+ static ngx_int_t
2453
+ ngx_http_v2_settings_frame_handler(ngx_http_v2_connection_t *h2c,
2454
+ ngx_http_v2_out_frame_t *frame)
2455
+ {
2456
+ ngx_buf_t *buf;
2457
+
2458
+ buf = frame->first->buf;
2459
+
2460
+ if (buf->pos != buf->last) {
2461
+ return NGX_AGAIN;
2462
+ }
2463
+
2464
+ ngx_free_chain(h2c->pool, frame->first);
2465
+
2466
+ return NGX_OK;
2467
+ }
2468
+
2469
+
2470
+ static ngx_int_t
2471
+ ngx_http_v2_send_window_update(ngx_http_v2_connection_t *h2c, ngx_uint_t sid,
2472
+ size_t window)
2473
+ {
2474
+ ngx_buf_t *buf;
2475
+ ngx_http_v2_out_frame_t *frame;
2476
+
2477
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
2478
+ "http2 send WINDOW_UPDATE frame sid:%ui, window:%uz",
2479
+ sid, window);
2480
+
2481
+ frame = ngx_http_v2_get_frame(h2c, NGX_HTTP_V2_WINDOW_UPDATE_SIZE,
2482
+ NGX_HTTP_V2_WINDOW_UPDATE_FRAME,
2483
+ NGX_HTTP_V2_NO_FLAG, sid);
2484
+ if (frame == NULL) {
2485
+ return NGX_ERROR;
2486
+ }
2487
+
2488
+ buf = frame->first->buf;
2489
+
2490
+ buf->last = ngx_http_v2_write_uint32(buf->last, window);
2491
+
2492
+ ngx_http_v2_queue_blocked_frame(h2c, frame);
2493
+
2494
+ return NGX_OK;
2495
+ }
2496
+
2497
+
2498
+ static ngx_int_t
2499
+ ngx_http_v2_send_rst_stream(ngx_http_v2_connection_t *h2c, ngx_uint_t sid,
2500
+ ngx_uint_t status)
2501
+ {
2502
+ ngx_buf_t *buf;
2503
+ ngx_http_v2_out_frame_t *frame;
2504
+
2505
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
2506
+ "http2 send RST_STREAM frame sid:%ui, status:%uz",
2507
+ sid, status);
2508
+
2509
+ frame = ngx_http_v2_get_frame(h2c, NGX_HTTP_V2_RST_STREAM_SIZE,
2510
+ NGX_HTTP_V2_RST_STREAM_FRAME,
2511
+ NGX_HTTP_V2_NO_FLAG, sid);
2512
+ if (frame == NULL) {
2513
+ return NGX_ERROR;
2514
+ }
2515
+
2516
+ buf = frame->first->buf;
2517
+
2518
+ buf->last = ngx_http_v2_write_uint32(buf->last, status);
2519
+
2520
+ ngx_http_v2_queue_blocked_frame(h2c, frame);
2521
+
2522
+ return NGX_OK;
2523
+ }
2524
+
2525
+
2526
+ static ngx_int_t
2527
+ ngx_http_v2_send_goaway(ngx_http_v2_connection_t *h2c, ngx_uint_t status)
2528
+ {
2529
+ ngx_buf_t *buf;
2530
+ ngx_http_v2_out_frame_t *frame;
2531
+
2532
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
2533
+ "http2 send GOAWAY frame, status:%uz", status);
2534
+
2535
+ frame = ngx_http_v2_get_frame(h2c, NGX_HTTP_V2_GOAWAY_SIZE,
2536
+ NGX_HTTP_V2_GOAWAY_FRAME,
2537
+ NGX_HTTP_V2_NO_FLAG, 0);
2538
+ if (frame == NULL) {
2539
+ return NGX_ERROR;
2540
+ }
2541
+
2542
+ buf = frame->first->buf;
2543
+
2544
+ buf->last = ngx_http_v2_write_sid(buf->last, h2c->last_sid);
2545
+ buf->last = ngx_http_v2_write_uint32(buf->last, status);
2546
+
2547
+ ngx_http_v2_queue_blocked_frame(h2c, frame);
2548
+
2549
+ return NGX_OK;
2550
+ }
2551
+
2552
+
2553
+ static ngx_http_v2_out_frame_t *
2554
+ ngx_http_v2_get_frame(ngx_http_v2_connection_t *h2c, size_t length,
2555
+ ngx_uint_t type, u_char flags, ngx_uint_t sid)
2556
+ {
2557
+ ngx_buf_t *buf;
2558
+ ngx_pool_t *pool;
2559
+ ngx_http_v2_out_frame_t *frame;
2560
+
2561
+ frame = h2c->free_frames;
2562
+
2563
+ if (frame) {
2564
+ h2c->free_frames = frame->next;
2565
+
2566
+ buf = frame->first->buf;
2567
+ buf->pos = buf->start;
2568
+
2569
+ frame->blocked = 0;
2570
+
2571
+ } else {
2572
+ pool = h2c->pool ? h2c->pool : h2c->connection->pool;
2573
+
2574
+ frame = ngx_pcalloc(pool, sizeof(ngx_http_v2_out_frame_t));
2575
+ if (frame == NULL) {
2576
+ return NULL;
2577
+ }
2578
+
2579
+ frame->first = ngx_alloc_chain_link(pool);
2580
+ if (frame->first == NULL) {
2581
+ return NULL;
2582
+ }
2583
+
2584
+ buf = ngx_create_temp_buf(pool, NGX_HTTP_V2_FRAME_BUFFER_SIZE);
2585
+ if (buf == NULL) {
2586
+ return NULL;
2587
+ }
2588
+
2589
+ buf->last_buf = 1;
2590
+
2591
+ frame->first->buf = buf;
2592
+ frame->last = frame->first;
2593
+
2594
+ frame->handler = ngx_http_v2_frame_handler;
2595
+ }
2596
+
2597
+ #if (NGX_DEBUG)
2598
+ if (length > NGX_HTTP_V2_FRAME_BUFFER_SIZE - NGX_HTTP_V2_FRAME_HEADER_SIZE)
2599
+ {
2600
+ ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0,
2601
+ "requested control frame is too large: %uz", length);
2602
+ return NULL;
2603
+ }
2604
+
2605
+ frame->length = length;
2606
+ #endif
2607
+
2608
+ buf->last = ngx_http_v2_write_len_and_type(buf->pos, length, type);
2609
+
2610
+ *buf->last++ = flags;
2611
+
2612
+ buf->last = ngx_http_v2_write_sid(buf->last, sid);
2613
+
2614
+ return frame;
2615
+ }
2616
+
2617
+
2618
+ static ngx_int_t
2619
+ ngx_http_v2_frame_handler(ngx_http_v2_connection_t *h2c,
2620
+ ngx_http_v2_out_frame_t *frame)
2621
+ {
2622
+ ngx_buf_t *buf;
2623
+
2624
+ buf = frame->first->buf;
2625
+
2626
+ if (buf->pos != buf->last) {
2627
+ return NGX_AGAIN;
2628
+ }
2629
+
2630
+ frame->next = h2c->free_frames;
2631
+ h2c->free_frames = frame;
2632
+
2633
+ return NGX_OK;
2634
+ }
2635
+
2636
+
2637
+ static ngx_http_v2_stream_t *
2638
+ ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c)
2639
+ {
2640
+ ngx_log_t *log;
2641
+ ngx_event_t *rev, *wev;
2642
+ ngx_connection_t *fc;
2643
+ ngx_http_log_ctx_t *ctx;
2644
+ ngx_http_request_t *r;
2645
+ ngx_http_v2_stream_t *stream;
2646
+ ngx_http_core_srv_conf_t *cscf;
2647
+
2648
+ fc = h2c->free_fake_connections;
2649
+
2650
+ if (fc) {
2651
+ h2c->free_fake_connections = fc->data;
2652
+
2653
+ rev = fc->read;
2654
+ wev = fc->write;
2655
+ log = fc->log;
2656
+ ctx = log->data;
2657
+
2658
+ } else {
2659
+ fc = ngx_palloc(h2c->pool, sizeof(ngx_connection_t));
2660
+ if (fc == NULL) {
2661
+ return NULL;
2662
+ }
2663
+
2664
+ rev = ngx_palloc(h2c->pool, sizeof(ngx_event_t));
2665
+ if (rev == NULL) {
2666
+ return NULL;
2667
+ }
2668
+
2669
+ wev = ngx_palloc(h2c->pool, sizeof(ngx_event_t));
2670
+ if (wev == NULL) {
2671
+ return NULL;
2672
+ }
2673
+
2674
+ log = ngx_palloc(h2c->pool, sizeof(ngx_log_t));
2675
+ if (log == NULL) {
2676
+ return NULL;
2677
+ }
2678
+
2679
+ ctx = ngx_palloc(h2c->pool, sizeof(ngx_http_log_ctx_t));
2680
+ if (ctx == NULL) {
2681
+ return NULL;
2682
+ }
2683
+
2684
+ ctx->connection = fc;
2685
+ ctx->request = NULL;
2686
+ ctx->current_request = NULL;
2687
+ }
2688
+
2689
+ ngx_memcpy(log, h2c->connection->log, sizeof(ngx_log_t));
2690
+
2691
+ log->data = ctx;
2692
+ log->action = "reading client request headers";
2693
+
2694
+ ngx_memzero(rev, sizeof(ngx_event_t));
2695
+
2696
+ rev->data = fc;
2697
+ rev->ready = 1;
2698
+ rev->handler = ngx_http_v2_close_stream_handler;
2699
+ rev->log = log;
2700
+
2701
+ ngx_memcpy(wev, rev, sizeof(ngx_event_t));
2702
+
2703
+ wev->write = 1;
2704
+
2705
+ ngx_memcpy(fc, h2c->connection, sizeof(ngx_connection_t));
2706
+
2707
+ fc->data = h2c->http_connection;
2708
+ fc->read = rev;
2709
+ fc->write = wev;
2710
+ fc->sent = 0;
2711
+ fc->log = log;
2712
+ fc->buffered = 0;
2713
+ fc->sndlowat = 1;
2714
+ fc->tcp_nodelay = NGX_TCP_NODELAY_DISABLED;
2715
+
2716
+ r = ngx_http_create_request(fc);
2717
+ if (r == NULL) {
2718
+ return NULL;
2719
+ }
2720
+
2721
+ ngx_str_set(&r->http_protocol, "HTTP/2.0");
2722
+
2723
+ r->http_version = NGX_HTTP_VERSION_20;
2724
+ r->valid_location = 1;
2725
+
2726
+ fc->data = r;
2727
+ h2c->connection->requests++;
2728
+
2729
+ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2730
+
2731
+ r->header_in = ngx_create_temp_buf(r->pool,
2732
+ cscf->client_header_buffer_size);
2733
+ if (r->header_in == NULL) {
2734
+ ngx_http_free_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2735
+ return NULL;
2736
+ }
2737
+
2738
+ if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
2739
+ sizeof(ngx_table_elt_t))
2740
+ != NGX_OK)
2741
+ {
2742
+ ngx_http_free_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2743
+ return NULL;
2744
+ }
2745
+
2746
+ r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
2747
+
2748
+ stream = ngx_pcalloc(r->pool, sizeof(ngx_http_v2_stream_t));
2749
+ if (stream == NULL) {
2750
+ ngx_http_free_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2751
+ return NULL;
2752
+ }
2753
+
2754
+ r->stream = stream;
2755
+
2756
+ stream->request = r;
2757
+ stream->connection = h2c;
2758
+
2759
+ stream->send_window = h2c->init_window;
2760
+ stream->recv_window = NGX_HTTP_V2_INITIAL_WINDOW;
2761
+
2762
+ h2c->processing++;
2763
+
2764
+ return stream;
2765
+ }
2766
+
2767
+
2768
+ static ngx_http_v2_node_t *
2769
+ ngx_http_v2_get_node_by_id(ngx_http_v2_connection_t *h2c, ngx_uint_t sid,
2770
+ ngx_uint_t alloc)
2771
+ {
2772
+ ngx_uint_t index;
2773
+ ngx_http_v2_node_t *node;
2774
+ ngx_http_v2_srv_conf_t *h2scf;
2775
+
2776
+ h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
2777
+ ngx_http_v2_module);
2778
+
2779
+ index = ngx_http_v2_index(h2scf, sid);
2780
+
2781
+ for (node = h2c->streams_index[index]; node; node = node->index) {
2782
+
2783
+ if (node->id == sid) {
2784
+ return node;
2785
+ }
2786
+ }
2787
+
2788
+ if (!alloc) {
2789
+ return NULL;
2790
+ }
2791
+
2792
+ if (h2c->closed_nodes < 32) {
2793
+ node = ngx_pcalloc(h2c->connection->pool, sizeof(ngx_http_v2_node_t));
2794
+ if (node == NULL) {
2795
+ return NULL;
2796
+ }
2797
+
2798
+ } else {
2799
+ node = ngx_http_v2_get_closed_node(h2c);
2800
+ }
2801
+
2802
+ node->id = sid;
2803
+
2804
+ ngx_queue_init(&node->children);
2805
+
2806
+ node->index = h2c->streams_index[index];
2807
+ h2c->streams_index[index] = node;
2808
+
2809
+ return node;
2810
+ }
2811
+
2812
+
2813
+ static ngx_http_v2_node_t *
2814
+ ngx_http_v2_get_closed_node(ngx_http_v2_connection_t *h2c)
2815
+ {
2816
+ ngx_uint_t weight;
2817
+ ngx_queue_t *q, *children;
2818
+ ngx_http_v2_node_t *node, **next, *n, *parent, *child;
2819
+ ngx_http_v2_srv_conf_t *h2scf;
2820
+
2821
+ h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
2822
+ ngx_http_v2_module);
2823
+
2824
+ h2c->closed_nodes--;
2825
+
2826
+ q = ngx_queue_head(&h2c->closed);
2827
+
2828
+ ngx_queue_remove(q);
2829
+
2830
+ node = ngx_queue_data(q, ngx_http_v2_node_t, reuse);
2831
+
2832
+ next = &h2c->streams_index[ngx_http_v2_index(h2scf, node->id)];
2833
+
2834
+ for ( ;; ) {
2835
+ n = *next;
2836
+
2837
+ if (n == node) {
2838
+ *next = n->index;
2839
+ break;
2840
+ }
2841
+
2842
+ next = &n->index;
2843
+ }
2844
+
2845
+ ngx_queue_remove(&node->queue);
2846
+
2847
+ weight = 0;
2848
+
2849
+ for (q = ngx_queue_head(&node->children);
2850
+ q != ngx_queue_sentinel(&node->children);
2851
+ q = ngx_queue_next(q))
2852
+ {
2853
+ child = ngx_queue_data(q, ngx_http_v2_node_t, queue);
2854
+ weight += child->weight;
2855
+ }
2856
+
2857
+ parent = node->parent;
2858
+
2859
+ for (q = ngx_queue_head(&node->children);
2860
+ q != ngx_queue_sentinel(&node->children);
2861
+ q = ngx_queue_next(q))
2862
+ {
2863
+ child = ngx_queue_data(q, ngx_http_v2_node_t, queue);
2864
+ child->parent = parent;
2865
+ child->weight = node->weight * child->weight / weight;
2866
+
2867
+ if (child->weight == 0) {
2868
+ child->weight = 1;
2869
+ }
2870
+ }
2871
+
2872
+ if (parent == NGX_HTTP_V2_ROOT) {
2873
+ node->rank = 0;
2874
+ node->rel_weight = 1.0;
2875
+
2876
+ children = &h2c->dependencies;
2877
+
2878
+ } else {
2879
+ node->rank = parent->rank;
2880
+ node->rel_weight = parent->rel_weight;
2881
+
2882
+ children = &parent->children;
2883
+ }
2884
+
2885
+ ngx_http_v2_node_children_update(node);
2886
+ ngx_queue_add(children, &node->children);
2887
+
2888
+ ngx_memzero(node, sizeof(ngx_http_v2_node_t));
2889
+
2890
+ return node;
2891
+ }
2892
+
2893
+
2894
+ static ngx_int_t
2895
+ ngx_http_v2_validate_header(ngx_http_request_t *r, ngx_http_v2_header_t *header)
2896
+ {
2897
+ u_char ch;
2898
+ ngx_uint_t i;
2899
+ ngx_http_core_srv_conf_t *cscf;
2900
+
2901
+ if (header->name.len == 0) {
2902
+ return NGX_ERROR;
2903
+ }
2904
+
2905
+ r->invalid_header = 0;
2906
+
2907
+ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2908
+
2909
+ for (i = (header->name.data[0] == ':'); i != header->name.len; i++) {
2910
+ ch = header->name.data[i];
2911
+
2912
+ if ((ch >= 'a' && ch <= 'z')
2913
+ || (ch == '-')
2914
+ || (ch >= '0' && ch <= '9')
2915
+ || (ch == '_' && cscf->underscores_in_headers))
2916
+ {
2917
+ continue;
2918
+ }
2919
+
2920
+ switch (ch) {
2921
+ case '\0':
2922
+ case LF:
2923
+ case CR:
2924
+ case ':':
2925
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
2926
+ "client sent invalid header name: \"%V\"",
2927
+ &header->name);
2928
+
2929
+ return NGX_ERROR;
2930
+ }
2931
+
2932
+ if (ch >= 'A' && ch <= 'Z') {
2933
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
2934
+ "client sent invalid header name: \"%V\"",
2935
+ &header->name);
2936
+
2937
+ return NGX_ERROR;
2938
+ }
2939
+
2940
+ r->invalid_header = 1;
2941
+ }
2942
+
2943
+ for (i = 0; i != header->value.len; i++) {
2944
+ ch = header->value.data[i];
2945
+
2946
+ switch (ch) {
2947
+ case '\0':
2948
+ case LF:
2949
+ case CR:
2950
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
2951
+ "client sent header \"%V\" with "
2952
+ "invalid value: \"%V\"",
2953
+ &header->name, &header->value);
2954
+
2955
+ return NGX_ERROR;
2956
+ }
2957
+ }
2958
+
2959
+ return NGX_OK;
2960
+ }
2961
+
2962
+
2963
+ static ngx_int_t
2964
+ ngx_http_v2_pseudo_header(ngx_http_request_t *r, ngx_http_v2_header_t *header)
2965
+ {
2966
+ header->name.len--;
2967
+ header->name.data++;
2968
+
2969
+ switch (header->name.len) {
2970
+ case 4:
2971
+ if (ngx_memcmp(header->name.data, "path", sizeof("path") - 1)
2972
+ == 0)
2973
+ {
2974
+ return ngx_http_v2_parse_path(r, header);
2975
+ }
2976
+
2977
+ break;
2978
+
2979
+ case 6:
2980
+ if (ngx_memcmp(header->name.data, "method", sizeof("method") - 1)
2981
+ == 0)
2982
+ {
2983
+ return ngx_http_v2_parse_method(r, header);
2984
+ }
2985
+
2986
+ if (ngx_memcmp(header->name.data, "scheme", sizeof("scheme") - 1)
2987
+ == 0)
2988
+ {
2989
+ return ngx_http_v2_parse_scheme(r, header);
2990
+ }
2991
+
2992
+ break;
2993
+
2994
+ case 9:
2995
+ if (ngx_memcmp(header->name.data, "authority", sizeof("authority") - 1)
2996
+ == 0)
2997
+ {
2998
+ return ngx_http_v2_parse_authority(r, header);
2999
+ }
3000
+
3001
+ break;
3002
+ }
3003
+
3004
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
3005
+ "client sent unknown pseudo header \"%V\"",
3006
+ &header->name);
3007
+
3008
+ return NGX_DECLINED;
3009
+ }
3010
+
3011
+
3012
+ static ngx_int_t
3013
+ ngx_http_v2_parse_path(ngx_http_request_t *r, ngx_http_v2_header_t *header)
3014
+ {
3015
+ if (r->unparsed_uri.len) {
3016
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
3017
+ "client sent duplicate :path header");
3018
+
3019
+ return NGX_DECLINED;
3020
+ }
3021
+
3022
+ if (header->value.len == 0) {
3023
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
3024
+ "client sent empty :path header");
3025
+
3026
+ return NGX_DECLINED;
3027
+ }
3028
+
3029
+ r->uri_start = header->value.data;
3030
+ r->uri_end = header->value.data + header->value.len;
3031
+
3032
+ if (ngx_http_parse_uri(r) != NGX_OK) {
3033
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
3034
+ "client sent invalid :path header: \"%V\"",
3035
+ &header->value);
3036
+
3037
+ return NGX_DECLINED;
3038
+ }
3039
+
3040
+ if (ngx_http_process_request_uri(r) != NGX_OK) {
3041
+ /*
3042
+ * request has been finalized already
3043
+ * in ngx_http_process_request_uri()
3044
+ */
3045
+ return NGX_ABORT;
3046
+ }
3047
+
3048
+ return NGX_OK;
3049
+ }
3050
+
3051
+
3052
+ static ngx_int_t
3053
+ ngx_http_v2_parse_method(ngx_http_request_t *r, ngx_http_v2_header_t *header)
3054
+ {
3055
+ size_t k, len;
3056
+ ngx_uint_t n;
3057
+ const u_char *p, *m;
3058
+
3059
+ /*
3060
+ * This array takes less than 256 sequential bytes,
3061
+ * and if typical CPU cache line size is 64 bytes,
3062
+ * it is prefetched for 4 load operations.
3063
+ */
3064
+ static const struct {
3065
+ u_char len;
3066
+ const u_char method[11];
3067
+ uint32_t value;
3068
+ } tests[] = {
3069
+ { 3, "GET", NGX_HTTP_GET },
3070
+ { 4, "POST", NGX_HTTP_POST },
3071
+ { 4, "HEAD", NGX_HTTP_HEAD },
3072
+ { 7, "OPTIONS", NGX_HTTP_OPTIONS },
3073
+ { 8, "PROPFIND", NGX_HTTP_PROPFIND },
3074
+ { 3, "PUT", NGX_HTTP_PUT },
3075
+ { 5, "MKCOL", NGX_HTTP_MKCOL },
3076
+ { 6, "DELETE", NGX_HTTP_DELETE },
3077
+ { 4, "COPY", NGX_HTTP_COPY },
3078
+ { 4, "MOVE", NGX_HTTP_MOVE },
3079
+ { 9, "PROPPATCH", NGX_HTTP_PROPPATCH },
3080
+ { 4, "LOCK", NGX_HTTP_LOCK },
3081
+ { 6, "UNLOCK", NGX_HTTP_UNLOCK },
3082
+ { 5, "PATCH", NGX_HTTP_PATCH },
3083
+ { 5, "TRACE", NGX_HTTP_TRACE }
3084
+ }, *test;
3085
+
3086
+ if (r->method_name.len) {
3087
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
3088
+ "client sent duplicate :method header");
3089
+
3090
+ return NGX_DECLINED;
3091
+ }
3092
+
3093
+ if (header->value.len == 0) {
3094
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
3095
+ "client sent empty :method header");
3096
+
3097
+ return NGX_DECLINED;
3098
+ }
3099
+
3100
+ r->method_name.len = header->value.len;
3101
+ r->method_name.data = header->value.data;
3102
+
3103
+ len = r->method_name.len;
3104
+ n = sizeof(tests) / sizeof(tests[0]);
3105
+ test = tests;
3106
+
3107
+ do {
3108
+ if (len == test->len) {
3109
+ p = r->method_name.data;
3110
+ m = test->method;
3111
+ k = len;
3112
+
3113
+ do {
3114
+ if (*p++ != *m++) {
3115
+ goto next;
3116
+ }
3117
+ } while (--k);
3118
+
3119
+ r->method = test->value;
3120
+ return NGX_OK;
3121
+ }
3122
+
3123
+ next:
3124
+ test++;
3125
+
3126
+ } while (--n);
3127
+
3128
+ p = r->method_name.data;
3129
+
3130
+ do {
3131
+ if ((*p < 'A' || *p > 'Z') && *p != '_') {
3132
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
3133
+ "client sent invalid method: \"%V\"",
3134
+ &r->method_name);
3135
+
3136
+ return NGX_DECLINED;
3137
+ }
3138
+
3139
+ p++;
3140
+
3141
+ } while (--len);
3142
+
3143
+ return NGX_OK;
3144
+ }
3145
+
3146
+
3147
+ static ngx_int_t
3148
+ ngx_http_v2_parse_scheme(ngx_http_request_t *r, ngx_http_v2_header_t *header)
3149
+ {
3150
+ if (r->schema_start) {
3151
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
3152
+ "client sent duplicate :schema header");
3153
+
3154
+ return NGX_DECLINED;
3155
+ }
3156
+
3157
+ if (header->value.len == 0) {
3158
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
3159
+ "client sent empty :schema header");
3160
+
3161
+ return NGX_DECLINED;
3162
+ }
3163
+
3164
+ r->schema_start = header->value.data;
3165
+ r->schema_end = header->value.data + header->value.len;
3166
+
3167
+ return NGX_OK;
3168
+ }
3169
+
3170
+
3171
+ static ngx_int_t
3172
+ ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_http_v2_header_t *header)
3173
+ {
3174
+ ngx_table_elt_t *h;
3175
+ ngx_http_header_t *hh;
3176
+ ngx_http_core_main_conf_t *cmcf;
3177
+
3178
+ static ngx_str_t host = ngx_string("host");
3179
+
3180
+ h = ngx_list_push(&r->headers_in.headers);
3181
+ if (h == NULL) {
3182
+ return NGX_ERROR;
3183
+ }
3184
+
3185
+ h->hash = ngx_hash_key(host.data, host.len);
3186
+
3187
+ h->key.len = host.len;
3188
+ h->key.data = host.data;
3189
+
3190
+ h->value.len = header->value.len;
3191
+ h->value.data = header->value.data;
3192
+
3193
+ h->lowcase_key = host.data;
3194
+
3195
+ cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
3196
+
3197
+ hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
3198
+ h->lowcase_key, h->key.len);
3199
+
3200
+ if (hh == NULL) {
3201
+ return NGX_ERROR;
3202
+ }
3203
+
3204
+ if (hh->handler(r, h, hh->offset) != NGX_OK) {
3205
+ /*
3206
+ * request has been finalized already
3207
+ * in ngx_http_process_host()
3208
+ */
3209
+ return NGX_ABORT;
3210
+ }
3211
+
3212
+ return NGX_OK;
3213
+ }
3214
+
3215
+
3216
+ static ngx_int_t
3217
+ ngx_http_v2_construct_request_line(ngx_http_request_t *r)
3218
+ {
3219
+ u_char *p;
3220
+
3221
+ static const u_char ending[] = " HTTP/2.0";
3222
+
3223
+ if (r->method_name.len == 0
3224
+ || r->unparsed_uri.len == 0)
3225
+ {
3226
+ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
3227
+ return NGX_ERROR;
3228
+ }
3229
+
3230
+ r->request_line.len = r->method_name.len + 1
3231
+ + r->unparsed_uri.len
3232
+ + sizeof(ending) - 1;
3233
+
3234
+ p = ngx_pnalloc(r->pool, r->request_line.len + 1);
3235
+ if (p == NULL) {
3236
+ ngx_http_v2_close_stream(r->stream, NGX_HTTP_INTERNAL_SERVER_ERROR);
3237
+ return NGX_ERROR;
3238
+ }
3239
+
3240
+ r->request_line.data = p;
3241
+
3242
+ p = ngx_cpymem(p, r->method_name.data, r->method_name.len);
3243
+
3244
+ *p++ = ' ';
3245
+
3246
+ p = ngx_cpymem(p, r->unparsed_uri.data, r->unparsed_uri.len);
3247
+
3248
+ ngx_memcpy(p, ending, sizeof(ending));
3249
+
3250
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3251
+ "http2 http request line: \"%V\"", &r->request_line);
3252
+
3253
+ return NGX_OK;
3254
+ }
3255
+
3256
+
3257
+ static ngx_int_t
3258
+ ngx_http_v2_cookie(ngx_http_request_t *r, ngx_http_v2_header_t *header)
3259
+ {
3260
+ ngx_str_t *val;
3261
+ ngx_array_t *cookies;
3262
+
3263
+ cookies = r->stream->cookies;
3264
+
3265
+ if (cookies == NULL) {
3266
+ cookies = ngx_array_create(r->pool, 2, sizeof(ngx_str_t));
3267
+ if (cookies == NULL) {
3268
+ return NGX_ERROR;
3269
+ }
3270
+
3271
+ r->stream->cookies = cookies;
3272
+ }
3273
+
3274
+ val = ngx_array_push(cookies);
3275
+ if (val == NULL) {
3276
+ return NGX_ERROR;
3277
+ }
3278
+
3279
+ val->len = header->value.len;
3280
+ val->data = header->value.data;
3281
+
3282
+ return NGX_OK;
3283
+ }
3284
+
3285
+
3286
+ static ngx_int_t
3287
+ ngx_http_v2_construct_cookie_header(ngx_http_request_t *r)
3288
+ {
3289
+ u_char *buf, *p, *end;
3290
+ size_t len;
3291
+ ngx_str_t *vals;
3292
+ ngx_uint_t i;
3293
+ ngx_array_t *cookies;
3294
+ ngx_table_elt_t *h;
3295
+ ngx_http_header_t *hh;
3296
+ ngx_http_core_main_conf_t *cmcf;
3297
+
3298
+ static ngx_str_t cookie = ngx_string("cookie");
3299
+
3300
+ cookies = r->stream->cookies;
3301
+
3302
+ if (cookies == NULL) {
3303
+ return NGX_OK;
3304
+ }
3305
+
3306
+ vals = cookies->elts;
3307
+
3308
+ i = 0;
3309
+ len = 0;
3310
+
3311
+ do {
3312
+ len += vals[i].len + 2;
3313
+ } while (++i != cookies->nelts);
3314
+
3315
+ len -= 2;
3316
+
3317
+ buf = ngx_pnalloc(r->pool, len + 1);
3318
+ if (buf == NULL) {
3319
+ ngx_http_v2_close_stream(r->stream, NGX_HTTP_INTERNAL_SERVER_ERROR);
3320
+ return NGX_ERROR;
3321
+ }
3322
+
3323
+ p = buf;
3324
+ end = buf + len;
3325
+
3326
+ for (i = 0; /* void */ ; i++) {
3327
+
3328
+ p = ngx_cpymem(p, vals[i].data, vals[i].len);
3329
+
3330
+ if (p == end) {
3331
+ *p = '\0';
3332
+ break;
3333
+ }
3334
+
3335
+ *p++ = ';'; *p++ = ' ';
3336
+ }
3337
+
3338
+ h = ngx_list_push(&r->headers_in.headers);
3339
+ if (h == NULL) {
3340
+ ngx_http_v2_close_stream(r->stream, NGX_HTTP_INTERNAL_SERVER_ERROR);
3341
+ return NGX_ERROR;
3342
+ }
3343
+
3344
+ h->hash = ngx_hash_key(cookie.data, cookie.len);
3345
+
3346
+ h->key.len = cookie.len;
3347
+ h->key.data = cookie.data;
3348
+
3349
+ h->value.len = len;
3350
+ h->value.data = buf;
3351
+
3352
+ h->lowcase_key = cookie.data;
3353
+
3354
+ cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
3355
+
3356
+ hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
3357
+ h->lowcase_key, h->key.len);
3358
+
3359
+ if (hh == NULL) {
3360
+ ngx_http_v2_close_stream(r->stream, NGX_HTTP_INTERNAL_SERVER_ERROR);
3361
+ return NGX_ERROR;
3362
+ }
3363
+
3364
+ if (hh->handler(r, h, hh->offset) != NGX_OK) {
3365
+ /*
3366
+ * request has been finalized already
3367
+ * in ngx_http_process_multi_header_lines()
3368
+ */
3369
+ return NGX_ERROR;
3370
+ }
3371
+
3372
+ return NGX_OK;
3373
+ }
3374
+
3375
+
3376
+ static void
3377
+ ngx_http_v2_run_request(ngx_http_request_t *r)
3378
+ {
3379
+ if (ngx_http_v2_construct_request_line(r) != NGX_OK) {
3380
+ return;
3381
+ }
3382
+
3383
+ if (ngx_http_v2_construct_cookie_header(r) != NGX_OK) {
3384
+ return;
3385
+ }
3386
+
3387
+ r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
3388
+
3389
+ if (ngx_http_process_request_header(r) != NGX_OK) {
3390
+ return;
3391
+ }
3392
+
3393
+ if (r->headers_in.content_length_n > 0 && r->stream->in_closed) {
3394
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
3395
+ "client prematurely closed stream");
3396
+
3397
+ r->stream->skip_data = 1;
3398
+
3399
+ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
3400
+ return;
3401
+ }
3402
+
3403
+ r->headers_in.chunked = (r->headers_in.content_length_n == -1);
3404
+
3405
+ ngx_http_process_request(r);
3406
+ }
3407
+
3408
+
3409
+ ngx_int_t
3410
+ ngx_http_v2_read_request_body(ngx_http_request_t *r,
3411
+ ngx_http_client_body_handler_pt post_handler)
3412
+ {
3413
+ off_t len;
3414
+ ngx_http_v2_stream_t *stream;
3415
+ ngx_http_request_body_t *rb;
3416
+ ngx_http_core_loc_conf_t *clcf;
3417
+ ngx_http_v2_connection_t *h2c;
3418
+
3419
+ stream = r->stream;
3420
+
3421
+ if (stream->skip_data) {
3422
+ r->request_body_no_buffering = 0;
3423
+ post_handler(r);
3424
+ return NGX_OK;
3425
+ }
3426
+
3427
+ rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
3428
+ if (rb == NULL) {
3429
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
3430
+ }
3431
+
3432
+ /*
3433
+ * set by ngx_pcalloc():
3434
+ *
3435
+ * rb->bufs = NULL;
3436
+ * rb->buf = NULL;
3437
+ * rb->received = 0;
3438
+ * rb->free = NULL;
3439
+ * rb->busy = NULL;
3440
+ */
3441
+
3442
+ rb->rest = 1;
3443
+ rb->post_handler = post_handler;
3444
+
3445
+ r->request_body = rb;
3446
+
3447
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3448
+
3449
+ len = r->headers_in.content_length_n;
3450
+
3451
+ if (r->request_body_no_buffering && !stream->in_closed) {
3452
+ r->request_body_in_file_only = 0;
3453
+
3454
+ if (len < 0 || len > (off_t) clcf->client_body_buffer_size) {
3455
+ len = clcf->client_body_buffer_size;
3456
+ }
3457
+
3458
+ if (len > NGX_HTTP_V2_MAX_WINDOW) {
3459
+ len = NGX_HTTP_V2_MAX_WINDOW;
3460
+ }
3461
+ }
3462
+
3463
+ if (len >= 0 && len <= (off_t) clcf->client_body_buffer_size
3464
+ && !r->request_body_in_file_only)
3465
+ {
3466
+ rb->buf = ngx_create_temp_buf(r->pool, (size_t) len);
3467
+
3468
+ } else {
3469
+ rb->buf = ngx_calloc_buf(r->pool);
3470
+
3471
+ if (rb->buf != NULL) {
3472
+ rb->buf->sync = 1;
3473
+ }
3474
+ }
3475
+
3476
+ if (rb->buf == NULL) {
3477
+ stream->skip_data = 1;
3478
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
3479
+ }
3480
+
3481
+ if (stream->in_closed) {
3482
+ r->request_body_no_buffering = 0;
3483
+ return ngx_http_v2_process_request_body(r, NULL, 0, 1);
3484
+ }
3485
+
3486
+ if (len) {
3487
+ if (r->request_body_no_buffering) {
3488
+ stream->recv_window = (size_t) len;
3489
+
3490
+ } else {
3491
+ stream->no_flow_control = 1;
3492
+ stream->recv_window = NGX_HTTP_V2_MAX_WINDOW;
3493
+ }
3494
+
3495
+ if (ngx_http_v2_send_window_update(stream->connection, stream->node->id,
3496
+ stream->recv_window)
3497
+ == NGX_ERROR)
3498
+ {
3499
+ stream->skip_data = 1;
3500
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
3501
+ }
3502
+
3503
+ h2c = stream->connection;
3504
+
3505
+ if (!h2c->blocked) {
3506
+ if (ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) {
3507
+ stream->skip_data = 1;
3508
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
3509
+ }
3510
+ }
3511
+ }
3512
+
3513
+ ngx_add_timer(r->connection->read, clcf->client_body_timeout);
3514
+
3515
+ r->read_event_handler = ngx_http_v2_read_client_request_body_handler;
3516
+ r->write_event_handler = ngx_http_request_empty_handler;
3517
+
3518
+ return NGX_AGAIN;
3519
+ }
3520
+
3521
+
3522
+ static ngx_int_t
3523
+ ngx_http_v2_process_request_body(ngx_http_request_t *r, u_char *pos,
3524
+ size_t size, ngx_uint_t last)
3525
+ {
3526
+ ngx_buf_t *buf;
3527
+ ngx_int_t rc;
3528
+ ngx_connection_t *fc;
3529
+ ngx_http_request_body_t *rb;
3530
+ ngx_http_core_loc_conf_t *clcf;
3531
+
3532
+ rb = r->request_body;
3533
+
3534
+ if (rb == NULL) {
3535
+ return NGX_OK;
3536
+ }
3537
+
3538
+ fc = r->connection;
3539
+ buf = rb->buf;
3540
+
3541
+ if (size) {
3542
+ if (buf->sync) {
3543
+ buf->pos = buf->start = pos;
3544
+ buf->last = buf->end = pos + size;
3545
+
3546
+ } else {
3547
+ if (size > (size_t) (buf->end - buf->last)) {
3548
+ ngx_log_error(NGX_LOG_INFO, fc->log, 0,
3549
+ "client intended to send body data "
3550
+ "larger than declared");
3551
+
3552
+ return NGX_HTTP_BAD_REQUEST;
3553
+ }
3554
+
3555
+ buf->last = ngx_cpymem(buf->last, pos, size);
3556
+ }
3557
+ }
3558
+
3559
+ if (last) {
3560
+ rb->rest = 0;
3561
+
3562
+ if (fc->read->timer_set) {
3563
+ ngx_del_timer(fc->read);
3564
+ }
3565
+
3566
+ if (r->request_body_no_buffering) {
3567
+ ngx_post_event(fc->read, &ngx_posted_events);
3568
+ return NGX_OK;
3569
+ }
3570
+
3571
+ rc = ngx_http_v2_filter_request_body(r);
3572
+
3573
+ if (rc != NGX_OK) {
3574
+ return rc;
3575
+ }
3576
+
3577
+ if (buf->sync) {
3578
+ /* prevent reusing this buffer in the upstream module */
3579
+ rb->buf = NULL;
3580
+ }
3581
+
3582
+ if (r->headers_in.content_length_n == -1) {
3583
+ r->headers_in.content_length_n = rb->received;
3584
+ }
3585
+
3586
+ r->read_event_handler = ngx_http_block_reading;
3587
+ rb->post_handler(r);
3588
+
3589
+ return NGX_OK;
3590
+ }
3591
+
3592
+ if (size == 0) {
3593
+ return NGX_OK;
3594
+ }
3595
+
3596
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3597
+ ngx_add_timer(fc->read, clcf->client_body_timeout);
3598
+
3599
+ if (r->request_body_no_buffering) {
3600
+ ngx_post_event(fc->read, &ngx_posted_events);
3601
+ return NGX_OK;
3602
+ }
3603
+
3604
+ if (buf->sync) {
3605
+ return ngx_http_v2_filter_request_body(r);
3606
+ }
3607
+
3608
+ return NGX_OK;
3609
+ }
3610
+
3611
+
3612
+ static ngx_int_t
3613
+ ngx_http_v2_filter_request_body(ngx_http_request_t *r)
3614
+ {
3615
+ ngx_buf_t *b, *buf;
3616
+ ngx_int_t rc;
3617
+ ngx_chain_t *cl;
3618
+ ngx_http_request_body_t *rb;
3619
+ ngx_http_core_loc_conf_t *clcf;
3620
+
3621
+ rb = r->request_body;
3622
+ buf = rb->buf;
3623
+
3624
+ if (buf->pos == buf->last && rb->rest) {
3625
+ cl = NULL;
3626
+ goto update;
3627
+ }
3628
+
3629
+ cl = ngx_chain_get_free_buf(r->pool, &rb->free);
3630
+ if (cl == NULL) {
3631
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
3632
+ }
3633
+
3634
+ b = cl->buf;
3635
+
3636
+ ngx_memzero(b, sizeof(ngx_buf_t));
3637
+
3638
+ if (buf->pos != buf->last) {
3639
+ r->request_length += buf->last - buf->pos;
3640
+ rb->received += buf->last - buf->pos;
3641
+
3642
+ if (r->headers_in.content_length_n != -1) {
3643
+ if (rb->received > r->headers_in.content_length_n) {
3644
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
3645
+ "client intended to send body data "
3646
+ "larger than declared");
3647
+
3648
+ return NGX_HTTP_BAD_REQUEST;
3649
+ }
3650
+
3651
+ } else {
3652
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3653
+
3654
+ if (clcf->client_max_body_size
3655
+ && rb->received > clcf->client_max_body_size)
3656
+ {
3657
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
3658
+ "client intended to send too large chunked body: "
3659
+ "%O bytes", rb->received);
3660
+
3661
+ return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
3662
+ }
3663
+ }
3664
+
3665
+ b->temporary = 1;
3666
+ b->pos = buf->pos;
3667
+ b->last = buf->last;
3668
+ b->start = b->pos;
3669
+ b->end = b->last;
3670
+
3671
+ buf->pos = buf->last;
3672
+ }
3673
+
3674
+ if (!rb->rest) {
3675
+ if (r->headers_in.content_length_n != -1
3676
+ && r->headers_in.content_length_n != rb->received)
3677
+ {
3678
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
3679
+ "client prematurely closed stream: "
3680
+ "only %O out of %O bytes of request body received",
3681
+ rb->received, r->headers_in.content_length_n);
3682
+
3683
+ return NGX_HTTP_BAD_REQUEST;
3684
+ }
3685
+
3686
+ b->last_buf = 1;
3687
+ }
3688
+
3689
+ b->tag = (ngx_buf_tag_t) &ngx_http_v2_filter_request_body;
3690
+ b->flush = r->request_body_no_buffering;
3691
+
3692
+ update:
3693
+
3694
+ rc = ngx_http_top_request_body_filter(r, cl);
3695
+
3696
+ ngx_chain_update_chains(r->pool, &rb->free, &rb->busy, &cl,
3697
+ (ngx_buf_tag_t) &ngx_http_v2_filter_request_body);
3698
+
3699
+ return rc;
3700
+ }
3701
+
3702
+
3703
+ static void
3704
+ ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r)
3705
+ {
3706
+ ngx_connection_t *fc;
3707
+
3708
+ fc = r->connection;
3709
+
3710
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
3711
+ "http2 read client request body handler");
3712
+
3713
+ if (fc->read->timedout) {
3714
+ ngx_log_error(NGX_LOG_INFO, fc->log, NGX_ETIMEDOUT, "client timed out");
3715
+
3716
+ fc->timedout = 1;
3717
+ r->stream->skip_data = 1;
3718
+
3719
+ ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
3720
+ return;
3721
+ }
3722
+
3723
+ if (fc->error) {
3724
+ ngx_log_error(NGX_LOG_INFO, fc->log, 0,
3725
+ "client prematurely closed stream");
3726
+
3727
+ r->stream->skip_data = 1;
3728
+
3729
+ ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST);
3730
+ return;
3731
+ }
3732
+ }
3733
+
3734
+
3735
+ ngx_int_t
3736
+ ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r)
3737
+ {
3738
+ size_t window;
3739
+ ngx_buf_t *buf;
3740
+ ngx_int_t rc;
3741
+ ngx_connection_t *fc;
3742
+ ngx_http_v2_stream_t *stream;
3743
+ ngx_http_v2_connection_t *h2c;
3744
+ ngx_http_core_loc_conf_t *clcf;
3745
+
3746
+ stream = r->stream;
3747
+ fc = r->connection;
3748
+
3749
+ if (fc->read->timedout) {
3750
+ if (stream->recv_window) {
3751
+ stream->skip_data = 1;
3752
+ fc->timedout = 1;
3753
+
3754
+ return NGX_HTTP_REQUEST_TIME_OUT;
3755
+ }
3756
+
3757
+ fc->read->timedout = 0;
3758
+ }
3759
+
3760
+ if (fc->error) {
3761
+ stream->skip_data = 1;
3762
+ return NGX_HTTP_BAD_REQUEST;
3763
+ }
3764
+
3765
+ rc = ngx_http_v2_filter_request_body(r);
3766
+
3767
+ if (rc != NGX_OK) {
3768
+ stream->skip_data = 1;
3769
+ return rc;
3770
+ }
3771
+
3772
+ if (!r->request_body->rest) {
3773
+ return NGX_OK;
3774
+ }
3775
+
3776
+ if (r->request_body->busy != NULL) {
3777
+ return NGX_AGAIN;
3778
+ }
3779
+
3780
+ buf = r->request_body->buf;
3781
+
3782
+ buf->pos = buf->start;
3783
+ buf->last = buf->start;
3784
+
3785
+ window = buf->end - buf->start;
3786
+ h2c = stream->connection;
3787
+
3788
+ if (h2c->state.stream == stream) {
3789
+ window -= h2c->state.length;
3790
+ }
3791
+
3792
+ if (window == stream->recv_window) {
3793
+ return NGX_AGAIN;
3794
+ }
3795
+
3796
+ if (ngx_http_v2_send_window_update(h2c, stream->node->id,
3797
+ window - stream->recv_window)
3798
+ == NGX_ERROR)
3799
+ {
3800
+ stream->skip_data = 1;
3801
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
3802
+ }
3803
+
3804
+ if (ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) {
3805
+ stream->skip_data = 1;
3806
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
3807
+ }
3808
+
3809
+ if (stream->recv_window == 0) {
3810
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3811
+ ngx_add_timer(fc->read, clcf->client_body_timeout);
3812
+ }
3813
+
3814
+ stream->recv_window = window;
3815
+
3816
+ return NGX_AGAIN;
3817
+ }
3818
+
3819
+
3820
+ static ngx_int_t
3821
+ ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c,
3822
+ ngx_http_v2_stream_t *stream, ngx_uint_t status)
3823
+ {
3824
+ ngx_event_t *rev;
3825
+ ngx_connection_t *fc;
3826
+
3827
+ if (ngx_http_v2_send_rst_stream(h2c, stream->node->id, status)
3828
+ == NGX_ERROR)
3829
+ {
3830
+ return NGX_ERROR;
3831
+ }
3832
+
3833
+ stream->rst_sent = 1;
3834
+
3835
+ fc = stream->request->connection;
3836
+ fc->error = 1;
3837
+
3838
+ rev = fc->read;
3839
+ rev->handler(rev);
3840
+
3841
+ return NGX_OK;
3842
+ }
3843
+
3844
+
3845
+ void
3846
+ ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc)
3847
+ {
3848
+ ngx_pool_t *pool;
3849
+ ngx_event_t *ev;
3850
+ ngx_connection_t *fc;
3851
+ ngx_http_v2_node_t *node;
3852
+ ngx_http_v2_connection_t *h2c;
3853
+
3854
+ h2c = stream->connection;
3855
+ node = stream->node;
3856
+
3857
+ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
3858
+ "http2 close stream %ui, queued %ui, processing %ui",
3859
+ node->id, stream->queued, h2c->processing);
3860
+
3861
+ fc = stream->request->connection;
3862
+
3863
+ if (stream->queued) {
3864
+ fc->write->handler = ngx_http_v2_close_stream_handler;
3865
+ return;
3866
+ }
3867
+
3868
+ if (!stream->rst_sent && !h2c->connection->error) {
3869
+
3870
+ if (!stream->out_closed) {
3871
+ if (ngx_http_v2_send_rst_stream(h2c, node->id,
3872
+ fc->timedout ? NGX_HTTP_V2_PROTOCOL_ERROR
3873
+ : NGX_HTTP_V2_INTERNAL_ERROR)
3874
+ != NGX_OK)
3875
+ {
3876
+ h2c->connection->error = 1;
3877
+ }
3878
+
3879
+ } else if (!stream->in_closed) {
3880
+ #if 0
3881
+ if (ngx_http_v2_send_rst_stream(h2c, node->id, NGX_HTTP_V2_NO_ERROR)
3882
+ != NGX_OK)
3883
+ {
3884
+ h2c->connection->error = 1;
3885
+ }
3886
+ #else
3887
+ /*
3888
+ * At the time of writing at least the latest versions of Chrome
3889
+ * do not properly handle RST_STREAM with NO_ERROR status.
3890
+ *
3891
+ * See: https://bugs.chromium.org/p/chromium/issues/detail?id=603182
3892
+ *
3893
+ * As a workaround, the stream window is maximized before closing
3894
+ * the stream. This allows a client to send up to 2 GB of data
3895
+ * before getting blocked on flow control.
3896
+ */
3897
+
3898
+ if (stream->recv_window < NGX_HTTP_V2_MAX_WINDOW
3899
+ && ngx_http_v2_send_window_update(h2c, node->id,
3900
+ NGX_HTTP_V2_MAX_WINDOW
3901
+ - stream->recv_window)
3902
+ != NGX_OK)
3903
+ {
3904
+ h2c->connection->error = 1;
3905
+ }
3906
+ #endif
3907
+ }
3908
+ }
3909
+
3910
+ if (h2c->state.stream == stream) {
3911
+ h2c->state.stream = NULL;
3912
+ }
3913
+
3914
+ node->stream = NULL;
3915
+
3916
+ ngx_queue_insert_tail(&h2c->closed, &node->reuse);
3917
+ h2c->closed_nodes++;
3918
+
3919
+ /*
3920
+ * This pool keeps decoded request headers which can be used by log phase
3921
+ * handlers in ngx_http_free_request().
3922
+ *
3923
+ * The pointer is stored into local variable because the stream object
3924
+ * will be destroyed after a call to ngx_http_free_request().
3925
+ */
3926
+ pool = stream->pool;
3927
+
3928
+ ngx_http_free_request(stream->request, rc);
3929
+
3930
+ if (pool != h2c->state.pool) {
3931
+ ngx_destroy_pool(pool);
3932
+
3933
+ } else {
3934
+ /* pool will be destroyed when the complete header is parsed */
3935
+ h2c->state.keep_pool = 0;
3936
+ }
3937
+
3938
+ ev = fc->read;
3939
+
3940
+ if (ev->timer_set) {
3941
+ ngx_del_timer(ev);
3942
+ }
3943
+
3944
+ if (ev->posted) {
3945
+ ngx_delete_posted_event(ev);
3946
+ }
3947
+
3948
+ ev = fc->write;
3949
+
3950
+ if (ev->timer_set) {
3951
+ ngx_del_timer(ev);
3952
+ }
3953
+
3954
+ if (ev->posted) {
3955
+ ngx_delete_posted_event(ev);
3956
+ }
3957
+
3958
+ fc->data = h2c->free_fake_connections;
3959
+ h2c->free_fake_connections = fc;
3960
+
3961
+ h2c->processing--;
3962
+
3963
+ if (h2c->processing || h2c->blocked) {
3964
+ return;
3965
+ }
3966
+
3967
+ ev = h2c->connection->read;
3968
+
3969
+ ev->handler = ngx_http_v2_handle_connection_handler;
3970
+ ngx_post_event(ev, &ngx_posted_events);
3971
+ }
3972
+
3973
+
3974
+ static void
3975
+ ngx_http_v2_close_stream_handler(ngx_event_t *ev)
3976
+ {
3977
+ ngx_connection_t *fc;
3978
+ ngx_http_request_t *r;
3979
+
3980
+ fc = ev->data;
3981
+ r = fc->data;
3982
+
3983
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
3984
+ "http2 close stream handler");
3985
+
3986
+ if (ev->timedout) {
3987
+ ngx_log_error(NGX_LOG_INFO, fc->log, NGX_ETIMEDOUT, "client timed out");
3988
+
3989
+ fc->timedout = 1;
3990
+
3991
+ ngx_http_v2_close_stream(r->stream, NGX_HTTP_REQUEST_TIME_OUT);
3992
+ return;
3993
+ }
3994
+
3995
+ ngx_http_v2_close_stream(r->stream, 0);
3996
+ }
3997
+
3998
+
3999
+ static void
4000
+ ngx_http_v2_handle_connection_handler(ngx_event_t *rev)
4001
+ {
4002
+ ngx_connection_t *c;
4003
+ ngx_http_v2_connection_t *h2c;
4004
+
4005
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
4006
+ "http2 handle connection handler");
4007
+
4008
+ rev->handler = ngx_http_v2_read_handler;
4009
+
4010
+ if (rev->ready) {
4011
+ ngx_http_v2_read_handler(rev);
4012
+ return;
4013
+ }
4014
+
4015
+ c = rev->data;
4016
+ h2c = c->data;
4017
+
4018
+ if (h2c->last_out && ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) {
4019
+ ngx_http_v2_finalize_connection(h2c, 0);
4020
+ return;
4021
+ }
4022
+
4023
+ ngx_http_v2_handle_connection(c->data);
4024
+ }
4025
+
4026
+
4027
+ static void
4028
+ ngx_http_v2_idle_handler(ngx_event_t *rev)
4029
+ {
4030
+ ngx_connection_t *c;
4031
+ ngx_http_v2_srv_conf_t *h2scf;
4032
+ ngx_http_v2_connection_t *h2c;
4033
+
4034
+ c = rev->data;
4035
+ h2c = c->data;
4036
+
4037
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http2 idle handler");
4038
+
4039
+ if (rev->timedout || c->close) {
4040
+ ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR);
4041
+ return;
4042
+ }
4043
+
4044
+ #if (NGX_HAVE_KQUEUE)
4045
+
4046
+ if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
4047
+ if (rev->pending_eof) {
4048
+ c->log->handler = NULL;
4049
+ ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
4050
+ "kevent() reported that client %V closed "
4051
+ "idle connection", &c->addr_text);
4052
+ #if (NGX_HTTP_SSL)
4053
+ if (c->ssl) {
4054
+ c->ssl->no_send_shutdown = 1;
4055
+ }
4056
+ #endif
4057
+ ngx_http_close_connection(c);
4058
+ return;
4059
+ }
4060
+ }
4061
+
4062
+ #endif
4063
+
4064
+ c->destroyed = 0;
4065
+ c->idle = 0;
4066
+ ngx_reusable_connection(c, 0);
4067
+
4068
+ h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
4069
+ ngx_http_v2_module);
4070
+
4071
+ h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log);
4072
+ if (h2c->pool == NULL) {
4073
+ ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
4074
+ return;
4075
+ }
4076
+
4077
+ c->write->handler = ngx_http_v2_write_handler;
4078
+
4079
+ rev->handler = ngx_http_v2_read_handler;
4080
+ ngx_http_v2_read_handler(rev);
4081
+ }
4082
+
4083
+
4084
+ static void
4085
+ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c,
4086
+ ngx_uint_t status)
4087
+ {
4088
+ ngx_uint_t i, size;
4089
+ ngx_event_t *ev;
4090
+ ngx_connection_t *c, *fc;
4091
+ ngx_http_request_t *r;
4092
+ ngx_http_v2_node_t *node;
4093
+ ngx_http_v2_stream_t *stream;
4094
+ ngx_http_v2_srv_conf_t *h2scf;
4095
+
4096
+ c = h2c->connection;
4097
+
4098
+ h2c->blocked = 1;
4099
+
4100
+ if (!c->error && ngx_http_v2_send_goaway(h2c, status) != NGX_ERROR) {
4101
+ (void) ngx_http_v2_send_output_queue(h2c);
4102
+ }
4103
+
4104
+ c->error = 1;
4105
+
4106
+ if (h2c->state.stream) {
4107
+ ngx_http_v2_close_stream(h2c->state.stream, NGX_HTTP_BAD_REQUEST);
4108
+ }
4109
+
4110
+ if (!h2c->processing) {
4111
+ ngx_http_close_connection(c);
4112
+ return;
4113
+ }
4114
+
4115
+ c->read->handler = ngx_http_empty_handler;
4116
+ c->write->handler = ngx_http_empty_handler;
4117
+
4118
+ h2c->last_out = NULL;
4119
+
4120
+ h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
4121
+ ngx_http_v2_module);
4122
+
4123
+ size = ngx_http_v2_index_size(h2scf);
4124
+
4125
+ for (i = 0; i < size; i++) {
4126
+
4127
+ for (node = h2c->streams_index[i]; node; node = node->index) {
4128
+ stream = node->stream;
4129
+
4130
+ if (stream == NULL) {
4131
+ continue;
4132
+ }
4133
+
4134
+ stream->handled = 0;
4135
+
4136
+ r = stream->request;
4137
+ fc = r->connection;
4138
+
4139
+ fc->error = 1;
4140
+
4141
+ if (stream->queued) {
4142
+ stream->queued = 0;
4143
+ ev = fc->write;
4144
+
4145
+ } else {
4146
+ ev = fc->read;
4147
+ }
4148
+
4149
+ ev->eof = 1;
4150
+ ev->handler(ev);
4151
+ }
4152
+ }
4153
+
4154
+ h2c->blocked = 0;
4155
+
4156
+ if (h2c->processing) {
4157
+ return;
4158
+ }
4159
+
4160
+ ngx_http_close_connection(c);
4161
+ }
4162
+
4163
+
4164
+ static ngx_int_t
4165
+ ngx_http_v2_adjust_windows(ngx_http_v2_connection_t *h2c, ssize_t delta)
4166
+ {
4167
+ ngx_uint_t i, size;
4168
+ ngx_event_t *wev;
4169
+ ngx_http_v2_node_t *node;
4170
+ ngx_http_v2_stream_t *stream;
4171
+ ngx_http_v2_srv_conf_t *h2scf;
4172
+
4173
+ h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
4174
+ ngx_http_v2_module);
4175
+
4176
+ size = ngx_http_v2_index_size(h2scf);
4177
+
4178
+ for (i = 0; i < size; i++) {
4179
+
4180
+ for (node = h2c->streams_index[i]; node; node = node->index) {
4181
+ stream = node->stream;
4182
+
4183
+ if (stream == NULL) {
4184
+ continue;
4185
+ }
4186
+
4187
+ if (delta > 0
4188
+ && stream->send_window
4189
+ > (ssize_t) (NGX_HTTP_V2_MAX_WINDOW - delta))
4190
+ {
4191
+ if (ngx_http_v2_terminate_stream(h2c, stream,
4192
+ NGX_HTTP_V2_FLOW_CTRL_ERROR)
4193
+ == NGX_ERROR)
4194
+ {
4195
+ return NGX_ERROR;
4196
+ }
4197
+
4198
+ continue;
4199
+ }
4200
+
4201
+ stream->send_window += delta;
4202
+
4203
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
4204
+ "http2:%ui adjusted window: %z",
4205
+ node->id, stream->send_window);
4206
+
4207
+ if (stream->send_window > 0 && stream->exhausted) {
4208
+ stream->exhausted = 0;
4209
+
4210
+ wev = stream->request->connection->write;
4211
+
4212
+ wev->active = 0;
4213
+ wev->ready = 1;
4214
+
4215
+ if (!wev->delayed) {
4216
+ wev->handler(wev);
4217
+ }
4218
+ }
4219
+ }
4220
+ }
4221
+
4222
+ return NGX_OK;
4223
+ }
4224
+
4225
+
4226
+ static void
4227
+ ngx_http_v2_set_dependency(ngx_http_v2_connection_t *h2c,
4228
+ ngx_http_v2_node_t *node, ngx_uint_t depend, ngx_uint_t exclusive)
4229
+ {
4230
+ ngx_queue_t *children, *q;
4231
+ ngx_http_v2_node_t *parent, *child, *next;
4232
+
4233
+ parent = depend ? ngx_http_v2_get_node_by_id(h2c, depend, 0) : NULL;
4234
+
4235
+ if (parent == NULL) {
4236
+ parent = NGX_HTTP_V2_ROOT;
4237
+
4238
+ if (depend != 0) {
4239
+ exclusive = 0;
4240
+ }
4241
+
4242
+ node->rank = 1;
4243
+ node->rel_weight = (1.0 / 256) * node->weight;
4244
+
4245
+ children = &h2c->dependencies;
4246
+
4247
+ } else {
4248
+ if (node->parent != NULL) {
4249
+
4250
+ for (next = parent->parent;
4251
+ next != NGX_HTTP_V2_ROOT && next->rank >= node->rank;
4252
+ next = next->parent)
4253
+ {
4254
+ if (next != node) {
4255
+ continue;
4256
+ }
4257
+
4258
+ ngx_queue_remove(&parent->queue);
4259
+ ngx_queue_insert_after(&node->queue, &parent->queue);
4260
+
4261
+ parent->parent = node->parent;
4262
+
4263
+ if (node->parent == NGX_HTTP_V2_ROOT) {
4264
+ parent->rank = 1;
4265
+ parent->rel_weight = (1.0 / 256) * parent->weight;
4266
+
4267
+ } else {
4268
+ parent->rank = node->parent->rank + 1;
4269
+ parent->rel_weight = (node->parent->rel_weight / 256)
4270
+ * parent->weight;
4271
+ }
4272
+
4273
+ if (!exclusive) {
4274
+ ngx_http_v2_node_children_update(parent);
4275
+ }
4276
+
4277
+ break;
4278
+ }
4279
+ }
4280
+
4281
+ node->rank = parent->rank + 1;
4282
+ node->rel_weight = (parent->rel_weight / 256) * node->weight;
4283
+
4284
+ if (parent->stream == NULL) {
4285
+ ngx_queue_remove(&parent->reuse);
4286
+ ngx_queue_insert_tail(&h2c->closed, &parent->reuse);
4287
+ }
4288
+
4289
+ children = &parent->children;
4290
+ }
4291
+
4292
+ if (exclusive) {
4293
+ for (q = ngx_queue_head(children);
4294
+ q != ngx_queue_sentinel(children);
4295
+ q = ngx_queue_next(q))
4296
+ {
4297
+ child = ngx_queue_data(q, ngx_http_v2_node_t, queue);
4298
+ child->parent = node;
4299
+ }
4300
+
4301
+ ngx_queue_add(&node->children, children);
4302
+ ngx_queue_init(children);
4303
+ }
4304
+
4305
+ if (node->parent != NULL) {
4306
+ ngx_queue_remove(&node->queue);
4307
+ }
4308
+
4309
+ ngx_queue_insert_tail(children, &node->queue);
4310
+
4311
+ node->parent = parent;
4312
+
4313
+ ngx_http_v2_node_children_update(node);
4314
+ }
4315
+
4316
+
4317
+ static void
4318
+ ngx_http_v2_node_children_update(ngx_http_v2_node_t *node)
4319
+ {
4320
+ ngx_queue_t *q;
4321
+ ngx_http_v2_node_t *child;
4322
+
4323
+ for (q = ngx_queue_head(&node->children);
4324
+ q != ngx_queue_sentinel(&node->children);
4325
+ q = ngx_queue_next(q))
4326
+ {
4327
+ child = ngx_queue_data(q, ngx_http_v2_node_t, queue);
4328
+
4329
+ child->rank = node->rank + 1;
4330
+ child->rel_weight = (node->rel_weight / 256) * child->weight;
4331
+
4332
+ ngx_http_v2_node_children_update(child);
4333
+ }
4334
+ }
4335
+
4336
+
4337
+ static void
4338
+ ngx_http_v2_pool_cleanup(void *data)
4339
+ {
4340
+ ngx_http_v2_connection_t *h2c = data;
4341
+
4342
+ if (h2c->state.pool) {
4343
+ ngx_destroy_pool(h2c->state.pool);
4344
+ }
4345
+
4346
+ if (h2c->pool) {
4347
+ ngx_destroy_pool(h2c->pool);
4348
+ }
4349
+ }