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
@@ -0,0 +1,337 @@
1
+ /*
2
+ * Copyright (C) Nginx, Inc.
3
+ * Copyright (C) Valentin V. Bartenev
4
+ */
5
+
6
+
7
+ #ifndef _NGX_HTTP_V2_H_INCLUDED_
8
+ #define _NGX_HTTP_V2_H_INCLUDED_
9
+
10
+
11
+ #include <ngx_config.h>
12
+ #include <ngx_core.h>
13
+ #include <ngx_http.h>
14
+
15
+
16
+ #define NGX_HTTP_V2_ALPN_ADVERTISE "\x02h2"
17
+ #define NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_V2_ALPN_ADVERTISE
18
+
19
+ #define NGX_HTTP_V2_STATE_BUFFER_SIZE 16
20
+
21
+ #define NGX_HTTP_V2_MAX_FRAME_SIZE ((1 << 24) - 1)
22
+
23
+ #define NGX_HTTP_V2_INT_OCTETS 4
24
+ #define NGX_HTTP_V2_MAX_FIELD \
25
+ (127 + (1 << (NGX_HTTP_V2_INT_OCTETS - 1) * 7) - 1)
26
+
27
+ #define NGX_HTTP_V2_FRAME_HEADER_SIZE 9
28
+
29
+ /* frame types */
30
+ #define NGX_HTTP_V2_DATA_FRAME 0x0
31
+ #define NGX_HTTP_V2_HEADERS_FRAME 0x1
32
+ #define NGX_HTTP_V2_PRIORITY_FRAME 0x2
33
+ #define NGX_HTTP_V2_RST_STREAM_FRAME 0x3
34
+ #define NGX_HTTP_V2_SETTINGS_FRAME 0x4
35
+ #define NGX_HTTP_V2_PUSH_PROMISE_FRAME 0x5
36
+ #define NGX_HTTP_V2_PING_FRAME 0x6
37
+ #define NGX_HTTP_V2_GOAWAY_FRAME 0x7
38
+ #define NGX_HTTP_V2_WINDOW_UPDATE_FRAME 0x8
39
+ #define NGX_HTTP_V2_CONTINUATION_FRAME 0x9
40
+
41
+ /* frame flags */
42
+ #define NGX_HTTP_V2_NO_FLAG 0x00
43
+ #define NGX_HTTP_V2_ACK_FLAG 0x01
44
+ #define NGX_HTTP_V2_END_STREAM_FLAG 0x01
45
+ #define NGX_HTTP_V2_END_HEADERS_FLAG 0x04
46
+ #define NGX_HTTP_V2_PADDED_FLAG 0x08
47
+ #define NGX_HTTP_V2_PRIORITY_FLAG 0x20
48
+
49
+
50
+ typedef struct ngx_http_v2_connection_s ngx_http_v2_connection_t;
51
+ typedef struct ngx_http_v2_node_s ngx_http_v2_node_t;
52
+ typedef struct ngx_http_v2_out_frame_s ngx_http_v2_out_frame_t;
53
+
54
+
55
+ typedef u_char *(*ngx_http_v2_handler_pt) (ngx_http_v2_connection_t *h2c,
56
+ u_char *pos, u_char *end);
57
+
58
+
59
+ typedef struct {
60
+ ngx_str_t name;
61
+ ngx_str_t value;
62
+ } ngx_http_v2_header_t;
63
+
64
+
65
+ typedef struct {
66
+ ngx_uint_t sid;
67
+ size_t length;
68
+ size_t padding;
69
+ unsigned flags:8;
70
+
71
+ unsigned incomplete:1;
72
+ unsigned keep_pool:1;
73
+
74
+ /* HPACK */
75
+ unsigned parse_name:1;
76
+ unsigned parse_value:1;
77
+ unsigned index:1;
78
+ ngx_http_v2_header_t header;
79
+ size_t header_limit;
80
+ u_char field_state;
81
+ u_char *field_start;
82
+ u_char *field_end;
83
+ size_t field_rest;
84
+ ngx_pool_t *pool;
85
+
86
+ ngx_http_v2_stream_t *stream;
87
+
88
+ u_char buffer[NGX_HTTP_V2_STATE_BUFFER_SIZE];
89
+ size_t buffer_used;
90
+ ngx_http_v2_handler_pt handler;
91
+ } ngx_http_v2_state_t;
92
+
93
+
94
+
95
+ typedef struct {
96
+ ngx_http_v2_header_t **entries;
97
+
98
+ ngx_uint_t added;
99
+ ngx_uint_t deleted;
100
+ ngx_uint_t reused;
101
+ ngx_uint_t allocated;
102
+
103
+ size_t size;
104
+ size_t free;
105
+ u_char *storage;
106
+ u_char *pos;
107
+ } ngx_http_v2_hpack_t;
108
+
109
+
110
+ struct ngx_http_v2_connection_s {
111
+ ngx_connection_t *connection;
112
+ ngx_http_connection_t *http_connection;
113
+
114
+ ngx_uint_t processing;
115
+
116
+ size_t send_window;
117
+ size_t recv_window;
118
+ size_t init_window;
119
+
120
+ size_t frame_size;
121
+
122
+ ngx_queue_t waiting;
123
+
124
+ ngx_http_v2_state_t state;
125
+
126
+ ngx_http_v2_hpack_t hpack;
127
+
128
+ ngx_pool_t *pool;
129
+
130
+ ngx_http_v2_out_frame_t *free_frames;
131
+ ngx_connection_t *free_fake_connections;
132
+
133
+ ngx_http_v2_node_t **streams_index;
134
+
135
+ ngx_http_v2_out_frame_t *last_out;
136
+
137
+ ngx_queue_t posted;
138
+ ngx_queue_t dependencies;
139
+ ngx_queue_t closed;
140
+
141
+ ngx_uint_t last_sid;
142
+
143
+ unsigned closed_nodes:8;
144
+ unsigned settings_ack:1;
145
+ unsigned blocked:1;
146
+ };
147
+
148
+
149
+ struct ngx_http_v2_node_s {
150
+ ngx_uint_t id;
151
+ ngx_http_v2_node_t *index;
152
+ ngx_http_v2_node_t *parent;
153
+ ngx_queue_t queue;
154
+ ngx_queue_t children;
155
+ ngx_queue_t reuse;
156
+ ngx_uint_t rank;
157
+ ngx_uint_t weight;
158
+ double rel_weight;
159
+ ngx_http_v2_stream_t *stream;
160
+ };
161
+
162
+
163
+ struct ngx_http_v2_stream_s {
164
+ ngx_http_request_t *request;
165
+ ngx_http_v2_connection_t *connection;
166
+ ngx_http_v2_node_t *node;
167
+
168
+ ngx_uint_t queued;
169
+
170
+ /*
171
+ * A change to SETTINGS_INITIAL_WINDOW_SIZE could cause the
172
+ * send_window to become negative, hence it's signed.
173
+ */
174
+ ssize_t send_window;
175
+ size_t recv_window;
176
+
177
+ ngx_http_v2_out_frame_t *free_frames;
178
+ ngx_chain_t *free_frame_headers;
179
+ ngx_chain_t *free_bufs;
180
+
181
+ ngx_queue_t queue;
182
+
183
+ ngx_array_t *cookies;
184
+
185
+ size_t header_limit;
186
+
187
+ ngx_pool_t *pool;
188
+
189
+ unsigned handled:1;
190
+ unsigned blocked:1;
191
+ unsigned exhausted:1;
192
+ unsigned in_closed:1;
193
+ unsigned out_closed:1;
194
+ unsigned rst_sent:1;
195
+ unsigned no_flow_control:1;
196
+ unsigned skip_data:1;
197
+ };
198
+
199
+
200
+ struct ngx_http_v2_out_frame_s {
201
+ ngx_http_v2_out_frame_t *next;
202
+ ngx_chain_t *first;
203
+ ngx_chain_t *last;
204
+ ngx_int_t (*handler)(ngx_http_v2_connection_t *h2c,
205
+ ngx_http_v2_out_frame_t *frame);
206
+
207
+ ngx_http_v2_stream_t *stream;
208
+ size_t length;
209
+
210
+ unsigned blocked:1;
211
+ unsigned fin:1;
212
+ };
213
+
214
+
215
+ static ngx_inline void
216
+ ngx_http_v2_queue_frame(ngx_http_v2_connection_t *h2c,
217
+ ngx_http_v2_out_frame_t *frame)
218
+ {
219
+ ngx_http_v2_out_frame_t **out;
220
+
221
+ for (out = &h2c->last_out; *out; out = &(*out)->next) {
222
+
223
+ if ((*out)->blocked || (*out)->stream == NULL) {
224
+ break;
225
+ }
226
+
227
+ if ((*out)->stream->node->rank < frame->stream->node->rank
228
+ || ((*out)->stream->node->rank == frame->stream->node->rank
229
+ && (*out)->stream->node->rel_weight
230
+ >= frame->stream->node->rel_weight))
231
+ {
232
+ break;
233
+ }
234
+ }
235
+
236
+ frame->next = *out;
237
+ *out = frame;
238
+ }
239
+
240
+
241
+ static ngx_inline void
242
+ ngx_http_v2_queue_blocked_frame(ngx_http_v2_connection_t *h2c,
243
+ ngx_http_v2_out_frame_t *frame)
244
+ {
245
+ ngx_http_v2_out_frame_t **out;
246
+
247
+ for (out = &h2c->last_out; *out; out = &(*out)->next)
248
+ {
249
+ if ((*out)->blocked || (*out)->stream == NULL) {
250
+ break;
251
+ }
252
+ }
253
+
254
+ frame->next = *out;
255
+ *out = frame;
256
+ }
257
+
258
+
259
+ void ngx_http_v2_init(ngx_event_t *rev);
260
+ void ngx_http_v2_request_headers_init(void);
261
+
262
+ ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r,
263
+ ngx_http_client_body_handler_pt post_handler);
264
+ ngx_int_t ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r);
265
+
266
+ void ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc);
267
+
268
+ ngx_int_t ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c);
269
+
270
+
271
+ ngx_int_t ngx_http_v2_get_indexed_header(ngx_http_v2_connection_t *h2c,
272
+ ngx_uint_t index, ngx_uint_t name_only);
273
+ ngx_int_t ngx_http_v2_add_header(ngx_http_v2_connection_t *h2c,
274
+ ngx_http_v2_header_t *header);
275
+ ngx_int_t ngx_http_v2_table_size(ngx_http_v2_connection_t *h2c, size_t size);
276
+
277
+
278
+ ngx_int_t ngx_http_v2_huff_decode(u_char *state, u_char *src, size_t len,
279
+ u_char **dst, ngx_uint_t last, ngx_log_t *log);
280
+ size_t ngx_http_v2_huff_encode(u_char *src, size_t len, u_char *dst,
281
+ ngx_uint_t lower);
282
+
283
+
284
+ #define ngx_http_v2_prefix(bits) ((1 << (bits)) - 1)
285
+
286
+
287
+ #if (NGX_HAVE_NONALIGNED)
288
+
289
+ #define ngx_http_v2_parse_uint16(p) ntohs(*(uint16_t *) (p))
290
+ #define ngx_http_v2_parse_uint32(p) ntohl(*(uint32_t *) (p))
291
+
292
+ #else
293
+
294
+ #define ngx_http_v2_parse_uint16(p) ((p)[0] << 8 | (p)[1])
295
+ #define ngx_http_v2_parse_uint32(p) \
296
+ ((p)[0] << 24 | (p)[1] << 16 | (p)[2] << 8 | (p)[3])
297
+
298
+ #endif
299
+
300
+ #define ngx_http_v2_parse_length(p) ((p) >> 8)
301
+ #define ngx_http_v2_parse_type(p) ((p) & 0xff)
302
+ #define ngx_http_v2_parse_sid(p) (ngx_http_v2_parse_uint32(p) & 0x7fffffff)
303
+ #define ngx_http_v2_parse_window(p) (ngx_http_v2_parse_uint32(p) & 0x7fffffff)
304
+
305
+
306
+ #define ngx_http_v2_write_uint16_aligned(p, s) \
307
+ (*(uint16_t *) (p) = htons((uint16_t) (s)), (p) + sizeof(uint16_t))
308
+ #define ngx_http_v2_write_uint32_aligned(p, s) \
309
+ (*(uint32_t *) (p) = htonl((uint32_t) (s)), (p) + sizeof(uint32_t))
310
+
311
+ #if (NGX_HAVE_NONALIGNED)
312
+
313
+ #define ngx_http_v2_write_uint16 ngx_http_v2_write_uint16_aligned
314
+ #define ngx_http_v2_write_uint32 ngx_http_v2_write_uint32_aligned
315
+
316
+ #else
317
+
318
+ #define ngx_http_v2_write_uint16(p, s) \
319
+ ((p)[0] = (u_char) ((s) >> 8), \
320
+ (p)[1] = (u_char) (s), \
321
+ (p) + sizeof(uint16_t))
322
+
323
+ #define ngx_http_v2_write_uint32(p, s) \
324
+ ((p)[0] = (u_char) ((s) >> 24), \
325
+ (p)[1] = (u_char) ((s) >> 16), \
326
+ (p)[2] = (u_char) ((s) >> 8), \
327
+ (p)[3] = (u_char) (s), \
328
+ (p) + sizeof(uint32_t))
329
+
330
+ #endif
331
+
332
+ #define ngx_http_v2_write_len_and_type(p, l, t) \
333
+ ngx_http_v2_write_uint32_aligned(p, (l) << 8 | (t))
334
+
335
+ #define ngx_http_v2_write_sid ngx_http_v2_write_uint32
336
+
337
+ #endif /* _NGX_HTTP_V2_H_INCLUDED_ */
@@ -0,0 +1,1391 @@
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 <nginx.h>
12
+ #include <ngx_http_v2_module.h>
13
+
14
+
15
+ /*
16
+ * This returns precise number of octets for values in range 0..253
17
+ * and estimate number for the rest, but not smaller than required.
18
+ */
19
+
20
+ #define ngx_http_v2_integer_octets(v) (1 + (v) / 127)
21
+
22
+ #define ngx_http_v2_literal_size(h) \
23
+ (ngx_http_v2_integer_octets(sizeof(h) - 1) + sizeof(h) - 1)
24
+
25
+ #define ngx_http_v2_indexed(i) (128 + (i))
26
+ #define ngx_http_v2_inc_indexed(i) (64 + (i))
27
+
28
+ #define ngx_http_v2_write_name(dst, src, len, tmp) \
29
+ ngx_http_v2_string_encode(dst, src, len, tmp, 1)
30
+ #define ngx_http_v2_write_value(dst, src, len, tmp) \
31
+ ngx_http_v2_string_encode(dst, src, len, tmp, 0)
32
+
33
+ #define NGX_HTTP_V2_ENCODE_RAW 0
34
+ #define NGX_HTTP_V2_ENCODE_HUFF 0x80
35
+
36
+ #define NGX_HTTP_V2_STATUS_INDEX 8
37
+ #define NGX_HTTP_V2_STATUS_200_INDEX 8
38
+ #define NGX_HTTP_V2_STATUS_204_INDEX 9
39
+ #define NGX_HTTP_V2_STATUS_206_INDEX 10
40
+ #define NGX_HTTP_V2_STATUS_304_INDEX 11
41
+ #define NGX_HTTP_V2_STATUS_400_INDEX 12
42
+ #define NGX_HTTP_V2_STATUS_404_INDEX 13
43
+ #define NGX_HTTP_V2_STATUS_500_INDEX 14
44
+
45
+ #define NGX_HTTP_V2_CONTENT_LENGTH_INDEX 28
46
+ #define NGX_HTTP_V2_CONTENT_TYPE_INDEX 31
47
+ #define NGX_HTTP_V2_DATE_INDEX 33
48
+ #define NGX_HTTP_V2_LAST_MODIFIED_INDEX 44
49
+ #define NGX_HTTP_V2_LOCATION_INDEX 46
50
+ #define NGX_HTTP_V2_SERVER_INDEX 54
51
+ #define NGX_HTTP_V2_VARY_INDEX 59
52
+
53
+
54
+ static u_char *ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len,
55
+ u_char *tmp, ngx_uint_t lower);
56
+ static u_char *ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix,
57
+ ngx_uint_t value);
58
+ static ngx_http_v2_out_frame_t *ngx_http_v2_create_headers_frame(
59
+ ngx_http_request_t *r, u_char *pos, u_char *end);
60
+
61
+ static ngx_chain_t *ngx_http_v2_send_chain(ngx_connection_t *fc,
62
+ ngx_chain_t *in, off_t limit);
63
+
64
+ static ngx_chain_t *ngx_http_v2_filter_get_shadow(
65
+ ngx_http_v2_stream_t *stream, ngx_buf_t *buf, off_t offset, off_t size);
66
+ static ngx_http_v2_out_frame_t *ngx_http_v2_filter_get_data_frame(
67
+ ngx_http_v2_stream_t *stream, size_t len, ngx_chain_t *first,
68
+ ngx_chain_t *last);
69
+
70
+ static ngx_inline ngx_int_t ngx_http_v2_flow_control(
71
+ ngx_http_v2_connection_t *h2c, ngx_http_v2_stream_t *stream);
72
+ static void ngx_http_v2_waiting_queue(ngx_http_v2_connection_t *h2c,
73
+ ngx_http_v2_stream_t *stream);
74
+
75
+ static ngx_inline ngx_int_t ngx_http_v2_filter_send(
76
+ ngx_connection_t *fc, ngx_http_v2_stream_t *stream);
77
+
78
+ static ngx_int_t ngx_http_v2_headers_frame_handler(
79
+ ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame);
80
+ static ngx_int_t ngx_http_v2_data_frame_handler(
81
+ ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame);
82
+ static ngx_inline void ngx_http_v2_handle_frame(
83
+ ngx_http_v2_stream_t *stream, ngx_http_v2_out_frame_t *frame);
84
+ static ngx_inline void ngx_http_v2_handle_stream(
85
+ ngx_http_v2_connection_t *h2c, ngx_http_v2_stream_t *stream);
86
+
87
+ static void ngx_http_v2_filter_cleanup(void *data);
88
+
89
+ static ngx_int_t ngx_http_v2_filter_init(ngx_conf_t *cf);
90
+
91
+
92
+ static ngx_http_module_t ngx_http_v2_filter_module_ctx = {
93
+ NULL, /* preconfiguration */
94
+ ngx_http_v2_filter_init, /* postconfiguration */
95
+
96
+ NULL, /* create main configuration */
97
+ NULL, /* init main configuration */
98
+
99
+ NULL, /* create server configuration */
100
+ NULL, /* merge server configuration */
101
+
102
+ NULL, /* create location configuration */
103
+ NULL /* merge location configuration */
104
+ };
105
+
106
+
107
+ ngx_module_t ngx_http_v2_filter_module = {
108
+ NGX_MODULE_V1,
109
+ &ngx_http_v2_filter_module_ctx, /* module context */
110
+ NULL, /* module directives */
111
+ NGX_HTTP_MODULE, /* module type */
112
+ NULL, /* init master */
113
+ NULL, /* init module */
114
+ NULL, /* init process */
115
+ NULL, /* init thread */
116
+ NULL, /* exit thread */
117
+ NULL, /* exit process */
118
+ NULL, /* exit master */
119
+ NGX_MODULE_V1_PADDING
120
+ };
121
+
122
+
123
+ static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
124
+
125
+
126
+ static ngx_int_t
127
+ ngx_http_v2_header_filter(ngx_http_request_t *r)
128
+ {
129
+ u_char status, *pos, *start, *p, *tmp;
130
+ size_t len, tmp_len;
131
+ ngx_str_t host, location;
132
+ ngx_uint_t i, port;
133
+ ngx_list_part_t *part;
134
+ ngx_table_elt_t *header;
135
+ ngx_connection_t *fc;
136
+ ngx_http_cleanup_t *cln;
137
+ ngx_http_v2_out_frame_t *frame;
138
+ ngx_http_core_loc_conf_t *clcf;
139
+ ngx_http_core_srv_conf_t *cscf;
140
+ struct sockaddr_in *sin;
141
+ #if (NGX_HAVE_INET6)
142
+ struct sockaddr_in6 *sin6;
143
+ #endif
144
+ u_char addr[NGX_SOCKADDR_STRLEN];
145
+
146
+ static const u_char nginx[5] = "\x84\xaa\x63\x55\xe7";
147
+ #if (NGX_HTTP_GZIP)
148
+ static const u_char accept_encoding[12] =
149
+ "\x8b\x84\x84\x2d\x69\x5b\x05\x44\x3c\x86\xaa\x6f";
150
+ #endif
151
+
152
+ static size_t nginx_ver_len = ngx_http_v2_literal_size(NGINX_VER);
153
+ static u_char nginx_ver[ngx_http_v2_literal_size(NGINX_VER)];
154
+
155
+ if (!r->stream) {
156
+ return ngx_http_next_header_filter(r);
157
+ }
158
+
159
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
160
+ "http2 header filter");
161
+
162
+ if (r->header_sent) {
163
+ return NGX_OK;
164
+ }
165
+
166
+ r->header_sent = 1;
167
+
168
+ if (r != r->main) {
169
+ return NGX_OK;
170
+ }
171
+
172
+ if (r->method == NGX_HTTP_HEAD) {
173
+ r->header_only = 1;
174
+ }
175
+
176
+ switch (r->headers_out.status) {
177
+
178
+ case NGX_HTTP_OK:
179
+ status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_200_INDEX);
180
+ break;
181
+
182
+ case NGX_HTTP_NO_CONTENT:
183
+ r->header_only = 1;
184
+
185
+ ngx_str_null(&r->headers_out.content_type);
186
+
187
+ r->headers_out.content_length = NULL;
188
+ r->headers_out.content_length_n = -1;
189
+
190
+ r->headers_out.last_modified_time = -1;
191
+ r->headers_out.last_modified = NULL;
192
+
193
+ status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_204_INDEX);
194
+ break;
195
+
196
+ case NGX_HTTP_PARTIAL_CONTENT:
197
+ status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_206_INDEX);
198
+ break;
199
+
200
+ case NGX_HTTP_NOT_MODIFIED:
201
+ r->header_only = 1;
202
+ status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_304_INDEX);
203
+ break;
204
+
205
+ default:
206
+ r->headers_out.last_modified_time = -1;
207
+ r->headers_out.last_modified = NULL;
208
+
209
+ switch (r->headers_out.status) {
210
+
211
+ case NGX_HTTP_BAD_REQUEST:
212
+ status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_400_INDEX);
213
+ break;
214
+
215
+ case NGX_HTTP_NOT_FOUND:
216
+ status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_404_INDEX);
217
+ break;
218
+
219
+ case NGX_HTTP_INTERNAL_SERVER_ERROR:
220
+ status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_500_INDEX);
221
+ break;
222
+
223
+ default:
224
+ status = 0;
225
+ }
226
+ }
227
+
228
+ len = status ? 1 : 1 + ngx_http_v2_literal_size("418");
229
+
230
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
231
+
232
+ if (r->headers_out.server == NULL) {
233
+ len += 1 + (clcf->server_tokens ? nginx_ver_len : sizeof(nginx));
234
+ }
235
+
236
+ if (r->headers_out.date == NULL) {
237
+ len += 1 + ngx_http_v2_literal_size("Wed, 31 Dec 1986 18:00:00 GMT");
238
+ }
239
+
240
+ if (r->headers_out.content_type.len) {
241
+ len += 1 + NGX_HTTP_V2_INT_OCTETS + r->headers_out.content_type.len;
242
+
243
+ if (r->headers_out.content_type_len == r->headers_out.content_type.len
244
+ && r->headers_out.charset.len)
245
+ {
246
+ len += sizeof("; charset=") - 1 + r->headers_out.charset.len;
247
+ }
248
+ }
249
+
250
+ if (r->headers_out.content_length == NULL
251
+ && r->headers_out.content_length_n >= 0)
252
+ {
253
+ len += 1 + ngx_http_v2_integer_octets(NGX_OFF_T_LEN) + NGX_OFF_T_LEN;
254
+ }
255
+
256
+ if (r->headers_out.last_modified == NULL
257
+ && r->headers_out.last_modified_time != -1)
258
+ {
259
+ len += 1 + ngx_http_v2_literal_size("Wed, 31 Dec 1986 18:00:00 GMT");
260
+ }
261
+
262
+ fc = r->connection;
263
+
264
+ if (r->headers_out.location && r->headers_out.location->value.len) {
265
+
266
+ if (r->headers_out.location->value.data[0] == '/') {
267
+ if (clcf->server_name_in_redirect) {
268
+ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
269
+ host = cscf->server_name;
270
+
271
+ } else if (r->headers_in.server.len) {
272
+ host = r->headers_in.server;
273
+
274
+ } else {
275
+ host.len = NGX_SOCKADDR_STRLEN;
276
+ host.data = addr;
277
+
278
+ if (ngx_connection_local_sockaddr(fc, &host, 0) != NGX_OK) {
279
+ return NGX_ERROR;
280
+ }
281
+ }
282
+
283
+ switch (fc->local_sockaddr->sa_family) {
284
+
285
+ #if (NGX_HAVE_INET6)
286
+ case AF_INET6:
287
+ sin6 = (struct sockaddr_in6 *) fc->local_sockaddr;
288
+ port = ntohs(sin6->sin6_port);
289
+ break;
290
+ #endif
291
+ #if (NGX_HAVE_UNIX_DOMAIN)
292
+ case AF_UNIX:
293
+ port = 0;
294
+ break;
295
+ #endif
296
+ default: /* AF_INET */
297
+ sin = (struct sockaddr_in *) fc->local_sockaddr;
298
+ port = ntohs(sin->sin_port);
299
+ break;
300
+ }
301
+
302
+ location.len = sizeof("https://") - 1 + host.len
303
+ + r->headers_out.location->value.len;
304
+
305
+ if (clcf->port_in_redirect) {
306
+
307
+ #if (NGX_HTTP_SSL)
308
+ if (fc->ssl)
309
+ port = (port == 443) ? 0 : port;
310
+ else
311
+ #endif
312
+ port = (port == 80) ? 0 : port;
313
+
314
+ } else {
315
+ port = 0;
316
+ }
317
+
318
+ if (port) {
319
+ location.len += sizeof(":65535") - 1;
320
+ }
321
+
322
+ location.data = ngx_pnalloc(r->pool, location.len);
323
+ if (location.data == NULL) {
324
+ return NGX_ERROR;
325
+ }
326
+
327
+ p = ngx_cpymem(location.data, "http", sizeof("http") - 1);
328
+
329
+ #if (NGX_HTTP_SSL)
330
+ if (fc->ssl) {
331
+ *p++ = 's';
332
+ }
333
+ #endif
334
+
335
+ *p++ = ':'; *p++ = '/'; *p++ = '/';
336
+ p = ngx_cpymem(p, host.data, host.len);
337
+
338
+ if (port) {
339
+ p = ngx_sprintf(p, ":%ui", port);
340
+ }
341
+
342
+ p = ngx_cpymem(p, r->headers_out.location->value.data,
343
+ r->headers_out.location->value.len);
344
+
345
+ /* update r->headers_out.location->value for possible logging */
346
+
347
+ r->headers_out.location->value.len = p - location.data;
348
+ r->headers_out.location->value.data = location.data;
349
+ ngx_str_set(&r->headers_out.location->key, "Location");
350
+ }
351
+
352
+ r->headers_out.location->hash = 0;
353
+
354
+ len += 1 + NGX_HTTP_V2_INT_OCTETS + r->headers_out.location->value.len;
355
+ }
356
+
357
+ tmp_len = len;
358
+
359
+ #if (NGX_HTTP_GZIP)
360
+ if (r->gzip_vary) {
361
+ if (clcf->gzip_vary) {
362
+ len += 1 + sizeof(accept_encoding);
363
+
364
+ } else {
365
+ r->gzip_vary = 0;
366
+ }
367
+ }
368
+ #endif
369
+
370
+ part = &r->headers_out.headers.part;
371
+ header = part->elts;
372
+
373
+ for (i = 0; /* void */; i++) {
374
+
375
+ if (i >= part->nelts) {
376
+ if (part->next == NULL) {
377
+ break;
378
+ }
379
+
380
+ part = part->next;
381
+ header = part->elts;
382
+ i = 0;
383
+ }
384
+
385
+ if (header[i].hash == 0) {
386
+ continue;
387
+ }
388
+
389
+ if (header[i].key.len > NGX_HTTP_V2_MAX_FIELD) {
390
+ ngx_log_error(NGX_LOG_CRIT, fc->log, 0,
391
+ "too long response header name: \"%V\"",
392
+ &header[i].key);
393
+ return NGX_ERROR;
394
+ }
395
+
396
+ if (header[i].value.len > NGX_HTTP_V2_MAX_FIELD) {
397
+ ngx_log_error(NGX_LOG_CRIT, fc->log, 0,
398
+ "too long response header value: \"%V: %V\"",
399
+ &header[i].key, &header[i].value);
400
+ return NGX_ERROR;
401
+ }
402
+
403
+ len += 1 + NGX_HTTP_V2_INT_OCTETS + header[i].key.len
404
+ + NGX_HTTP_V2_INT_OCTETS + header[i].value.len;
405
+
406
+ if (header[i].key.len > tmp_len) {
407
+ tmp_len = header[i].key.len;
408
+ }
409
+
410
+ if (header[i].value.len > tmp_len) {
411
+ tmp_len = header[i].value.len;
412
+ }
413
+ }
414
+
415
+ tmp = ngx_palloc(r->pool, tmp_len);
416
+ pos = ngx_pnalloc(r->pool, len);
417
+
418
+ if (pos == NULL || tmp == NULL) {
419
+ return NGX_ERROR;
420
+ }
421
+
422
+ start = pos;
423
+
424
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0,
425
+ "http2 output header: \":status: %03ui\"",
426
+ r->headers_out.status);
427
+
428
+ if (status) {
429
+ *pos++ = status;
430
+
431
+ } else {
432
+ *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_STATUS_INDEX);
433
+ *pos++ = NGX_HTTP_V2_ENCODE_RAW | 3;
434
+ pos = ngx_sprintf(pos, "%03ui", r->headers_out.status);
435
+ }
436
+
437
+ if (r->headers_out.server == NULL) {
438
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0,
439
+ "http2 output header: \"server: %s\"",
440
+ clcf->server_tokens ? NGINX_VER : "nginx");
441
+
442
+ *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_SERVER_INDEX);
443
+
444
+ if (clcf->server_tokens) {
445
+ if (nginx_ver[0] == '\0') {
446
+ p = ngx_http_v2_write_value(nginx_ver, (u_char *) NGINX_VER,
447
+ sizeof(NGINX_VER) - 1, tmp);
448
+ nginx_ver_len = p - nginx_ver;
449
+ }
450
+
451
+ pos = ngx_cpymem(pos, nginx_ver, nginx_ver_len);
452
+
453
+ } else {
454
+ pos = ngx_cpymem(pos, nginx, sizeof(nginx));
455
+ }
456
+ }
457
+
458
+ if (r->headers_out.date == NULL) {
459
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0,
460
+ "http2 output header: \"date: %V\"",
461
+ &ngx_cached_http_time);
462
+
463
+ *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_DATE_INDEX);
464
+ pos = ngx_http_v2_write_value(pos, ngx_cached_http_time.data,
465
+ ngx_cached_http_time.len, tmp);
466
+ }
467
+
468
+ if (r->headers_out.content_type.len) {
469
+ *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_CONTENT_TYPE_INDEX);
470
+
471
+ if (r->headers_out.content_type_len == r->headers_out.content_type.len
472
+ && r->headers_out.charset.len)
473
+ {
474
+ len = r->headers_out.content_type.len + sizeof("; charset=") - 1
475
+ + r->headers_out.charset.len;
476
+
477
+ p = ngx_pnalloc(r->pool, len);
478
+ if (p == NULL) {
479
+ return NGX_ERROR;
480
+ }
481
+
482
+ p = ngx_cpymem(p, r->headers_out.content_type.data,
483
+ r->headers_out.content_type.len);
484
+
485
+ p = ngx_cpymem(p, "; charset=", sizeof("; charset=") - 1);
486
+
487
+ p = ngx_cpymem(p, r->headers_out.charset.data,
488
+ r->headers_out.charset.len);
489
+
490
+ /* updated r->headers_out.content_type is also needed for logging */
491
+
492
+ r->headers_out.content_type.len = len;
493
+ r->headers_out.content_type.data = p - len;
494
+ }
495
+
496
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0,
497
+ "http2 output header: \"content-type: %V\"",
498
+ &r->headers_out.content_type);
499
+
500
+ pos = ngx_http_v2_write_value(pos, r->headers_out.content_type.data,
501
+ r->headers_out.content_type.len, tmp);
502
+ }
503
+
504
+ if (r->headers_out.content_length == NULL
505
+ && r->headers_out.content_length_n >= 0)
506
+ {
507
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0,
508
+ "http2 output header: \"content-length: %O\"",
509
+ r->headers_out.content_length_n);
510
+
511
+ *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_CONTENT_LENGTH_INDEX);
512
+
513
+ p = pos;
514
+ pos = ngx_sprintf(pos + 1, "%O", r->headers_out.content_length_n);
515
+ *p = NGX_HTTP_V2_ENCODE_RAW | (u_char) (pos - p - 1);
516
+ }
517
+
518
+ if (r->headers_out.last_modified == NULL
519
+ && r->headers_out.last_modified_time != -1)
520
+ {
521
+ *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LAST_MODIFIED_INDEX);
522
+
523
+ ngx_http_time(pos, r->headers_out.last_modified_time);
524
+ len = sizeof("Wed, 31 Dec 1986 18:00:00 GMT") - 1;
525
+
526
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, fc->log, 0,
527
+ "http2 output header: \"last-modified: %*s\"",
528
+ len, pos);
529
+
530
+ /*
531
+ * Date will always be encoded using huffman in the temporary buffer,
532
+ * so it's safe here to use src and dst pointing to the same address.
533
+ */
534
+ pos = ngx_http_v2_write_value(pos, pos, len, tmp);
535
+ }
536
+
537
+ if (r->headers_out.location && r->headers_out.location->value.len) {
538
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0,
539
+ "http2 output header: \"location: %V\"",
540
+ &r->headers_out.location->value);
541
+
542
+ *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LOCATION_INDEX);
543
+ pos = ngx_http_v2_write_value(pos, r->headers_out.location->value.data,
544
+ r->headers_out.location->value.len, tmp);
545
+ }
546
+
547
+ #if (NGX_HTTP_GZIP)
548
+ if (r->gzip_vary) {
549
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
550
+ "http2 output header: \"vary: Accept-Encoding\"");
551
+
552
+ *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_VARY_INDEX);
553
+ pos = ngx_cpymem(pos, accept_encoding, sizeof(accept_encoding));
554
+ }
555
+ #endif
556
+
557
+ part = &r->headers_out.headers.part;
558
+ header = part->elts;
559
+
560
+ for (i = 0; /* void */; i++) {
561
+
562
+ if (i >= part->nelts) {
563
+ if (part->next == NULL) {
564
+ break;
565
+ }
566
+
567
+ part = part->next;
568
+ header = part->elts;
569
+ i = 0;
570
+ }
571
+
572
+ if (header[i].hash == 0) {
573
+ continue;
574
+ }
575
+
576
+ #if (NGX_DEBUG)
577
+ if (fc->log->log_level & NGX_LOG_DEBUG_HTTP) {
578
+ ngx_strlow(tmp, header[i].key.data, header[i].key.len);
579
+
580
+ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, fc->log, 0,
581
+ "http2 output header: \"%*s: %V\"",
582
+ header[i].key.len, tmp, &header[i].value);
583
+ }
584
+ #endif
585
+
586
+ *pos++ = 0;
587
+
588
+ pos = ngx_http_v2_write_name(pos, header[i].key.data,
589
+ header[i].key.len, tmp);
590
+
591
+ pos = ngx_http_v2_write_value(pos, header[i].value.data,
592
+ header[i].value.len, tmp);
593
+ }
594
+
595
+ frame = ngx_http_v2_create_headers_frame(r, start, pos);
596
+ if (frame == NULL) {
597
+ return NGX_ERROR;
598
+ }
599
+
600
+ ngx_http_v2_queue_blocked_frame(r->stream->connection, frame);
601
+
602
+ cln = ngx_http_cleanup_add(r, 0);
603
+ if (cln == NULL) {
604
+ return NGX_ERROR;
605
+ }
606
+
607
+ cln->handler = ngx_http_v2_filter_cleanup;
608
+ cln->data = r->stream;
609
+
610
+ r->stream->queued = 1;
611
+
612
+ fc->send_chain = ngx_http_v2_send_chain;
613
+ fc->need_last_buf = 1;
614
+
615
+ return ngx_http_v2_filter_send(fc, r->stream);
616
+ }
617
+
618
+
619
+ static u_char *
620
+ ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, u_char *tmp,
621
+ ngx_uint_t lower)
622
+ {
623
+ size_t hlen;
624
+
625
+ hlen = ngx_http_v2_huff_encode(src, len, tmp, lower);
626
+
627
+ if (hlen > 0) {
628
+ *dst = NGX_HTTP_V2_ENCODE_HUFF;
629
+ dst = ngx_http_v2_write_int(dst, ngx_http_v2_prefix(7), hlen);
630
+ return ngx_cpymem(dst, tmp, hlen);
631
+ }
632
+
633
+ *dst = NGX_HTTP_V2_ENCODE_RAW;
634
+ dst = ngx_http_v2_write_int(dst, ngx_http_v2_prefix(7), len);
635
+
636
+ if (lower) {
637
+ ngx_strlow(dst, src, len);
638
+ return dst + len;
639
+ }
640
+
641
+ return ngx_cpymem(dst, src, len);
642
+ }
643
+
644
+
645
+ static u_char *
646
+ ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix, ngx_uint_t value)
647
+ {
648
+ if (value < prefix) {
649
+ *pos++ |= value;
650
+ return pos;
651
+ }
652
+
653
+ *pos++ |= prefix;
654
+ value -= prefix;
655
+
656
+ while (value >= 128) {
657
+ *pos++ = value % 128 + 128;
658
+ value /= 128;
659
+ }
660
+
661
+ *pos++ = (u_char) value;
662
+
663
+ return pos;
664
+ }
665
+
666
+
667
+ static ngx_http_v2_out_frame_t *
668
+ ngx_http_v2_create_headers_frame(ngx_http_request_t *r, u_char *pos,
669
+ u_char *end)
670
+ {
671
+ u_char type, flags;
672
+ size_t rest, frame_size;
673
+ ngx_buf_t *b;
674
+ ngx_chain_t *cl, **ll;
675
+ ngx_http_v2_stream_t *stream;
676
+ ngx_http_v2_out_frame_t *frame;
677
+
678
+ stream = r->stream;
679
+ rest = end - pos;
680
+
681
+ frame = ngx_palloc(r->pool, sizeof(ngx_http_v2_out_frame_t));
682
+ if (frame == NULL) {
683
+ return NULL;
684
+ }
685
+
686
+ frame->handler = ngx_http_v2_headers_frame_handler;
687
+ frame->stream = stream;
688
+ frame->length = rest;
689
+ frame->blocked = 1;
690
+ frame->fin = r->header_only;
691
+
692
+ ll = &frame->first;
693
+
694
+ type = NGX_HTTP_V2_HEADERS_FRAME;
695
+ flags = r->header_only ? NGX_HTTP_V2_END_STREAM_FLAG : NGX_HTTP_V2_NO_FLAG;
696
+ frame_size = stream->connection->frame_size;
697
+
698
+ for ( ;; ) {
699
+ if (rest <= frame_size) {
700
+ frame_size = rest;
701
+ flags |= NGX_HTTP_V2_END_HEADERS_FLAG;
702
+ }
703
+
704
+ b = ngx_create_temp_buf(r->pool, NGX_HTTP_V2_FRAME_HEADER_SIZE);
705
+ if (b == NULL) {
706
+ return NULL;
707
+ }
708
+
709
+ b->last = ngx_http_v2_write_len_and_type(b->last, frame_size, type);
710
+ *b->last++ = flags;
711
+ b->last = ngx_http_v2_write_sid(b->last, stream->node->id);
712
+
713
+ b->tag = (ngx_buf_tag_t) &ngx_http_v2_module;
714
+
715
+ cl = ngx_alloc_chain_link(r->pool);
716
+ if (cl == NULL) {
717
+ return NULL;
718
+ }
719
+
720
+ cl->buf = b;
721
+
722
+ *ll = cl;
723
+ ll = &cl->next;
724
+
725
+ b = ngx_calloc_buf(r->pool);
726
+ if (b == NULL) {
727
+ return NULL;
728
+ }
729
+
730
+ b->pos = pos;
731
+
732
+ pos += frame_size;
733
+
734
+ b->last = pos;
735
+ b->start = b->pos;
736
+ b->end = b->last;
737
+ b->temporary = 1;
738
+
739
+ cl = ngx_alloc_chain_link(r->pool);
740
+ if (cl == NULL) {
741
+ return NULL;
742
+ }
743
+
744
+ cl->buf = b;
745
+
746
+ *ll = cl;
747
+ ll = &cl->next;
748
+
749
+ rest -= frame_size;
750
+
751
+ if (rest) {
752
+ type = NGX_HTTP_V2_CONTINUATION_FRAME;
753
+ flags = NGX_HTTP_V2_NO_FLAG;
754
+ continue;
755
+ }
756
+
757
+ b->last_buf = r->header_only;
758
+ cl->next = NULL;
759
+ frame->last = cl;
760
+
761
+ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
762
+ "http2:%ui create HEADERS frame %p: len:%uz",
763
+ stream->node->id, frame, frame->length);
764
+
765
+ return frame;
766
+ }
767
+ }
768
+
769
+
770
+ static ngx_chain_t *
771
+ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit)
772
+ {
773
+ off_t size, offset;
774
+ size_t rest, frame_size;
775
+ ngx_chain_t *cl, *out, **ln;
776
+ ngx_http_request_t *r;
777
+ ngx_http_v2_stream_t *stream;
778
+ ngx_http_v2_loc_conf_t *h2lcf;
779
+ ngx_http_v2_out_frame_t *frame;
780
+ ngx_http_v2_connection_t *h2c;
781
+
782
+ r = fc->data;
783
+ stream = r->stream;
784
+
785
+ #if (NGX_SUPPRESS_WARN)
786
+ size = 0;
787
+ #endif
788
+
789
+ while (in) {
790
+ size = ngx_buf_size(in->buf);
791
+
792
+ if (size || in->buf->last_buf) {
793
+ break;
794
+ }
795
+
796
+ in = in->next;
797
+ }
798
+
799
+ if (in == NULL) {
800
+
801
+ if (stream->queued) {
802
+ fc->write->active = 1;
803
+ fc->write->ready = 0;
804
+
805
+ } else {
806
+ fc->buffered &= ~NGX_HTTP_V2_BUFFERED;
807
+ }
808
+
809
+ return NULL;
810
+ }
811
+
812
+ h2c = stream->connection;
813
+
814
+ if (size && ngx_http_v2_flow_control(h2c, stream) == NGX_DECLINED) {
815
+ fc->write->active = 1;
816
+ fc->write->ready = 0;
817
+ return in;
818
+ }
819
+
820
+ if (in->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_filter_get_shadow) {
821
+ cl = ngx_alloc_chain_link(r->pool);
822
+ if (cl == NULL) {
823
+ return NGX_CHAIN_ERROR;
824
+ }
825
+
826
+ cl->buf = in->buf;
827
+ in->buf = cl->buf->shadow;
828
+
829
+ offset = ngx_buf_in_memory(in->buf)
830
+ ? (cl->buf->pos - in->buf->pos)
831
+ : (cl->buf->file_pos - in->buf->file_pos);
832
+
833
+ cl->next = stream->free_bufs;
834
+ stream->free_bufs = cl;
835
+
836
+ } else {
837
+ offset = 0;
838
+ }
839
+
840
+ if (limit == 0 || limit > (off_t) h2c->send_window) {
841
+ limit = h2c->send_window;
842
+ }
843
+
844
+ if (limit > stream->send_window) {
845
+ limit = (stream->send_window > 0) ? stream->send_window : 0;
846
+ }
847
+
848
+ h2lcf = ngx_http_get_module_loc_conf(r, ngx_http_v2_module);
849
+
850
+ frame_size = (h2lcf->chunk_size < h2c->frame_size)
851
+ ? h2lcf->chunk_size : h2c->frame_size;
852
+
853
+ #if (NGX_SUPPRESS_WARN)
854
+ cl = NULL;
855
+ #endif
856
+
857
+ for ( ;; ) {
858
+ if ((off_t) frame_size > limit) {
859
+ frame_size = (size_t) limit;
860
+ }
861
+
862
+ ln = &out;
863
+ rest = frame_size;
864
+
865
+ while ((off_t) rest >= size) {
866
+
867
+ if (offset) {
868
+ cl = ngx_http_v2_filter_get_shadow(stream, in->buf,
869
+ offset, size);
870
+ if (cl == NULL) {
871
+ return NGX_CHAIN_ERROR;
872
+ }
873
+
874
+ offset = 0;
875
+
876
+ } else {
877
+ cl = ngx_alloc_chain_link(r->pool);
878
+ if (cl == NULL) {
879
+ return NGX_CHAIN_ERROR;
880
+ }
881
+
882
+ cl->buf = in->buf;
883
+ }
884
+
885
+ *ln = cl;
886
+ ln = &cl->next;
887
+
888
+ rest -= (size_t) size;
889
+ in = in->next;
890
+
891
+ if (in == NULL) {
892
+ frame_size -= rest;
893
+ rest = 0;
894
+ break;
895
+ }
896
+
897
+ size = ngx_buf_size(in->buf);
898
+ }
899
+
900
+ if (rest) {
901
+ cl = ngx_http_v2_filter_get_shadow(stream, in->buf, offset, rest);
902
+ if (cl == NULL) {
903
+ return NGX_CHAIN_ERROR;
904
+ }
905
+
906
+ cl->buf->flush = 0;
907
+ cl->buf->last_buf = 0;
908
+
909
+ *ln = cl;
910
+
911
+ offset += rest;
912
+ size -= rest;
913
+ }
914
+
915
+ frame = ngx_http_v2_filter_get_data_frame(stream, frame_size, out, cl);
916
+ if (frame == NULL) {
917
+ return NGX_CHAIN_ERROR;
918
+ }
919
+
920
+ ngx_http_v2_queue_frame(h2c, frame);
921
+
922
+ h2c->send_window -= frame_size;
923
+
924
+ stream->send_window -= frame_size;
925
+ stream->queued++;
926
+
927
+ if (in == NULL) {
928
+ break;
929
+ }
930
+
931
+ limit -= frame_size;
932
+
933
+ if (limit == 0) {
934
+ break;
935
+ }
936
+ }
937
+
938
+ if (offset) {
939
+ cl = ngx_http_v2_filter_get_shadow(stream, in->buf, offset, size);
940
+ if (cl == NULL) {
941
+ return NGX_CHAIN_ERROR;
942
+ }
943
+
944
+ in->buf = cl->buf;
945
+ ngx_free_chain(r->pool, cl);
946
+ }
947
+
948
+ if (ngx_http_v2_filter_send(fc, stream) == NGX_ERROR) {
949
+ return NGX_CHAIN_ERROR;
950
+ }
951
+
952
+ if (in && ngx_http_v2_flow_control(h2c, stream) == NGX_DECLINED) {
953
+ fc->write->active = 1;
954
+ fc->write->ready = 0;
955
+ }
956
+
957
+ return in;
958
+ }
959
+
960
+
961
+ static ngx_chain_t *
962
+ ngx_http_v2_filter_get_shadow(ngx_http_v2_stream_t *stream, ngx_buf_t *buf,
963
+ off_t offset, off_t size)
964
+ {
965
+ ngx_buf_t *chunk;
966
+ ngx_chain_t *cl;
967
+
968
+ cl = ngx_chain_get_free_buf(stream->request->pool, &stream->free_bufs);
969
+ if (cl == NULL) {
970
+ return NULL;
971
+ }
972
+
973
+ chunk = cl->buf;
974
+
975
+ ngx_memcpy(chunk, buf, sizeof(ngx_buf_t));
976
+
977
+ chunk->tag = (ngx_buf_tag_t) &ngx_http_v2_filter_get_shadow;
978
+ chunk->shadow = buf;
979
+
980
+ if (ngx_buf_in_memory(chunk)) {
981
+ chunk->pos += offset;
982
+ chunk->last = chunk->pos + size;
983
+ }
984
+
985
+ if (chunk->in_file) {
986
+ chunk->file_pos += offset;
987
+ chunk->file_last = chunk->file_pos + size;
988
+ }
989
+
990
+ return cl;
991
+ }
992
+
993
+
994
+ static ngx_http_v2_out_frame_t *
995
+ ngx_http_v2_filter_get_data_frame(ngx_http_v2_stream_t *stream,
996
+ size_t len, ngx_chain_t *first, ngx_chain_t *last)
997
+ {
998
+ u_char flags;
999
+ ngx_buf_t *buf;
1000
+ ngx_chain_t *cl;
1001
+ ngx_http_v2_out_frame_t *frame;
1002
+
1003
+
1004
+ frame = stream->free_frames;
1005
+
1006
+ if (frame) {
1007
+ stream->free_frames = frame->next;
1008
+
1009
+ } else {
1010
+ frame = ngx_palloc(stream->request->pool,
1011
+ sizeof(ngx_http_v2_out_frame_t));
1012
+ if (frame == NULL) {
1013
+ return NULL;
1014
+ }
1015
+ }
1016
+
1017
+ flags = last->buf->last_buf ? NGX_HTTP_V2_END_STREAM_FLAG : 0;
1018
+
1019
+ ngx_log_debug4(NGX_LOG_DEBUG_HTTP, stream->request->connection->log, 0,
1020
+ "http2:%ui create DATA frame %p: len:%uz flags:%ui",
1021
+ stream->node->id, frame, len, (ngx_uint_t) flags);
1022
+
1023
+ cl = ngx_chain_get_free_buf(stream->request->pool,
1024
+ &stream->free_frame_headers);
1025
+ if (cl == NULL) {
1026
+ return NULL;
1027
+ }
1028
+
1029
+ buf = cl->buf;
1030
+
1031
+ if (!buf->start) {
1032
+ buf->start = ngx_palloc(stream->request->pool,
1033
+ NGX_HTTP_V2_FRAME_HEADER_SIZE);
1034
+ if (buf->start == NULL) {
1035
+ return NULL;
1036
+ }
1037
+
1038
+ buf->end = buf->start + NGX_HTTP_V2_FRAME_HEADER_SIZE;
1039
+ buf->last = buf->end;
1040
+
1041
+ buf->tag = (ngx_buf_tag_t) &ngx_http_v2_module;
1042
+ buf->memory = 1;
1043
+ }
1044
+
1045
+ buf->pos = buf->start;
1046
+ buf->last = buf->pos;
1047
+
1048
+ buf->last = ngx_http_v2_write_len_and_type(buf->last, len,
1049
+ NGX_HTTP_V2_DATA_FRAME);
1050
+ *buf->last++ = flags;
1051
+
1052
+ buf->last = ngx_http_v2_write_sid(buf->last, stream->node->id);
1053
+
1054
+ cl->next = first;
1055
+ first = cl;
1056
+
1057
+ last->buf->flush = 1;
1058
+
1059
+ frame->first = first;
1060
+ frame->last = last;
1061
+ frame->handler = ngx_http_v2_data_frame_handler;
1062
+ frame->stream = stream;
1063
+ frame->length = len;
1064
+ frame->blocked = 0;
1065
+ frame->fin = last->buf->last_buf;
1066
+
1067
+ return frame;
1068
+ }
1069
+
1070
+
1071
+ static ngx_inline ngx_int_t
1072
+ ngx_http_v2_filter_send(ngx_connection_t *fc, ngx_http_v2_stream_t *stream)
1073
+ {
1074
+ stream->blocked = 1;
1075
+
1076
+ if (ngx_http_v2_send_output_queue(stream->connection) == NGX_ERROR) {
1077
+ fc->error = 1;
1078
+ return NGX_ERROR;
1079
+ }
1080
+
1081
+ stream->blocked = 0;
1082
+
1083
+ if (stream->queued) {
1084
+ fc->buffered |= NGX_HTTP_V2_BUFFERED;
1085
+ fc->write->active = 1;
1086
+ fc->write->ready = 0;
1087
+ return NGX_AGAIN;
1088
+ }
1089
+
1090
+ fc->buffered &= ~NGX_HTTP_V2_BUFFERED;
1091
+
1092
+ return NGX_OK;
1093
+ }
1094
+
1095
+
1096
+ static ngx_inline ngx_int_t
1097
+ ngx_http_v2_flow_control(ngx_http_v2_connection_t *h2c,
1098
+ ngx_http_v2_stream_t *stream)
1099
+ {
1100
+ if (stream->send_window <= 0) {
1101
+ stream->exhausted = 1;
1102
+ return NGX_DECLINED;
1103
+ }
1104
+
1105
+ if (h2c->send_window == 0) {
1106
+ ngx_http_v2_waiting_queue(h2c, stream);
1107
+ return NGX_DECLINED;
1108
+ }
1109
+
1110
+ return NGX_OK;
1111
+ }
1112
+
1113
+
1114
+ static void
1115
+ ngx_http_v2_waiting_queue(ngx_http_v2_connection_t *h2c,
1116
+ ngx_http_v2_stream_t *stream)
1117
+ {
1118
+ ngx_queue_t *q;
1119
+ ngx_http_v2_stream_t *s;
1120
+
1121
+ if (stream->handled) {
1122
+ return;
1123
+ }
1124
+
1125
+ stream->handled = 1;
1126
+
1127
+ for (q = ngx_queue_last(&h2c->waiting);
1128
+ q != ngx_queue_sentinel(&h2c->waiting);
1129
+ q = ngx_queue_prev(q))
1130
+ {
1131
+ s = ngx_queue_data(q, ngx_http_v2_stream_t, queue);
1132
+
1133
+ if (s->node->rank < stream->node->rank
1134
+ || (s->node->rank == stream->node->rank
1135
+ && s->node->rel_weight >= stream->node->rel_weight))
1136
+ {
1137
+ break;
1138
+ }
1139
+ }
1140
+
1141
+ ngx_queue_insert_after(q, &stream->queue);
1142
+ }
1143
+
1144
+
1145
+
1146
+ static ngx_int_t
1147
+ ngx_http_v2_headers_frame_handler(ngx_http_v2_connection_t *h2c,
1148
+ ngx_http_v2_out_frame_t *frame)
1149
+ {
1150
+ ngx_chain_t *cl, *ln;
1151
+ ngx_http_v2_stream_t *stream;
1152
+
1153
+ stream = frame->stream;
1154
+ cl = frame->first;
1155
+
1156
+ for ( ;; ) {
1157
+ if (cl->buf->pos != cl->buf->last) {
1158
+ frame->first = cl;
1159
+
1160
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
1161
+ "http2:%ui HEADERS frame %p was sent partially",
1162
+ stream->node->id, frame);
1163
+
1164
+ return NGX_AGAIN;
1165
+ }
1166
+
1167
+ ln = cl->next;
1168
+
1169
+ if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_module) {
1170
+ cl->next = stream->free_frame_headers;
1171
+ stream->free_frame_headers = cl;
1172
+
1173
+ } else {
1174
+ cl->next = stream->free_bufs;
1175
+ stream->free_bufs = cl;
1176
+ }
1177
+
1178
+ if (cl == frame->last) {
1179
+ break;
1180
+ }
1181
+
1182
+ cl = ln;
1183
+ }
1184
+
1185
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
1186
+ "http2:%ui HEADERS frame %p was sent",
1187
+ stream->node->id, frame);
1188
+
1189
+ ngx_http_v2_handle_frame(stream, frame);
1190
+
1191
+ ngx_http_v2_handle_stream(h2c, stream);
1192
+
1193
+ return NGX_OK;
1194
+ }
1195
+
1196
+
1197
+ static ngx_int_t
1198
+ ngx_http_v2_data_frame_handler(ngx_http_v2_connection_t *h2c,
1199
+ ngx_http_v2_out_frame_t *frame)
1200
+ {
1201
+ ngx_buf_t *buf;
1202
+ ngx_chain_t *cl, *ln;
1203
+ ngx_http_v2_stream_t *stream;
1204
+
1205
+ stream = frame->stream;
1206
+
1207
+ cl = frame->first;
1208
+
1209
+ if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_module) {
1210
+
1211
+ if (cl->buf->pos != cl->buf->last) {
1212
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
1213
+ "http2:%ui DATA frame %p was sent partially",
1214
+ stream->node->id, frame);
1215
+
1216
+ return NGX_AGAIN;
1217
+ }
1218
+
1219
+ ln = cl->next;
1220
+
1221
+ cl->next = stream->free_frame_headers;
1222
+ stream->free_frame_headers = cl;
1223
+
1224
+ if (cl == frame->last) {
1225
+ goto done;
1226
+ }
1227
+
1228
+ cl = ln;
1229
+ }
1230
+
1231
+ for ( ;; ) {
1232
+ if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_filter_get_shadow) {
1233
+ buf = cl->buf->shadow;
1234
+
1235
+ if (ngx_buf_in_memory(buf)) {
1236
+ buf->pos = cl->buf->pos;
1237
+ }
1238
+
1239
+ if (buf->in_file) {
1240
+ buf->file_pos = cl->buf->file_pos;
1241
+ }
1242
+ }
1243
+
1244
+ if (ngx_buf_size(cl->buf) != 0) {
1245
+
1246
+ if (cl != frame->first) {
1247
+ frame->first = cl;
1248
+ ngx_http_v2_handle_stream(h2c, stream);
1249
+ }
1250
+
1251
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
1252
+ "http2:%ui DATA frame %p was sent partially",
1253
+ stream->node->id, frame);
1254
+
1255
+ return NGX_AGAIN;
1256
+ }
1257
+
1258
+ ln = cl->next;
1259
+
1260
+ if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_filter_get_shadow) {
1261
+ cl->next = stream->free_bufs;
1262
+ stream->free_bufs = cl;
1263
+
1264
+ } else {
1265
+ ngx_free_chain(stream->request->pool, cl);
1266
+ }
1267
+
1268
+ if (cl == frame->last) {
1269
+ goto done;
1270
+ }
1271
+
1272
+ cl = ln;
1273
+ }
1274
+
1275
+ done:
1276
+
1277
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
1278
+ "http2:%ui DATA frame %p was sent",
1279
+ stream->node->id, frame);
1280
+
1281
+ stream->request->header_size += NGX_HTTP_V2_FRAME_HEADER_SIZE;
1282
+
1283
+ ngx_http_v2_handle_frame(stream, frame);
1284
+
1285
+ ngx_http_v2_handle_stream(h2c, stream);
1286
+
1287
+ return NGX_OK;
1288
+ }
1289
+
1290
+
1291
+ static ngx_inline void
1292
+ ngx_http_v2_handle_frame(ngx_http_v2_stream_t *stream,
1293
+ ngx_http_v2_out_frame_t *frame)
1294
+ {
1295
+ ngx_http_request_t *r;
1296
+
1297
+ r = stream->request;
1298
+
1299
+ r->connection->sent += NGX_HTTP_V2_FRAME_HEADER_SIZE + frame->length;
1300
+
1301
+ if (frame->fin) {
1302
+ stream->out_closed = 1;
1303
+ }
1304
+
1305
+ frame->next = stream->free_frames;
1306
+ stream->free_frames = frame;
1307
+
1308
+ stream->queued--;
1309
+ }
1310
+
1311
+
1312
+ static ngx_inline void
1313
+ ngx_http_v2_handle_stream(ngx_http_v2_connection_t *h2c,
1314
+ ngx_http_v2_stream_t *stream)
1315
+ {
1316
+ ngx_event_t *wev;
1317
+
1318
+ if (stream->handled || stream->blocked || stream->exhausted) {
1319
+ return;
1320
+ }
1321
+
1322
+ wev = stream->request->connection->write;
1323
+
1324
+ if (!wev->delayed) {
1325
+ stream->handled = 1;
1326
+ ngx_queue_insert_tail(&h2c->posted, &stream->queue);
1327
+ }
1328
+ }
1329
+
1330
+
1331
+ static void
1332
+ ngx_http_v2_filter_cleanup(void *data)
1333
+ {
1334
+ ngx_http_v2_stream_t *stream = data;
1335
+
1336
+ size_t window;
1337
+ ngx_http_v2_out_frame_t *frame, **fn;
1338
+ ngx_http_v2_connection_t *h2c;
1339
+
1340
+ if (stream->handled) {
1341
+ stream->handled = 0;
1342
+ ngx_queue_remove(&stream->queue);
1343
+ }
1344
+
1345
+ if (stream->queued == 0) {
1346
+ return;
1347
+ }
1348
+
1349
+ window = 0;
1350
+ h2c = stream->connection;
1351
+ fn = &h2c->last_out;
1352
+
1353
+ for ( ;; ) {
1354
+ frame = *fn;
1355
+
1356
+ if (frame == NULL) {
1357
+ break;
1358
+ }
1359
+
1360
+ if (frame->stream == stream && !frame->blocked) {
1361
+ *fn = frame->next;
1362
+
1363
+ window += frame->length;
1364
+
1365
+ if (--stream->queued == 0) {
1366
+ break;
1367
+ }
1368
+
1369
+ continue;
1370
+ }
1371
+
1372
+ fn = &frame->next;
1373
+ }
1374
+
1375
+ if (h2c->send_window == 0 && window && !ngx_queue_empty(&h2c->waiting)) {
1376
+ ngx_queue_add(&h2c->posted, &h2c->waiting);
1377
+ ngx_queue_init(&h2c->waiting);
1378
+ }
1379
+
1380
+ h2c->send_window += window;
1381
+ }
1382
+
1383
+
1384
+ static ngx_int_t
1385
+ ngx_http_v2_filter_init(ngx_conf_t *cf)
1386
+ {
1387
+ ngx_http_next_header_filter = ngx_http_top_header_filter;
1388
+ ngx_http_top_header_filter = ngx_http_v2_header_filter;
1389
+
1390
+ return NGX_OK;
1391
+ }