nginxtra 1.4.7.9 → 1.6.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) 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 +286 -19
  6. data/vendor/nginx/CHANGES.ru +296 -22
  7. data/vendor/nginx/auto/cc/clang +4 -3
  8. data/vendor/nginx/auto/cc/conf +23 -0
  9. data/vendor/nginx/auto/cc/msvc +1 -0
  10. data/vendor/nginx/auto/cc/name +1 -1
  11. data/vendor/nginx/auto/cc/owc +4 -4
  12. data/vendor/nginx/auto/cc/sunc +1 -1
  13. data/vendor/nginx/auto/endianness +2 -2
  14. data/vendor/nginx/auto/feature +1 -1
  15. data/vendor/nginx/auto/include +1 -1
  16. data/vendor/nginx/auto/lib/libatomic/make +3 -1
  17. data/vendor/nginx/auto/lib/openssl/conf +4 -0
  18. data/vendor/nginx/auto/lib/openssl/make +1 -1
  19. data/vendor/nginx/auto/lib/pcre/conf +5 -0
  20. data/vendor/nginx/auto/lib/pcre/make +11 -11
  21. data/vendor/nginx/auto/lib/pcre/makefile.bcc +4 -3
  22. data/vendor/nginx/auto/lib/pcre/makefile.msvc +2 -1
  23. data/vendor/nginx/auto/lib/pcre/makefile.owc +2 -1
  24. data/vendor/nginx/auto/lib/perl/make +1 -0
  25. data/vendor/nginx/auto/lib/test +1 -1
  26. data/vendor/nginx/auto/lib/zlib/make +22 -1
  27. data/vendor/nginx/auto/modules +8 -0
  28. data/vendor/nginx/auto/options +3 -0
  29. data/vendor/nginx/auto/os/darwin +1 -1
  30. data/vendor/nginx/auto/os/linux +32 -0
  31. data/vendor/nginx/auto/os/win32 +12 -1
  32. data/vendor/nginx/auto/sources +8 -2
  33. data/vendor/nginx/auto/types/sizeof +1 -1
  34. data/vendor/nginx/auto/types/typedef +1 -1
  35. data/vendor/nginx/auto/types/uintptr_t +1 -1
  36. data/vendor/nginx/auto/unix +13 -1
  37. data/vendor/nginx/conf/mime.types +11 -2
  38. data/vendor/nginx/conf/nginx.conf +3 -4
  39. data/vendor/nginx/contrib/README +6 -0
  40. data/vendor/nginx/contrib/vim/ftdetect/nginx.vim +4 -0
  41. data/vendor/nginx/contrib/vim/indent/nginx.vim +11 -0
  42. data/vendor/nginx/contrib/vim/syntax/nginx.vim +703 -0
  43. data/vendor/nginx/src/core/nginx.c +2 -7
  44. data/vendor/nginx/src/core/nginx.h +2 -2
  45. data/vendor/nginx/src/core/ngx_conf_file.c +8 -88
  46. data/vendor/nginx/src/core/ngx_conf_file.h +3 -3
  47. data/vendor/nginx/src/core/ngx_config.h +2 -2
  48. data/vendor/nginx/src/core/ngx_connection.c +100 -29
  49. data/vendor/nginx/src/core/ngx_connection.h +11 -0
  50. data/vendor/nginx/src/core/ngx_core.h +1 -0
  51. data/vendor/nginx/src/core/ngx_cycle.c +23 -99
  52. data/vendor/nginx/src/core/ngx_cycle.h +2 -0
  53. data/vendor/nginx/src/core/ngx_file.c +100 -8
  54. data/vendor/nginx/src/core/ngx_file.h +3 -0
  55. data/vendor/nginx/src/core/ngx_hash.c +6 -9
  56. data/vendor/nginx/src/core/ngx_inet.c +93 -5
  57. data/vendor/nginx/src/core/ngx_inet.h +4 -2
  58. data/vendor/nginx/src/core/ngx_list.c +1 -9
  59. data/vendor/nginx/src/core/ngx_log.c +132 -30
  60. data/vendor/nginx/src/core/ngx_log.h +5 -2
  61. data/vendor/nginx/src/core/ngx_open_file_cache.c +67 -1
  62. data/vendor/nginx/src/core/ngx_palloc.c +5 -2
  63. data/vendor/nginx/src/core/ngx_proxy_protocol.c +91 -0
  64. data/vendor/nginx/src/core/ngx_proxy_protocol.h +23 -0
  65. data/vendor/nginx/src/core/ngx_resolver.c +1080 -285
  66. data/vendor/nginx/src/core/ngx_resolver.h +33 -3
  67. data/vendor/nginx/src/core/ngx_slab.c +7 -2
  68. data/vendor/nginx/src/core/ngx_slab.h +2 -0
  69. data/vendor/nginx/src/core/ngx_string.c +78 -13
  70. data/vendor/nginx/src/core/ngx_string.h +2 -0
  71. data/vendor/nginx/src/event/modules/ngx_devpoll_module.c +2 -2
  72. data/vendor/nginx/src/event/modules/ngx_epoll_module.c +13 -5
  73. data/vendor/nginx/src/event/modules/ngx_select_module.c +1 -1
  74. data/vendor/nginx/src/event/modules/ngx_win32_select_module.c +2 -2
  75. data/vendor/nginx/src/event/ngx_event.c +0 -1
  76. data/vendor/nginx/src/event/ngx_event.h +7 -6
  77. data/vendor/nginx/src/event/ngx_event_accept.c +6 -4
  78. data/vendor/nginx/src/event/ngx_event_connect.c +2 -2
  79. data/vendor/nginx/src/event/ngx_event_openssl.c +304 -13
  80. data/vendor/nginx/src/event/ngx_event_openssl.h +20 -1
  81. data/vendor/nginx/src/event/ngx_event_openssl_stapling.c +35 -23
  82. data/vendor/nginx/src/event/ngx_event_pipe.c +15 -30
  83. data/vendor/nginx/src/http/modules/ngx_http_access_module.c +115 -35
  84. data/vendor/nginx/src/http/modules/ngx_http_auth_basic_module.c +1 -1
  85. data/vendor/nginx/src/http/modules/ngx_http_auth_request_module.c +444 -0
  86. data/vendor/nginx/src/http/modules/ngx_http_autoindex_module.c +2 -1
  87. data/vendor/nginx/src/http/modules/ngx_http_charset_filter_module.c +1 -1
  88. data/vendor/nginx/src/http/modules/ngx_http_dav_module.c +1 -3
  89. data/vendor/nginx/src/http/modules/ngx_http_fastcgi_module.c +251 -36
  90. data/vendor/nginx/src/http/modules/ngx_http_gunzip_filter_module.c +9 -5
  91. data/vendor/nginx/src/http/modules/ngx_http_gzip_filter_module.c +5 -3
  92. data/vendor/nginx/src/http/modules/ngx_http_gzip_static_module.c +1 -1
  93. data/vendor/nginx/src/http/modules/ngx_http_headers_filter_module.c +4 -0
  94. data/vendor/nginx/src/http/modules/ngx_http_image_filter_module.c +8 -2
  95. data/vendor/nginx/src/http/modules/ngx_http_limit_req_module.c +5 -1
  96. data/vendor/nginx/src/http/modules/ngx_http_map_module.c +3 -3
  97. data/vendor/nginx/src/http/modules/ngx_http_memcached_module.c +21 -10
  98. data/vendor/nginx/src/http/modules/ngx_http_mp4_module.c +669 -197
  99. data/vendor/nginx/src/http/modules/ngx_http_proxy_module.c +93 -60
  100. data/vendor/nginx/src/http/modules/ngx_http_range_filter_module.c +13 -6
  101. data/vendor/nginx/src/http/modules/ngx_http_realip_module.c +20 -1
  102. data/vendor/nginx/src/http/modules/ngx_http_referer_module.c +132 -74
  103. data/vendor/nginx/src/http/modules/ngx_http_scgi_module.c +18 -12
  104. data/vendor/nginx/src/http/modules/ngx_http_ssi_filter_module.c +22 -20
  105. data/vendor/nginx/src/http/modules/ngx_http_ssl_module.c +121 -3
  106. data/vendor/nginx/src/http/modules/ngx_http_ssl_module.h +5 -0
  107. data/vendor/nginx/src/http/modules/ngx_http_stub_status_module.c +3 -0
  108. data/vendor/nginx/src/http/modules/ngx_http_sub_filter_module.c +123 -91
  109. data/vendor/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c +29 -19
  110. data/vendor/nginx/src/http/modules/ngx_http_upstream_keepalive_module.c +2 -5
  111. data/vendor/nginx/src/http/modules/ngx_http_uwsgi_module.c +215 -19
  112. data/vendor/nginx/src/http/modules/ngx_http_xslt_filter_module.c +32 -6
  113. data/vendor/nginx/src/http/modules/perl/nginx.xs +4 -7
  114. data/vendor/nginx/src/http/modules/perl/ngx_http_perl_module.c +2 -2
  115. data/vendor/nginx/src/http/ngx_http.c +17 -7
  116. data/vendor/nginx/src/http/ngx_http_cache.h +4 -2
  117. data/vendor/nginx/src/http/ngx_http_copy_filter_module.c +4 -2
  118. data/vendor/nginx/src/http/ngx_http_core_module.c +63 -50
  119. data/vendor/nginx/src/http/ngx_http_core_module.h +5 -0
  120. data/vendor/nginx/src/http/ngx_http_file_cache.c +115 -3
  121. data/vendor/nginx/src/http/ngx_http_header_filter_module.c +9 -6
  122. data/vendor/nginx/src/http/ngx_http_parse.c +88 -10
  123. data/vendor/nginx/src/http/ngx_http_postpone_filter_module.c +2 -4
  124. data/vendor/nginx/src/http/ngx_http_request.c +116 -8
  125. data/vendor/nginx/src/http/ngx_http_request.h +5 -1
  126. data/vendor/nginx/src/http/ngx_http_request_body.c +7 -7
  127. data/vendor/nginx/src/http/ngx_http_script.c +6 -5
  128. data/vendor/nginx/src/http/ngx_http_spdy.c +889 -271
  129. data/vendor/nginx/src/http/ngx_http_spdy.h +51 -28
  130. data/vendor/nginx/src/http/ngx_http_spdy_filter_module.c +382 -167
  131. data/vendor/nginx/src/http/ngx_http_spdy_module.c +65 -8
  132. data/vendor/nginx/src/http/ngx_http_spdy_module.h +5 -0
  133. data/vendor/nginx/src/http/ngx_http_special_response.c +1 -1
  134. data/vendor/nginx/src/http/ngx_http_upstream.c +290 -114
  135. data/vendor/nginx/src/http/ngx_http_upstream.h +9 -5
  136. data/vendor/nginx/src/http/ngx_http_upstream_round_robin.c +32 -24
  137. data/vendor/nginx/src/http/ngx_http_variables.c +40 -6
  138. data/vendor/nginx/src/http/ngx_http_write_filter_module.c +12 -5
  139. data/vendor/nginx/src/mail/ngx_mail.c +4 -2
  140. data/vendor/nginx/src/mail/ngx_mail.h +2 -0
  141. data/vendor/nginx/src/mail/ngx_mail_auth_http_module.c +0 -1
  142. data/vendor/nginx/src/mail/ngx_mail_core_module.c +2 -1
  143. data/vendor/nginx/src/mail/ngx_mail_handler.c +17 -4
  144. data/vendor/nginx/src/mail/ngx_mail_parse.c +32 -2
  145. data/vendor/nginx/src/mail/ngx_mail_proxy_module.c +54 -7
  146. data/vendor/nginx/src/mail/ngx_mail_smtp_handler.c +50 -78
  147. data/vendor/nginx/src/mail/ngx_mail_ssl_module.c +48 -11
  148. data/vendor/nginx/src/mail/ngx_mail_ssl_module.h +3 -0
  149. data/vendor/nginx/src/os/unix/ngx_channel.c +3 -1
  150. data/vendor/nginx/src/os/unix/ngx_darwin_config.h +1 -0
  151. data/vendor/nginx/src/os/unix/ngx_darwin_init.c +1 -1
  152. data/vendor/nginx/src/os/unix/ngx_darwin_sendfile_chain.c +14 -16
  153. data/vendor/nginx/src/os/unix/ngx_errno.h +3 -0
  154. data/vendor/nginx/src/os/unix/ngx_files.h +10 -16
  155. data/vendor/nginx/src/os/unix/ngx_freebsd_config.h +6 -0
  156. data/vendor/nginx/src/os/unix/ngx_freebsd_init.c +1 -1
  157. data/vendor/nginx/src/os/unix/ngx_freebsd_rfork_thread.c +1 -1
  158. data/vendor/nginx/src/os/unix/ngx_freebsd_rfork_thread.h +2 -2
  159. data/vendor/nginx/src/os/unix/ngx_freebsd_sendfile_chain.c +17 -19
  160. data/vendor/nginx/src/os/unix/ngx_linux_config.h +8 -2
  161. data/vendor/nginx/src/os/unix/ngx_linux_sendfile_chain.c +20 -22
  162. data/vendor/nginx/src/os/unix/ngx_posix_config.h +1 -0
  163. data/vendor/nginx/src/os/unix/ngx_process.c +5 -0
  164. data/vendor/nginx/src/os/unix/ngx_process_cycle.c +15 -3
  165. data/vendor/nginx/src/os/unix/ngx_readv_chain.c +2 -1
  166. data/vendor/nginx/src/os/unix/ngx_recv.c +4 -1
  167. data/vendor/nginx/src/os/unix/ngx_solaris_config.h +1 -0
  168. data/vendor/nginx/src/os/unix/ngx_solaris_sendfilev_chain.c +14 -16
  169. metadata +8 -2
@@ -15,12 +15,10 @@
15
15
  #include <zlib.h>
16
16
 
17
17
 
18
- #define NGX_SPDY_VERSION 2
18
+ #define NGX_SPDY_VERSION 3
19
19
 
20
- #ifdef TLSEXT_TYPE_next_proto_neg
21
- #define NGX_SPDY_NPN_ADVERTISE "\x06spdy/2"
22
- #define NGX_SPDY_NPN_NEGOTIATED "spdy/2"
23
- #endif
20
+ #define NGX_SPDY_NPN_ADVERTISE "\x08spdy/3.1"
21
+ #define NGX_SPDY_NPN_NEGOTIATED "spdy/3.1"
24
22
 
25
23
  #define NGX_SPDY_STATE_BUFFER_SIZE 16
26
24
 
@@ -30,32 +28,34 @@
30
28
  #define NGX_SPDY_SYN_REPLY 2
31
29
  #define NGX_SPDY_RST_STREAM 3
32
30
  #define NGX_SPDY_SETTINGS 4
33
- #define NGX_SPDY_NOOP 5
34
31
  #define NGX_SPDY_PING 6
35
32
  #define NGX_SPDY_GOAWAY 7
36
33
  #define NGX_SPDY_HEADERS 8
34
+ #define NGX_SPDY_WINDOW_UPDATE 9
37
35
 
38
36
  #define NGX_SPDY_FRAME_HEADER_SIZE 8
39
37
 
40
38
  #define NGX_SPDY_SID_SIZE 4
39
+ #define NGX_SPDY_DELTA_SIZE 4
41
40
 
42
41
  #define NGX_SPDY_SYN_STREAM_SIZE 10
43
- #define NGX_SPDY_SYN_REPLY_SIZE 6
42
+ #define NGX_SPDY_SYN_REPLY_SIZE 4
44
43
  #define NGX_SPDY_RST_STREAM_SIZE 8
45
44
  #define NGX_SPDY_PING_SIZE 4
46
- #define NGX_SPDY_GOAWAY_SIZE 4
47
- #define NGX_SPDY_NV_NUM_SIZE 2
48
- #define NGX_SPDY_NV_NLEN_SIZE 2
49
- #define NGX_SPDY_NV_VLEN_SIZE 2
45
+ #define NGX_SPDY_GOAWAY_SIZE 8
46
+ #define NGX_SPDY_WINDOW_UPDATE_SIZE 8
47
+ #define NGX_SPDY_NV_NUM_SIZE 4
48
+ #define NGX_SPDY_NV_NLEN_SIZE 4
49
+ #define NGX_SPDY_NV_VLEN_SIZE 4
50
50
  #define NGX_SPDY_SETTINGS_NUM_SIZE 4
51
- #define NGX_SPDY_SETTINGS_IDF_SIZE 4
51
+ #define NGX_SPDY_SETTINGS_FID_SIZE 4
52
52
  #define NGX_SPDY_SETTINGS_VAL_SIZE 4
53
53
 
54
54
  #define NGX_SPDY_SETTINGS_PAIR_SIZE \
55
- (NGX_SPDY_SETTINGS_IDF_SIZE + NGX_SPDY_SETTINGS_VAL_SIZE)
55
+ (NGX_SPDY_SETTINGS_FID_SIZE + NGX_SPDY_SETTINGS_VAL_SIZE)
56
56
 
57
57
  #define NGX_SPDY_HIGHEST_PRIORITY 0
58
- #define NGX_SPDY_LOWEST_PRIORITY 3
58
+ #define NGX_SPDY_LOWEST_PRIORITY 7
59
59
 
60
60
  #define NGX_SPDY_FLAG_FIN 0x01
61
61
  #define NGX_SPDY_FLAG_UNIDIRECTIONAL 0x02
@@ -81,6 +81,12 @@ struct ngx_http_spdy_connection_s {
81
81
 
82
82
  ngx_uint_t processing;
83
83
 
84
+ size_t send_window;
85
+ size_t recv_window;
86
+ size_t init_window;
87
+
88
+ ngx_queue_t waiting;
89
+
84
90
  u_char buffer[NGX_SPDY_STATE_BUFFER_SIZE];
85
91
  size_t buffer_used;
86
92
  ngx_http_spdy_handler_pt handler;
@@ -96,18 +102,19 @@ struct ngx_http_spdy_connection_s {
96
102
  ngx_http_spdy_stream_t **streams_index;
97
103
 
98
104
  ngx_http_spdy_out_frame_t *last_out;
99
- ngx_http_spdy_stream_t *last_stream;
105
+
106
+ ngx_queue_t posted;
100
107
 
101
108
  ngx_http_spdy_stream_t *stream;
102
109
 
103
- ngx_uint_t headers;
110
+ ngx_uint_t entries;
104
111
  size_t length;
105
112
  u_char flags;
106
113
 
107
114
  ngx_uint_t last_sid;
108
115
 
109
- unsigned blocked:2;
110
- unsigned waiting:1; /* FIXME better name */
116
+ unsigned blocked:1;
117
+ unsigned incomplete:1;
111
118
  };
112
119
 
113
120
 
@@ -116,15 +123,27 @@ struct ngx_http_spdy_stream_s {
116
123
  ngx_http_request_t *request;
117
124
  ngx_http_spdy_connection_t *connection;
118
125
  ngx_http_spdy_stream_t *index;
119
- ngx_http_spdy_stream_t *next;
120
126
 
121
127
  ngx_uint_t header_buffers;
122
- ngx_uint_t waiting;
128
+ ngx_uint_t queued;
129
+
130
+ /*
131
+ * A change to SETTINGS_INITIAL_WINDOW_SIZE could cause the
132
+ * send_window to become negative, hence it's signed.
133
+ */
134
+ ssize_t send_window;
135
+ size_t recv_window;
136
+
123
137
  ngx_http_spdy_out_frame_t *free_frames;
124
138
  ngx_chain_t *free_data_headers;
139
+ ngx_chain_t *free_bufs;
125
140
 
126
- unsigned priority:2;
141
+ ngx_queue_t queue;
142
+
143
+ unsigned priority:3;
127
144
  unsigned handled:1;
145
+ unsigned blocked:1;
146
+ unsigned exhausted:1;
128
147
  unsigned in_closed:1;
129
148
  unsigned out_closed:1;
130
149
  unsigned skip_data:2;
@@ -138,10 +157,8 @@ struct ngx_http_spdy_out_frame_s {
138
157
  ngx_int_t (*handler)(ngx_http_spdy_connection_t *sc,
139
158
  ngx_http_spdy_out_frame_t *frame);
140
159
 
141
- ngx_http_spdy_out_frame_t *free;
142
-
143
160
  ngx_http_spdy_stream_t *stream;
144
- size_t size;
161
+ size_t length;
145
162
 
146
163
  ngx_uint_t priority;
147
164
  unsigned blocked:1;
@@ -157,6 +174,9 @@ ngx_http_spdy_queue_frame(ngx_http_spdy_connection_t *sc,
157
174
 
158
175
  for (out = &sc->last_out; *out; out = &(*out)->next)
159
176
  {
177
+ /*
178
+ * NB: higher values represent lower priorities.
179
+ */
160
180
  if (frame->priority >= (*out)->priority) {
161
181
  break;
162
182
  }
@@ -173,9 +193,9 @@ ngx_http_spdy_queue_blocked_frame(ngx_http_spdy_connection_t *sc,
173
193
  {
174
194
  ngx_http_spdy_out_frame_t **out;
175
195
 
176
- for (out = &sc->last_out; *out && !(*out)->blocked; out = &(*out)->next)
196
+ for (out = &sc->last_out; *out; out = &(*out)->next)
177
197
  {
178
- if (frame->priority >= (*out)->priority) {
198
+ if ((*out)->blocked) {
179
199
  break;
180
200
  }
181
201
  }
@@ -186,7 +206,7 @@ ngx_http_spdy_queue_blocked_frame(ngx_http_spdy_connection_t *sc,
186
206
 
187
207
 
188
208
  void ngx_http_spdy_init(ngx_event_t *rev);
189
- void ngx_http_spdy_request_headers_init();
209
+ void ngx_http_spdy_request_headers_init(void);
190
210
 
191
211
  ngx_int_t ngx_http_spdy_read_request_body(ngx_http_request_t *r,
192
212
  ngx_http_client_body_handler_pt post_handler);
@@ -229,7 +249,10 @@ ngx_int_t ngx_http_spdy_send_output_queue(ngx_http_spdy_connection_t *sc);
229
249
 
230
250
  #define ngx_spdy_frame_write_flags_and_len(p, f, l) \
231
251
  ngx_spdy_frame_aligned_write_uint32(p, (f) << 24 | (l))
252
+ #define ngx_spdy_frame_write_flags_and_id(p, f, i) \
253
+ ngx_spdy_frame_aligned_write_uint32(p, (f) << 24 | (i))
232
254
 
233
- #define ngx_spdy_frame_write_sid ngx_spdy_frame_aligned_write_uint32
255
+ #define ngx_spdy_frame_write_sid ngx_spdy_frame_aligned_write_uint32
256
+ #define ngx_spdy_frame_write_window ngx_spdy_frame_aligned_write_uint32
234
257
 
235
258
  #endif /* _NGX_HTTP_SPDY_H_INCLUDED_ */
@@ -14,14 +14,12 @@
14
14
  #include <zlib.h>
15
15
 
16
16
 
17
- #define NGX_SPDY_WRITE_BUFFERED NGX_HTTP_WRITE_BUFFERED
18
-
19
17
  #define ngx_http_spdy_nv_nsize(h) (NGX_SPDY_NV_NLEN_SIZE + sizeof(h) - 1)
20
18
  #define ngx_http_spdy_nv_vsize(h) (NGX_SPDY_NV_VLEN_SIZE + sizeof(h) - 1)
21
19
 
22
- #define ngx_http_spdy_nv_write_num ngx_spdy_frame_write_uint16
23
- #define ngx_http_spdy_nv_write_nlen ngx_spdy_frame_write_uint16
24
- #define ngx_http_spdy_nv_write_vlen ngx_spdy_frame_write_uint16
20
+ #define ngx_http_spdy_nv_write_num ngx_spdy_frame_write_uint32
21
+ #define ngx_http_spdy_nv_write_nlen ngx_spdy_frame_write_uint32
22
+ #define ngx_http_spdy_nv_write_vlen ngx_spdy_frame_write_uint32
25
23
 
26
24
  #define ngx_http_spdy_nv_write_name(p, h) \
27
25
  ngx_cpymem(ngx_http_spdy_nv_write_nlen(p, sizeof(h) - 1), h, sizeof(h) - 1)
@@ -29,12 +27,22 @@
29
27
  #define ngx_http_spdy_nv_write_val(p, h) \
30
28
  ngx_cpymem(ngx_http_spdy_nv_write_vlen(p, sizeof(h) - 1), h, sizeof(h) - 1)
31
29
 
30
+
31
+ static ngx_chain_t *ngx_http_spdy_send_chain(ngx_connection_t *fc,
32
+ ngx_chain_t *in, off_t limit);
33
+
32
34
  static ngx_inline ngx_int_t ngx_http_spdy_filter_send(
33
35
  ngx_connection_t *fc, ngx_http_spdy_stream_t *stream);
36
+ static ngx_inline ngx_int_t ngx_http_spdy_flow_control(
37
+ ngx_http_spdy_connection_t *sc, ngx_http_spdy_stream_t *stream);
38
+ static void ngx_http_spdy_waiting_queue(ngx_http_spdy_connection_t *sc,
39
+ ngx_http_spdy_stream_t *stream);
34
40
 
41
+ static ngx_chain_t *ngx_http_spdy_filter_get_shadow(
42
+ ngx_http_spdy_stream_t *stream, ngx_buf_t *buf, off_t offset, off_t size);
35
43
  static ngx_http_spdy_out_frame_t *ngx_http_spdy_filter_get_data_frame(
36
- ngx_http_spdy_stream_t *stream, size_t len, ngx_uint_t flags,
37
- ngx_chain_t *first, ngx_chain_t *last);
44
+ ngx_http_spdy_stream_t *stream, size_t len, ngx_chain_t *first,
45
+ ngx_chain_t *last);
38
46
 
39
47
  static ngx_int_t ngx_http_spdy_syn_frame_handler(
40
48
  ngx_http_spdy_connection_t *sc, ngx_http_spdy_out_frame_t *frame);
@@ -82,7 +90,6 @@ ngx_module_t ngx_http_spdy_filter_module = {
82
90
 
83
91
 
84
92
  static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
85
- static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
86
93
 
87
94
 
88
95
  static ngx_int_t
@@ -159,10 +166,12 @@ ngx_http_spdy_header_filter(ngx_http_request_t *r)
159
166
  }
160
167
 
161
168
  len = NGX_SPDY_NV_NUM_SIZE
162
- + ngx_http_spdy_nv_nsize("version")
169
+ + ngx_http_spdy_nv_nsize(":version")
163
170
  + ngx_http_spdy_nv_vsize("HTTP/1.1")
164
- + ngx_http_spdy_nv_nsize("status")
165
- + ngx_http_spdy_nv_vsize("418");
171
+ + ngx_http_spdy_nv_nsize(":status")
172
+ + (r->headers_out.status_line.len
173
+ ? NGX_SPDY_NV_VLEN_SIZE + r->headers_out.status_line.len
174
+ : ngx_http_spdy_nv_vsize("418"));
166
175
 
167
176
  clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
168
177
 
@@ -300,12 +309,20 @@ ngx_http_spdy_header_filter(ngx_http_request_t *r)
300
309
 
301
310
  last = buf + NGX_SPDY_NV_NUM_SIZE;
302
311
 
303
- last = ngx_http_spdy_nv_write_name(last, "version");
312
+ last = ngx_http_spdy_nv_write_name(last, ":version");
304
313
  last = ngx_http_spdy_nv_write_val(last, "HTTP/1.1");
305
314
 
306
- last = ngx_http_spdy_nv_write_name(last, "status");
307
- last = ngx_spdy_frame_write_uint16(last, 3);
308
- last = ngx_sprintf(last, "%03ui", r->headers_out.status);
315
+ last = ngx_http_spdy_nv_write_name(last, ":status");
316
+
317
+ if (r->headers_out.status_line.len) {
318
+ last = ngx_http_spdy_nv_write_vlen(last,
319
+ r->headers_out.status_line.len);
320
+ last = ngx_cpymem(last, r->headers_out.status_line.data,
321
+ r->headers_out.status_line.len);
322
+ } else {
323
+ last = ngx_http_spdy_nv_write_vlen(last, 3);
324
+ last = ngx_sprintf(last, "%03ui", r->headers_out.status);
325
+ }
309
326
 
310
327
  count = 2;
311
328
 
@@ -444,17 +461,6 @@ ngx_http_spdy_header_filter(ngx_http_request_t *r)
444
461
  continue;
445
462
  }
446
463
 
447
- if ((header[i].key.len == 6
448
- && ngx_strncasecmp(header[i].key.data,
449
- (u_char *) "status", 6) == 0)
450
- || (header[i].key.len == 7
451
- && ngx_strncasecmp(header[i].key.data,
452
- (u_char *) "version", 7) == 0))
453
- {
454
- header[i].hash = 0;
455
- continue;
456
- }
457
-
458
464
  last = ngx_http_spdy_nv_write_nlen(last, header[i].key.len);
459
465
 
460
466
  ngx_strlow(last, header[i].key.data, header[i].key.len);
@@ -500,7 +506,7 @@ ngx_http_spdy_header_filter(ngx_http_request_t *r)
500
506
  count++;
501
507
  }
502
508
 
503
- (void) ngx_spdy_frame_write_uint16(buf, count);
509
+ (void) ngx_http_spdy_nv_write_num(buf, count);
504
510
 
505
511
  stream = r->spdy_stream;
506
512
  sc = stream->connection;
@@ -547,13 +553,14 @@ ngx_http_spdy_header_filter(ngx_http_request_t *r)
547
553
 
548
554
  r->header_size = len;
549
555
 
556
+ len -= NGX_SPDY_FRAME_HEADER_SIZE;
557
+
550
558
  if (r->header_only) {
551
559
  b->last_buf = 1;
552
- p = ngx_spdy_frame_write_flags_and_len(p, NGX_SPDY_FLAG_FIN,
553
- len - NGX_SPDY_FRAME_HEADER_SIZE);
560
+ p = ngx_spdy_frame_write_flags_and_len(p, NGX_SPDY_FLAG_FIN, len);
561
+
554
562
  } else {
555
- p = ngx_spdy_frame_write_flags_and_len(p, 0,
556
- len - NGX_SPDY_FRAME_HEADER_SIZE);
563
+ p = ngx_spdy_frame_write_flags_and_len(p, 0, len);
557
564
  }
558
565
 
559
566
  (void) ngx_spdy_frame_write_sid(p, stream->id);
@@ -574,21 +581,18 @@ ngx_http_spdy_header_filter(ngx_http_request_t *r)
574
581
  frame->first = cl;
575
582
  frame->last = cl;
576
583
  frame->handler = ngx_http_spdy_syn_frame_handler;
577
- frame->free = NULL;
578
584
  frame->stream = stream;
579
- frame->size = len;
585
+ frame->length = len;
580
586
  frame->priority = stream->priority;
581
587
  frame->blocked = 1;
582
588
  frame->fin = r->header_only;
583
589
 
584
590
  ngx_log_debug3(NGX_LOG_DEBUG_HTTP, stream->request->connection->log, 0,
585
- "spdy:%ui create SYN_REPLY frame %p: size:%uz",
586
- stream->id, frame, frame->size);
591
+ "spdy:%ui create SYN_REPLY frame %p: len:%uz",
592
+ stream->id, frame, frame->length);
587
593
 
588
594
  ngx_http_spdy_queue_blocked_frame(sc, frame);
589
595
 
590
- r->blocked++;
591
-
592
596
  cln = ngx_http_cleanup_add(r, 0);
593
597
  if (cln == NULL) {
594
598
  return NGX_ERROR;
@@ -597,109 +601,240 @@ ngx_http_spdy_header_filter(ngx_http_request_t *r)
597
601
  cln->handler = ngx_http_spdy_filter_cleanup;
598
602
  cln->data = stream;
599
603
 
600
- stream->waiting = 1;
604
+ stream->queued = 1;
605
+
606
+ c->send_chain = ngx_http_spdy_send_chain;
607
+ c->need_last_buf = 1;
601
608
 
602
609
  return ngx_http_spdy_filter_send(c, stream);
603
610
  }
604
611
 
605
612
 
606
- static ngx_int_t
607
- ngx_http_spdy_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
613
+ static ngx_chain_t *
614
+ ngx_http_spdy_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit)
608
615
  {
609
- off_t size;
610
- ngx_buf_t *b;
611
- ngx_chain_t *cl, *ll, *out, **ln;
612
- ngx_http_spdy_stream_t *stream;
613
- ngx_http_spdy_out_frame_t *frame;
614
-
616
+ off_t size, offset;
617
+ size_t rest, frame_size;
618
+ ngx_chain_t *cl, *out, **ln;
619
+ ngx_http_request_t *r;
620
+ ngx_http_spdy_stream_t *stream;
621
+ ngx_http_spdy_loc_conf_t *slcf;
622
+ ngx_http_spdy_out_frame_t *frame;
623
+ ngx_http_spdy_connection_t *sc;
624
+
625
+ r = fc->data;
615
626
  stream = r->spdy_stream;
616
627
 
617
- if (stream == NULL) {
618
- return ngx_http_next_body_filter(r, in);
628
+ #if (NGX_SUPPRESS_WARN)
629
+ size = 0;
630
+ #endif
631
+
632
+ while (in) {
633
+ size = ngx_buf_size(in->buf);
634
+
635
+ if (size || in->buf->last_buf) {
636
+ break;
637
+ }
638
+
639
+ in = in->next;
619
640
  }
620
641
 
621
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
622
- "spdy body filter \"%V?%V\"", &r->uri, &r->args);
642
+ if (in == NULL) {
623
643
 
624
- if (in == NULL || r->header_only) {
644
+ if (stream->queued) {
645
+ fc->write->delayed = 1;
646
+ } else {
647
+ fc->buffered &= ~NGX_SPDY_BUFFERED;
648
+ }
625
649
 
626
- if (stream->waiting) {
627
- return NGX_AGAIN;
650
+ return NULL;
651
+ }
652
+
653
+ sc = stream->connection;
654
+
655
+ if (size && ngx_http_spdy_flow_control(sc, stream) == NGX_DECLINED) {
656
+ fc->write->delayed = 1;
657
+ return in;
658
+ }
659
+
660
+ if (limit == 0 || limit > (off_t) sc->send_window) {
661
+ limit = sc->send_window;
662
+ }
663
+
664
+ if (limit > stream->send_window) {
665
+ limit = (stream->send_window > 0) ? stream->send_window : 0;
666
+ }
667
+
668
+ if (in->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow) {
669
+ cl = ngx_alloc_chain_link(r->pool);
670
+ if (cl == NULL) {
671
+ return NGX_CHAIN_ERROR;
628
672
  }
629
673
 
630
- r->connection->buffered &= ~NGX_SPDY_WRITE_BUFFERED;
674
+ cl->buf = in->buf;
675
+ in->buf = cl->buf->shadow;
631
676
 
632
- return NGX_OK;
677
+ offset = ngx_buf_in_memory(in->buf)
678
+ ? (cl->buf->pos - in->buf->pos)
679
+ : (cl->buf->file_pos - in->buf->file_pos);
680
+
681
+ cl->next = stream->free_bufs;
682
+ stream->free_bufs = cl;
683
+
684
+ } else {
685
+ offset = 0;
633
686
  }
634
687
 
635
- size = 0;
636
- ln = &out;
637
- ll = in;
688
+ #if (NGX_SUPPRESS_WARN)
689
+ cl = NULL;
690
+ #endif
691
+
692
+ slcf = ngx_http_get_module_loc_conf(r, ngx_http_spdy_module);
693
+
694
+ frame_size = (limit <= (off_t) slcf->chunk_size) ? (size_t) limit
695
+ : slcf->chunk_size;
638
696
 
639
697
  for ( ;; ) {
640
- b = ll->buf;
641
- #if 1
642
- if (ngx_buf_size(b) == 0 && !ngx_buf_special(b)) {
643
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
644
- "zero size buf in spdy body filter "
645
- "t:%d r:%d f:%d %p %p-%p %p %O-%O",
646
- b->temporary,
647
- b->recycled,
648
- b->in_file,
649
- b->start,
650
- b->pos,
651
- b->last,
652
- b->file,
653
- b->file_pos,
654
- b->file_last);
655
-
656
- ngx_debug_point();
657
- return NGX_ERROR;
698
+ ln = &out;
699
+ rest = frame_size;
700
+
701
+ while ((off_t) rest >= size) {
702
+
703
+ if (offset) {
704
+ cl = ngx_http_spdy_filter_get_shadow(stream, in->buf,
705
+ offset, size);
706
+ if (cl == NULL) {
707
+ return NGX_CHAIN_ERROR;
708
+ }
709
+
710
+ offset = 0;
711
+
712
+ } else {
713
+ cl = ngx_alloc_chain_link(r->pool);
714
+ if (cl == NULL) {
715
+ return NGX_CHAIN_ERROR;
716
+ }
717
+
718
+ cl->buf = in->buf;
719
+ }
720
+
721
+ *ln = cl;
722
+ ln = &cl->next;
723
+
724
+ rest -= (size_t) size;
725
+ in = in->next;
726
+
727
+ if (in == NULL) {
728
+ frame_size -= rest;
729
+ rest = 0;
730
+ break;
731
+ }
732
+
733
+ size = ngx_buf_size(in->buf);
658
734
  }
659
- #endif
660
- cl = ngx_alloc_chain_link(r->pool);
661
- if (cl == NULL) {
662
- return NGX_ERROR;
735
+
736
+ if (rest) {
737
+ cl = ngx_http_spdy_filter_get_shadow(stream, in->buf,
738
+ offset, rest);
739
+ if (cl == NULL) {
740
+ return NGX_CHAIN_ERROR;
741
+ }
742
+
743
+ cl->buf->flush = 0;
744
+ cl->buf->last_buf = 0;
745
+
746
+ *ln = cl;
747
+
748
+ offset += rest;
749
+ size -= rest;
663
750
  }
664
751
 
665
- size += ngx_buf_size(b);
666
- cl->buf = b;
752
+ frame = ngx_http_spdy_filter_get_data_frame(stream, frame_size,
753
+ out, cl);
754
+ if (frame == NULL) {
755
+ return NGX_CHAIN_ERROR;
756
+ }
757
+
758
+ ngx_http_spdy_queue_frame(sc, frame);
759
+
760
+ sc->send_window -= frame_size;
761
+
762
+ stream->send_window -= frame_size;
763
+ stream->queued++;
764
+
765
+ if (in == NULL) {
766
+ break;
767
+ }
667
768
 
668
- *ln = cl;
669
- ln = &cl->next;
769
+ limit -= frame_size;
670
770
 
671
- if (ll->next == NULL) {
771
+ if (limit == 0) {
672
772
  break;
673
773
  }
674
774
 
675
- ll = ll->next;
775
+ if (limit < (off_t) slcf->chunk_size) {
776
+ frame_size = (size_t) limit;
777
+ }
676
778
  }
677
779
 
678
- if (size > NGX_SPDY_MAX_FRAME_SIZE) {
679
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
680
- "FIXME: chain too big in spdy filter: %O", size);
681
- return NGX_ERROR;
780
+ if (offset) {
781
+ cl = ngx_http_spdy_filter_get_shadow(stream, in->buf, offset, size);
782
+ if (cl == NULL) {
783
+ return NGX_CHAIN_ERROR;
784
+ }
785
+
786
+ in->buf = cl->buf;
787
+ ngx_free_chain(r->pool, cl);
682
788
  }
683
789
 
684
- frame = ngx_http_spdy_filter_get_data_frame(stream, (size_t) size,
685
- b->last_buf, out, cl);
686
- if (frame == NULL) {
687
- return NGX_ERROR;
790
+ if (ngx_http_spdy_filter_send(fc, stream) == NGX_ERROR) {
791
+ return NGX_CHAIN_ERROR;
792
+ }
793
+
794
+ if (in && ngx_http_spdy_flow_control(sc, stream) == NGX_DECLINED) {
795
+ fc->write->delayed = 1;
688
796
  }
689
797
 
690
- ngx_http_spdy_queue_frame(stream->connection, frame);
798
+ return in;
799
+ }
800
+
801
+
802
+ static ngx_chain_t *
803
+ ngx_http_spdy_filter_get_shadow(ngx_http_spdy_stream_t *stream, ngx_buf_t *buf,
804
+ off_t offset, off_t size)
805
+ {
806
+ ngx_buf_t *chunk;
807
+ ngx_chain_t *cl;
808
+
809
+ cl = ngx_chain_get_free_buf(stream->request->pool, &stream->free_bufs);
810
+ if (cl == NULL) {
811
+ return NULL;
812
+ }
813
+
814
+ chunk = cl->buf;
815
+
816
+ ngx_memcpy(chunk, buf, sizeof(ngx_buf_t));
691
817
 
692
- stream->waiting++;
818
+ chunk->tag = (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow;
819
+ chunk->shadow = buf;
693
820
 
694
- r->main->blocked++;
821
+ if (ngx_buf_in_memory(chunk)) {
822
+ chunk->pos += offset;
823
+ chunk->last = chunk->pos + size;
824
+ }
825
+
826
+ if (chunk->in_file) {
827
+ chunk->file_pos += offset;
828
+ chunk->file_last = chunk->file_pos + size;
829
+ }
695
830
 
696
- return ngx_http_spdy_filter_send(r->connection, stream);
831
+ return cl;
697
832
  }
698
833
 
699
834
 
700
835
  static ngx_http_spdy_out_frame_t *
701
836
  ngx_http_spdy_filter_get_data_frame(ngx_http_spdy_stream_t *stream,
702
- size_t len, ngx_uint_t fin, ngx_chain_t *first, ngx_chain_t *last)
837
+ size_t len, ngx_chain_t *first, ngx_chain_t *last)
703
838
  {
704
839
  u_char *p;
705
840
  ngx_buf_t *buf;
@@ -711,7 +846,7 @@ ngx_http_spdy_filter_get_data_frame(ngx_http_spdy_stream_t *stream,
711
846
  frame = stream->free_frames;
712
847
 
713
848
  if (frame) {
714
- stream->free_frames = frame->free;
849
+ stream->free_frames = frame->next;
715
850
 
716
851
  } else {
717
852
  frame = ngx_palloc(stream->request->pool,
@@ -721,62 +856,60 @@ ngx_http_spdy_filter_get_data_frame(ngx_http_spdy_stream_t *stream,
721
856
  }
722
857
  }
723
858
 
859
+ flags = last->buf->last_buf ? NGX_SPDY_FLAG_FIN : 0;
860
+
724
861
  ngx_log_debug4(NGX_LOG_DEBUG_HTTP, stream->request->connection->log, 0,
725
- "spdy:%ui create DATA frame %p: len:%uz fin:%ui",
726
- stream->id, frame, len, fin);
862
+ "spdy:%ui create DATA frame %p: len:%uz flags:%ui",
863
+ stream->id, frame, len, flags);
727
864
 
728
- if (len || fin) {
865
+ cl = ngx_chain_get_free_buf(stream->request->pool,
866
+ &stream->free_data_headers);
867
+ if (cl == NULL) {
868
+ return NULL;
869
+ }
729
870
 
730
- flags = fin ? NGX_SPDY_FLAG_FIN : 0;
871
+ buf = cl->buf;
731
872
 
732
- cl = ngx_chain_get_free_buf(stream->request->pool,
733
- &stream->free_data_headers);
734
- if (cl == NULL) {
735
- return NULL;
736
- }
873
+ if (buf->start) {
874
+ p = buf->start;
875
+ buf->pos = p;
737
876
 
738
- buf = cl->buf;
877
+ p += NGX_SPDY_SID_SIZE;
739
878
 
740
- if (buf->start) {
741
- p = buf->start;
742
- buf->pos = p;
879
+ (void) ngx_spdy_frame_write_flags_and_len(p, flags, len);
743
880
 
744
- p += sizeof(uint32_t);
881
+ } else {
882
+ p = ngx_palloc(stream->request->pool, NGX_SPDY_FRAME_HEADER_SIZE);
883
+ if (p == NULL) {
884
+ return NULL;
885
+ }
745
886
 
746
- (void) ngx_spdy_frame_write_flags_and_len(p, flags, len);
887
+ buf->pos = p;
888
+ buf->start = p;
747
889
 
748
- } else {
749
- p = ngx_palloc(stream->request->pool, NGX_SPDY_FRAME_HEADER_SIZE);
750
- if (p == NULL) {
751
- return NULL;
752
- }
890
+ p = ngx_spdy_frame_write_sid(p, stream->id);
891
+ p = ngx_spdy_frame_write_flags_and_len(p, flags, len);
753
892
 
754
- buf->pos = p;
755
- buf->start = p;
893
+ buf->last = p;
894
+ buf->end = p;
756
895
 
757
- p = ngx_spdy_frame_write_sid(p, stream->id);
758
- p = ngx_spdy_frame_write_flags_and_len(p, flags, len);
759
-
760
- buf->last = p;
761
- buf->end = p;
896
+ buf->tag = (ngx_buf_tag_t) &ngx_http_spdy_filter_get_data_frame;
897
+ buf->memory = 1;
898
+ }
762
899
 
763
- buf->tag = (ngx_buf_tag_t) &ngx_http_spdy_filter_module;
764
- buf->memory = 1;
765
- }
900
+ cl->next = first;
901
+ first = cl;
766
902
 
767
- cl->next = first;
768
- first = cl;
769
- }
903
+ last->buf->flush = 1;
770
904
 
771
905
  frame->first = first;
772
906
  frame->last = last;
773
907
  frame->handler = ngx_http_spdy_data_frame_handler;
774
- frame->free = NULL;
775
908
  frame->stream = stream;
776
- frame->size = NGX_SPDY_FRAME_HEADER_SIZE + len;
909
+ frame->length = len;
777
910
  frame->priority = stream->priority;
778
911
  frame->blocked = 0;
779
- frame->fin = fin;
912
+ frame->fin = last->buf->last_buf;
780
913
 
781
914
  return frame;
782
915
  }
@@ -785,23 +918,76 @@ ngx_http_spdy_filter_get_data_frame(ngx_http_spdy_stream_t *stream,
785
918
  static ngx_inline ngx_int_t
786
919
  ngx_http_spdy_filter_send(ngx_connection_t *fc, ngx_http_spdy_stream_t *stream)
787
920
  {
921
+ stream->blocked = 1;
922
+
788
923
  if (ngx_http_spdy_send_output_queue(stream->connection) == NGX_ERROR) {
789
924
  fc->error = 1;
790
925
  return NGX_ERROR;
791
926
  }
792
927
 
793
- if (stream->waiting) {
794
- fc->buffered |= NGX_SPDY_WRITE_BUFFERED;
928
+ stream->blocked = 0;
929
+
930
+ if (stream->queued) {
931
+ fc->buffered |= NGX_SPDY_BUFFERED;
795
932
  fc->write->delayed = 1;
796
933
  return NGX_AGAIN;
797
934
  }
798
935
 
799
- fc->buffered &= ~NGX_SPDY_WRITE_BUFFERED;
936
+ fc->buffered &= ~NGX_SPDY_BUFFERED;
937
+
938
+ return NGX_OK;
939
+ }
940
+
941
+
942
+ static ngx_inline ngx_int_t
943
+ ngx_http_spdy_flow_control(ngx_http_spdy_connection_t *sc,
944
+ ngx_http_spdy_stream_t *stream)
945
+ {
946
+ if (stream->send_window <= 0) {
947
+ stream->exhausted = 1;
948
+ return NGX_DECLINED;
949
+ }
950
+
951
+ if (sc->send_window == 0) {
952
+ ngx_http_spdy_waiting_queue(sc, stream);
953
+ return NGX_DECLINED;
954
+ }
800
955
 
801
956
  return NGX_OK;
802
957
  }
803
958
 
804
959
 
960
+ static void
961
+ ngx_http_spdy_waiting_queue(ngx_http_spdy_connection_t *sc,
962
+ ngx_http_spdy_stream_t *stream)
963
+ {
964
+ ngx_queue_t *q;
965
+ ngx_http_spdy_stream_t *s;
966
+
967
+ if (stream->handled) {
968
+ return;
969
+ }
970
+
971
+ stream->handled = 1;
972
+
973
+ for (q = ngx_queue_last(&sc->waiting);
974
+ q != ngx_queue_sentinel(&sc->waiting);
975
+ q = ngx_queue_prev(q))
976
+ {
977
+ s = ngx_queue_data(q, ngx_http_spdy_stream_t, queue);
978
+
979
+ /*
980
+ * NB: higher values represent lower priorities.
981
+ */
982
+ if (stream->priority >= s->priority) {
983
+ break;
984
+ }
985
+ }
986
+
987
+ ngx_queue_insert_after(q, &stream->queue);
988
+ }
989
+
990
+
805
991
  static ngx_int_t
806
992
  ngx_http_spdy_syn_frame_handler(ngx_http_spdy_connection_t *sc,
807
993
  ngx_http_spdy_out_frame_t *frame)
@@ -834,6 +1020,7 @@ static ngx_int_t
834
1020
  ngx_http_spdy_data_frame_handler(ngx_http_spdy_connection_t *sc,
835
1021
  ngx_http_spdy_out_frame_t *frame)
836
1022
  {
1023
+ ngx_buf_t *buf;
837
1024
  ngx_chain_t *cl, *ln;
838
1025
  ngx_http_spdy_stream_t *stream;
839
1026
 
@@ -841,7 +1028,7 @@ ngx_http_spdy_data_frame_handler(ngx_http_spdy_connection_t *sc,
841
1028
 
842
1029
  cl = frame->first;
843
1030
 
844
- if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_module) {
1031
+ if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_data_frame) {
845
1032
 
846
1033
  if (cl->buf->pos != cl->buf->last) {
847
1034
  ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
@@ -864,6 +1051,18 @@ ngx_http_spdy_data_frame_handler(ngx_http_spdy_connection_t *sc,
864
1051
  }
865
1052
 
866
1053
  for ( ;; ) {
1054
+ if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow) {
1055
+ buf = cl->buf->shadow;
1056
+
1057
+ if (ngx_buf_in_memory(buf)) {
1058
+ buf->pos = cl->buf->pos;
1059
+ }
1060
+
1061
+ if (buf->in_file) {
1062
+ buf->file_pos = cl->buf->file_pos;
1063
+ }
1064
+ }
1065
+
867
1066
  if (ngx_buf_size(cl->buf) != 0) {
868
1067
 
869
1068
  if (cl != frame->first) {
@@ -880,7 +1079,13 @@ ngx_http_spdy_data_frame_handler(ngx_http_spdy_connection_t *sc,
880
1079
 
881
1080
  ln = cl->next;
882
1081
 
883
- ngx_free_chain(stream->request->pool, cl);
1082
+ if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow) {
1083
+ cl->next = stream->free_bufs;
1084
+ stream->free_bufs = cl;
1085
+
1086
+ } else {
1087
+ ngx_free_chain(stream->request->pool, cl);
1088
+ }
884
1089
 
885
1090
  if (cl == frame->last) {
886
1091
  goto done;
@@ -912,17 +1117,16 @@ ngx_http_spdy_handle_frame(ngx_http_spdy_stream_t *stream,
912
1117
 
913
1118
  r = stream->request;
914
1119
 
915
- r->connection->sent += frame->size;
916
- r->blocked--;
1120
+ r->connection->sent += NGX_SPDY_FRAME_HEADER_SIZE + frame->length;
917
1121
 
918
1122
  if (frame->fin) {
919
1123
  stream->out_closed = 1;
920
1124
  }
921
1125
 
922
- frame->free = stream->free_frames;
1126
+ frame->next = stream->free_frames;
923
1127
  stream->free_frames = frame;
924
1128
 
925
- stream->waiting--;
1129
+ stream->queued--;
926
1130
  }
927
1131
 
928
1132
 
@@ -930,21 +1134,19 @@ static ngx_inline void
930
1134
  ngx_http_spdy_handle_stream(ngx_http_spdy_connection_t *sc,
931
1135
  ngx_http_spdy_stream_t *stream)
932
1136
  {
933
- ngx_connection_t *fc;
934
-
935
- fc = stream->request->connection;
936
-
937
- fc->write->delayed = 0;
1137
+ ngx_event_t *wev;
938
1138
 
939
- if (stream->handled) {
1139
+ if (stream->handled || stream->blocked || stream->exhausted) {
940
1140
  return;
941
1141
  }
942
1142
 
943
- if (sc->blocked == 2) {
944
- stream->handled = 1;
1143
+ wev = stream->request->connection->write;
1144
+
1145
+ if (!wev->timer_set) {
1146
+ wev->delayed = 0;
945
1147
 
946
- stream->next = sc->last_stream;
947
- sc->last_stream = stream;
1148
+ stream->handled = 1;
1149
+ ngx_queue_insert_tail(&sc->posted, &stream->queue);
948
1150
  }
949
1151
  }
950
1152
 
@@ -954,16 +1156,22 @@ ngx_http_spdy_filter_cleanup(void *data)
954
1156
  {
955
1157
  ngx_http_spdy_stream_t *stream = data;
956
1158
 
957
- ngx_http_request_t *r;
958
- ngx_http_spdy_out_frame_t *frame, **fn;
1159
+ size_t delta;
1160
+ ngx_http_spdy_out_frame_t *frame, **fn;
1161
+ ngx_http_spdy_connection_t *sc;
959
1162
 
960
- if (stream->waiting == 0) {
961
- return;
1163
+ if (stream->handled) {
1164
+ stream->handled = 0;
1165
+ ngx_queue_remove(&stream->queue);
962
1166
  }
963
1167
 
964
- r = stream->request;
1168
+ if (stream->queued == 0) {
1169
+ return;
1170
+ }
965
1171
 
966
- fn = &stream->connection->last_out;
1172
+ delta = 0;
1173
+ sc = stream->connection;
1174
+ fn = &sc->last_out;
967
1175
 
968
1176
  for ( ;; ) {
969
1177
  frame = *fn;
@@ -973,16 +1181,26 @@ ngx_http_spdy_filter_cleanup(void *data)
973
1181
  }
974
1182
 
975
1183
  if (frame->stream == stream && !frame->blocked) {
1184
+ *fn = frame->next;
976
1185
 
977
- stream->waiting--;
978
- r->blocked--;
1186
+ delta += frame->length;
1187
+
1188
+ if (--stream->queued == 0) {
1189
+ break;
1190
+ }
979
1191
 
980
- *fn = frame->next;
981
1192
  continue;
982
1193
  }
983
1194
 
984
1195
  fn = &frame->next;
985
1196
  }
1197
+
1198
+ if (sc->send_window == 0 && delta && !ngx_queue_empty(&sc->waiting)) {
1199
+ ngx_queue_add(&sc->posted, &sc->waiting);
1200
+ ngx_queue_init(&sc->waiting);
1201
+ }
1202
+
1203
+ sc->send_window += delta;
986
1204
  }
987
1205
 
988
1206
 
@@ -992,8 +1210,5 @@ ngx_http_spdy_filter_init(ngx_conf_t *cf)
992
1210
  ngx_http_next_header_filter = ngx_http_top_header_filter;
993
1211
  ngx_http_top_header_filter = ngx_http_spdy_header_filter;
994
1212
 
995
- ngx_http_next_body_filter = ngx_http_top_body_filter;
996
- ngx_http_top_body_filter = ngx_http_spdy_body_filter;
997
-
998
1213
  return NGX_OK;
999
1214
  }