nginxtra 1.2.8.8 → 1.4.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/bin/nginxtra +1 -1
  2. data/bin/nginxtra_rails +1 -1
  3. data/lib/nginxtra/version.rb +1 -1
  4. data/vendor/nginx/CHANGES +202 -63
  5. data/vendor/nginx/CHANGES.ru +208 -66
  6. data/vendor/nginx/auto/lib/md5/conf +3 -3
  7. data/vendor/nginx/auto/lib/perl/conf +3 -1
  8. data/vendor/nginx/auto/lib/perl/make +21 -16
  9. data/vendor/nginx/auto/lib/sha1/conf +1 -1
  10. data/vendor/nginx/auto/modules +25 -4
  11. data/vendor/nginx/auto/options +7 -1
  12. data/vendor/nginx/auto/sources +15 -1
  13. data/vendor/nginx/auto/unix +14 -0
  14. data/vendor/nginx/src/core/nginx.h +2 -2
  15. data/vendor/nginx/src/core/ngx_array.c +1 -7
  16. data/vendor/nginx/src/core/ngx_array.h +2 -2
  17. data/vendor/nginx/src/core/ngx_connection.c +13 -7
  18. data/vendor/nginx/src/core/ngx_connection.h +1 -2
  19. data/vendor/nginx/src/core/ngx_core.h +1 -2
  20. data/vendor/nginx/src/core/ngx_crypt.c +37 -0
  21. data/vendor/nginx/src/core/ngx_cycle.h +1 -1
  22. data/vendor/nginx/src/core/ngx_inet.c +219 -48
  23. data/vendor/nginx/src/core/ngx_inet.h +1 -1
  24. data/vendor/nginx/src/event/modules/ngx_devpoll_module.c +7 -1
  25. data/vendor/nginx/src/event/modules/ngx_eventport_module.c +1 -1
  26. data/vendor/nginx/src/event/ngx_event.c +5 -1
  27. data/vendor/nginx/src/event/ngx_event.h +1 -0
  28. data/vendor/nginx/src/event/ngx_event_connect.c +1 -1
  29. data/vendor/nginx/src/event/ngx_event_openssl.c +135 -9
  30. data/vendor/nginx/src/event/ngx_event_openssl.h +9 -0
  31. data/vendor/nginx/src/event/ngx_event_openssl_stapling.c +1749 -0
  32. data/vendor/nginx/src/http/modules/ngx_http_addition_filter_module.c +1 -0
  33. data/vendor/nginx/src/http/modules/ngx_http_chunked_filter_module.c +1 -0
  34. data/vendor/nginx/src/http/modules/ngx_http_fastcgi_module.c +5 -0
  35. data/vendor/nginx/src/http/modules/ngx_http_flv_module.c +4 -0
  36. data/vendor/nginx/src/http/modules/ngx_http_geo_module.c +7 -8
  37. data/vendor/nginx/src/http/modules/ngx_http_geoip_module.c +10 -12
  38. data/vendor/nginx/src/http/modules/ngx_http_gunzip_filter_module.c +677 -0
  39. data/vendor/nginx/src/http/modules/ngx_http_gzip_filter_module.c +3 -0
  40. data/vendor/nginx/src/http/modules/ngx_http_gzip_static_module.c +36 -10
  41. data/vendor/nginx/src/http/modules/ngx_http_headers_filter_module.c +31 -13
  42. data/vendor/nginx/src/http/modules/ngx_http_image_filter_module.c +13 -0
  43. data/vendor/nginx/src/http/modules/ngx_http_limit_conn_module.c +18 -2
  44. data/vendor/nginx/src/http/modules/ngx_http_limit_req_module.c +19 -2
  45. data/vendor/nginx/src/http/modules/ngx_http_map_module.c +1 -1
  46. data/vendor/nginx/src/http/modules/ngx_http_memcached_module.c +60 -8
  47. data/vendor/nginx/src/http/modules/ngx_http_mp4_module.c +4 -8
  48. data/vendor/nginx/src/http/modules/ngx_http_not_modified_filter_module.c +126 -29
  49. data/vendor/nginx/src/http/modules/ngx_http_proxy_module.c +59 -301
  50. data/vendor/nginx/src/http/modules/ngx_http_range_filter_module.c +34 -6
  51. data/vendor/nginx/src/http/modules/ngx_http_realip_module.c +13 -12
  52. data/vendor/nginx/src/http/modules/ngx_http_scgi_module.c +30 -11
  53. data/vendor/nginx/src/http/modules/ngx_http_ssi_filter_module.c +1 -0
  54. data/vendor/nginx/src/http/modules/ngx_http_ssl_module.c +155 -4
  55. data/vendor/nginx/src/http/modules/ngx_http_ssl_module.h +6 -0
  56. data/vendor/nginx/src/http/modules/ngx_http_static_module.c +4 -0
  57. data/vendor/nginx/src/http/modules/ngx_http_stub_status_module.c +90 -3
  58. data/vendor/nginx/src/http/modules/ngx_http_sub_filter_module.c +1 -0
  59. data/vendor/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c +5 -0
  60. data/vendor/nginx/src/http/modules/ngx_http_upstream_least_conn_module.c +5 -0
  61. data/vendor/nginx/src/http/modules/ngx_http_uwsgi_module.c +14 -1
  62. data/vendor/nginx/src/http/modules/ngx_http_xslt_filter_module.c +1 -0
  63. data/vendor/nginx/src/http/modules/perl/Makefile.PL +4 -2
  64. data/vendor/nginx/src/http/modules/perl/nginx.pm +1 -1
  65. data/vendor/nginx/src/http/modules/perl/nginx.xs +36 -3
  66. data/vendor/nginx/src/http/ngx_http.c +24 -1
  67. data/vendor/nginx/src/http/ngx_http.h +26 -2
  68. data/vendor/nginx/src/http/ngx_http_core_module.c +136 -10
  69. data/vendor/nginx/src/http/ngx_http_core_module.h +37 -13
  70. data/vendor/nginx/src/http/ngx_http_header_filter_module.c +9 -2
  71. data/vendor/nginx/src/http/ngx_http_parse.c +404 -0
  72. data/vendor/nginx/src/http/ngx_http_request.c +840 -517
  73. data/vendor/nginx/src/http/ngx_http_request.h +37 -25
  74. data/vendor/nginx/src/http/ngx_http_request_body.c +585 -156
  75. data/vendor/nginx/src/http/ngx_http_spdy.c +2882 -0
  76. data/vendor/nginx/src/http/ngx_http_spdy.h +235 -0
  77. data/vendor/nginx/src/http/ngx_http_spdy_filter_module.c +999 -0
  78. data/vendor/nginx/src/http/ngx_http_spdy_module.c +351 -0
  79. data/vendor/nginx/src/http/ngx_http_spdy_module.h +36 -0
  80. data/vendor/nginx/src/http/ngx_http_special_response.c +3 -1
  81. data/vendor/nginx/src/http/ngx_http_upstream.c +415 -26
  82. data/vendor/nginx/src/http/ngx_http_upstream.h +11 -1
  83. data/vendor/nginx/src/http/ngx_http_upstream_round_robin.c +2 -45
  84. data/vendor/nginx/src/http/ngx_http_upstream_round_robin.h +0 -2
  85. data/vendor/nginx/src/http/ngx_http_variables.c +72 -12
  86. data/vendor/nginx/src/mail/ngx_mail.h +2 -2
  87. data/vendor/nginx/src/mail/ngx_mail_auth_http_module.c +35 -25
  88. data/vendor/nginx/src/mail/ngx_mail_core_module.c +5 -1
  89. metadata +9 -2
@@ -0,0 +1,235 @@
1
+ /*
2
+ * Copyright (C) Nginx, Inc.
3
+ * Copyright (C) Valentin V. Bartenev
4
+ */
5
+
6
+
7
+ #ifndef _NGX_HTTP_SPDY_H_INCLUDED_
8
+ #define _NGX_HTTP_SPDY_H_INCLUDED_
9
+
10
+
11
+ #include <ngx_config.h>
12
+ #include <ngx_core.h>
13
+ #include <ngx_http.h>
14
+
15
+ #include <zlib.h>
16
+
17
+
18
+ #define NGX_SPDY_VERSION 2
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
24
+
25
+ #define NGX_SPDY_STATE_BUFFER_SIZE 16
26
+
27
+ #define NGX_SPDY_CTL_BIT 1
28
+
29
+ #define NGX_SPDY_SYN_STREAM 1
30
+ #define NGX_SPDY_SYN_REPLY 2
31
+ #define NGX_SPDY_RST_STREAM 3
32
+ #define NGX_SPDY_SETTINGS 4
33
+ #define NGX_SPDY_NOOP 5
34
+ #define NGX_SPDY_PING 6
35
+ #define NGX_SPDY_GOAWAY 7
36
+ #define NGX_SPDY_HEADERS 8
37
+
38
+ #define NGX_SPDY_FRAME_HEADER_SIZE 8
39
+
40
+ #define NGX_SPDY_SID_SIZE 4
41
+
42
+ #define NGX_SPDY_SYN_STREAM_SIZE 10
43
+ #define NGX_SPDY_SYN_REPLY_SIZE 6
44
+ #define NGX_SPDY_RST_STREAM_SIZE 8
45
+ #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
50
+ #define NGX_SPDY_SETTINGS_NUM_SIZE 4
51
+ #define NGX_SPDY_SETTINGS_IDF_SIZE 4
52
+ #define NGX_SPDY_SETTINGS_VAL_SIZE 4
53
+
54
+ #define NGX_SPDY_SETTINGS_PAIR_SIZE \
55
+ (NGX_SPDY_SETTINGS_IDF_SIZE + NGX_SPDY_SETTINGS_VAL_SIZE)
56
+
57
+ #define NGX_SPDY_HIGHEST_PRIORITY 0
58
+ #define NGX_SPDY_LOWEST_PRIORITY 3
59
+
60
+ #define NGX_SPDY_FLAG_FIN 0x01
61
+ #define NGX_SPDY_FLAG_UNIDIRECTIONAL 0x02
62
+ #define NGX_SPDY_FLAG_CLEAR_SETTINGS 0x01
63
+
64
+ #define NGX_SPDY_MAX_FRAME_SIZE ((1 << 24) - 1)
65
+
66
+ #define NGX_SPDY_DATA_DISCARD 1
67
+ #define NGX_SPDY_DATA_ERROR 2
68
+ #define NGX_SPDY_DATA_INTERNAL_ERROR 3
69
+
70
+
71
+ typedef struct ngx_http_spdy_connection_s ngx_http_spdy_connection_t;
72
+ typedef struct ngx_http_spdy_out_frame_s ngx_http_spdy_out_frame_t;
73
+
74
+
75
+ typedef u_char *(*ngx_http_spdy_handler_pt) (ngx_http_spdy_connection_t *sc,
76
+ u_char *pos, u_char *end);
77
+
78
+ struct ngx_http_spdy_connection_s {
79
+ ngx_connection_t *connection;
80
+ ngx_http_connection_t *http_connection;
81
+
82
+ ngx_uint_t processing;
83
+
84
+ u_char buffer[NGX_SPDY_STATE_BUFFER_SIZE];
85
+ size_t buffer_used;
86
+ ngx_http_spdy_handler_pt handler;
87
+
88
+ z_stream zstream_in;
89
+ z_stream zstream_out;
90
+
91
+ ngx_pool_t *pool;
92
+
93
+ ngx_http_spdy_out_frame_t *free_ctl_frames;
94
+ ngx_connection_t *free_fake_connections;
95
+
96
+ ngx_http_spdy_stream_t **streams_index;
97
+
98
+ ngx_http_spdy_out_frame_t *last_out;
99
+ ngx_http_spdy_stream_t *last_stream;
100
+
101
+ ngx_http_spdy_stream_t *stream;
102
+
103
+ ngx_uint_t headers;
104
+ size_t length;
105
+ u_char flags;
106
+
107
+ ngx_uint_t last_sid;
108
+
109
+ unsigned blocked:2;
110
+ unsigned waiting:1; /* FIXME better name */
111
+ };
112
+
113
+
114
+ struct ngx_http_spdy_stream_s {
115
+ ngx_uint_t id;
116
+ ngx_http_request_t *request;
117
+ ngx_http_spdy_connection_t *connection;
118
+ ngx_http_spdy_stream_t *index;
119
+ ngx_http_spdy_stream_t *next;
120
+
121
+ ngx_uint_t header_buffers;
122
+ ngx_uint_t waiting;
123
+ ngx_http_spdy_out_frame_t *free_frames;
124
+ ngx_chain_t *free_data_headers;
125
+
126
+ unsigned priority:2;
127
+ unsigned handled:1;
128
+ unsigned in_closed:1;
129
+ unsigned out_closed:1;
130
+ unsigned skip_data:2;
131
+ };
132
+
133
+
134
+ struct ngx_http_spdy_out_frame_s {
135
+ ngx_http_spdy_out_frame_t *next;
136
+ ngx_chain_t *first;
137
+ ngx_chain_t *last;
138
+ ngx_int_t (*handler)(ngx_http_spdy_connection_t *sc,
139
+ ngx_http_spdy_out_frame_t *frame);
140
+
141
+ ngx_http_spdy_out_frame_t *free;
142
+
143
+ ngx_http_spdy_stream_t *stream;
144
+ size_t size;
145
+
146
+ ngx_uint_t priority;
147
+ unsigned blocked:1;
148
+ unsigned fin:1;
149
+ };
150
+
151
+
152
+ static ngx_inline void
153
+ ngx_http_spdy_queue_frame(ngx_http_spdy_connection_t *sc,
154
+ ngx_http_spdy_out_frame_t *frame)
155
+ {
156
+ ngx_http_spdy_out_frame_t **out;
157
+
158
+ for (out = &sc->last_out; *out; out = &(*out)->next)
159
+ {
160
+ if (frame->priority >= (*out)->priority) {
161
+ break;
162
+ }
163
+ }
164
+
165
+ frame->next = *out;
166
+ *out = frame;
167
+ }
168
+
169
+
170
+ static ngx_inline void
171
+ ngx_http_spdy_queue_blocked_frame(ngx_http_spdy_connection_t *sc,
172
+ ngx_http_spdy_out_frame_t *frame)
173
+ {
174
+ ngx_http_spdy_out_frame_t **out;
175
+
176
+ for (out = &sc->last_out; *out && !(*out)->blocked; out = &(*out)->next)
177
+ {
178
+ if (frame->priority >= (*out)->priority) {
179
+ break;
180
+ }
181
+ }
182
+
183
+ frame->next = *out;
184
+ *out = frame;
185
+ }
186
+
187
+
188
+ void ngx_http_spdy_init(ngx_event_t *rev);
189
+ void ngx_http_spdy_request_headers_init();
190
+
191
+ ngx_int_t ngx_http_spdy_read_request_body(ngx_http_request_t *r,
192
+ ngx_http_client_body_handler_pt post_handler);
193
+
194
+ void ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc);
195
+
196
+ ngx_int_t ngx_http_spdy_send_output_queue(ngx_http_spdy_connection_t *sc);
197
+
198
+
199
+ #define ngx_spdy_frame_aligned_write_uint16(p, s) \
200
+ (*(uint16_t *) (p) = htons((uint16_t) (s)), (p) + sizeof(uint16_t))
201
+
202
+ #define ngx_spdy_frame_aligned_write_uint32(p, s) \
203
+ (*(uint32_t *) (p) = htonl((uint32_t) (s)), (p) + sizeof(uint32_t))
204
+
205
+ #if (NGX_HAVE_NONALIGNED)
206
+
207
+ #define ngx_spdy_frame_write_uint16 ngx_spdy_frame_aligned_write_uint16
208
+ #define ngx_spdy_frame_write_uint32 ngx_spdy_frame_aligned_write_uint32
209
+
210
+ #else
211
+
212
+ #define ngx_spdy_frame_write_uint16(p, s) \
213
+ ((p)[0] = (u_char) (s) >> 8, (p)[1] = (u_char) (s), (p) + sizeof(uint16_t))
214
+
215
+ #define ngx_spdy_frame_write_uint32(p, s) \
216
+ ((p)[0] = (u_char) (s) >> 24, \
217
+ (p)[1] = (u_char) (s) >> 16, \
218
+ (p)[2] = (u_char) (s) >> 8, \
219
+ (p)[3] = (u_char) (s), (p) + sizeof(uint32_t))
220
+
221
+ #endif
222
+
223
+
224
+ #define ngx_spdy_ctl_frame_head(t) \
225
+ ((uint32_t) NGX_SPDY_CTL_BIT << 31 | NGX_SPDY_VERSION << 16 | (t))
226
+
227
+ #define ngx_spdy_frame_write_head(p, t) \
228
+ ngx_spdy_frame_aligned_write_uint32(p, ngx_spdy_ctl_frame_head(t))
229
+
230
+ #define ngx_spdy_frame_write_flags_and_len(p, f, l) \
231
+ ngx_spdy_frame_aligned_write_uint32(p, (f) << 24 | (l))
232
+
233
+ #define ngx_spdy_frame_write_sid ngx_spdy_frame_aligned_write_uint32
234
+
235
+ #endif /* _NGX_HTTP_SPDY_H_INCLUDED_ */
@@ -0,0 +1,999 @@
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_spdy_module.h>
13
+
14
+ #include <zlib.h>
15
+
16
+
17
+ #define NGX_SPDY_WRITE_BUFFERED NGX_HTTP_WRITE_BUFFERED
18
+
19
+ #define ngx_http_spdy_nv_nsize(h) (NGX_SPDY_NV_NLEN_SIZE + sizeof(h) - 1)
20
+ #define ngx_http_spdy_nv_vsize(h) (NGX_SPDY_NV_VLEN_SIZE + sizeof(h) - 1)
21
+
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
25
+
26
+ #define ngx_http_spdy_nv_write_name(p, h) \
27
+ ngx_cpymem(ngx_http_spdy_nv_write_nlen(p, sizeof(h) - 1), h, sizeof(h) - 1)
28
+
29
+ #define ngx_http_spdy_nv_write_val(p, h) \
30
+ ngx_cpymem(ngx_http_spdy_nv_write_vlen(p, sizeof(h) - 1), h, sizeof(h) - 1)
31
+
32
+ static ngx_inline ngx_int_t ngx_http_spdy_filter_send(
33
+ ngx_connection_t *fc, ngx_http_spdy_stream_t *stream);
34
+
35
+ 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);
38
+
39
+ static ngx_int_t ngx_http_spdy_syn_frame_handler(
40
+ ngx_http_spdy_connection_t *sc, ngx_http_spdy_out_frame_t *frame);
41
+ static ngx_int_t ngx_http_spdy_data_frame_handler(
42
+ ngx_http_spdy_connection_t *sc, ngx_http_spdy_out_frame_t *frame);
43
+ static ngx_inline void ngx_http_spdy_handle_frame(
44
+ ngx_http_spdy_stream_t *stream, ngx_http_spdy_out_frame_t *frame);
45
+ static ngx_inline void ngx_http_spdy_handle_stream(
46
+ ngx_http_spdy_connection_t *sc, ngx_http_spdy_stream_t *stream);
47
+
48
+ static void ngx_http_spdy_filter_cleanup(void *data);
49
+
50
+ static ngx_int_t ngx_http_spdy_filter_init(ngx_conf_t *cf);
51
+
52
+
53
+ static ngx_http_module_t ngx_http_spdy_filter_module_ctx = {
54
+ NULL, /* preconfiguration */
55
+ ngx_http_spdy_filter_init, /* postconfiguration */
56
+
57
+ NULL, /* create main configuration */
58
+ NULL, /* init main configuration */
59
+
60
+ NULL, /* create server configuration */
61
+ NULL, /* merge server configuration */
62
+
63
+ NULL, /* create location configuration */
64
+ NULL /* merge location configuration */
65
+ };
66
+
67
+
68
+ ngx_module_t ngx_http_spdy_filter_module = {
69
+ NGX_MODULE_V1,
70
+ &ngx_http_spdy_filter_module_ctx, /* module context */
71
+ NULL, /* module directives */
72
+ NGX_HTTP_MODULE, /* module type */
73
+ NULL, /* init master */
74
+ NULL, /* init module */
75
+ NULL, /* init process */
76
+ NULL, /* init thread */
77
+ NULL, /* exit thread */
78
+ NULL, /* exit process */
79
+ NULL, /* exit master */
80
+ NGX_MODULE_V1_PADDING
81
+ };
82
+
83
+
84
+ 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
+
87
+
88
+ static ngx_int_t
89
+ ngx_http_spdy_header_filter(ngx_http_request_t *r)
90
+ {
91
+ int rc;
92
+ size_t len;
93
+ u_char *p, *buf, *last;
94
+ ngx_buf_t *b;
95
+ ngx_str_t host;
96
+ ngx_uint_t i, j, count, port;
97
+ ngx_chain_t *cl;
98
+ ngx_list_part_t *part, *pt;
99
+ ngx_table_elt_t *header, *h;
100
+ ngx_connection_t *c;
101
+ ngx_http_cleanup_t *cln;
102
+ ngx_http_core_loc_conf_t *clcf;
103
+ ngx_http_core_srv_conf_t *cscf;
104
+ ngx_http_spdy_stream_t *stream;
105
+ ngx_http_spdy_out_frame_t *frame;
106
+ ngx_http_spdy_connection_t *sc;
107
+ struct sockaddr_in *sin;
108
+ #if (NGX_HAVE_INET6)
109
+ struct sockaddr_in6 *sin6;
110
+ #endif
111
+ u_char addr[NGX_SOCKADDR_STRLEN];
112
+
113
+ if (!r->spdy_stream) {
114
+ return ngx_http_next_header_filter(r);
115
+ }
116
+
117
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
118
+ "spdy header filter");
119
+
120
+ if (r->header_sent) {
121
+ return NGX_OK;
122
+ }
123
+
124
+ r->header_sent = 1;
125
+
126
+ if (r != r->main) {
127
+ return NGX_OK;
128
+ }
129
+
130
+ c = r->connection;
131
+
132
+ if (r->method == NGX_HTTP_HEAD) {
133
+ r->header_only = 1;
134
+ }
135
+
136
+ switch (r->headers_out.status) {
137
+
138
+ case NGX_HTTP_OK:
139
+ case NGX_HTTP_PARTIAL_CONTENT:
140
+ break;
141
+
142
+ case NGX_HTTP_NOT_MODIFIED:
143
+ r->header_only = 1;
144
+ break;
145
+
146
+ case NGX_HTTP_NO_CONTENT:
147
+ r->header_only = 1;
148
+
149
+ ngx_str_null(&r->headers_out.content_type);
150
+
151
+ r->headers_out.content_length = NULL;
152
+ r->headers_out.content_length_n = -1;
153
+
154
+ /* fall through */
155
+
156
+ default:
157
+ r->headers_out.last_modified_time = -1;
158
+ r->headers_out.last_modified = NULL;
159
+ }
160
+
161
+ len = NGX_SPDY_NV_NUM_SIZE
162
+ + ngx_http_spdy_nv_nsize("version")
163
+ + ngx_http_spdy_nv_vsize("HTTP/1.1")
164
+ + ngx_http_spdy_nv_nsize("status")
165
+ + ngx_http_spdy_nv_vsize("418");
166
+
167
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
168
+
169
+ if (r->headers_out.server == NULL) {
170
+ len += ngx_http_spdy_nv_nsize("server");
171
+ len += clcf->server_tokens ? ngx_http_spdy_nv_vsize(NGINX_VER)
172
+ : ngx_http_spdy_nv_vsize("nginx");
173
+ }
174
+
175
+ if (r->headers_out.date == NULL) {
176
+ len += ngx_http_spdy_nv_nsize("date")
177
+ + ngx_http_spdy_nv_vsize("Wed, 31 Dec 1986 10:00:00 GMT");
178
+ }
179
+
180
+ if (r->headers_out.content_type.len) {
181
+ len += ngx_http_spdy_nv_nsize("content-type")
182
+ + NGX_SPDY_NV_VLEN_SIZE + r->headers_out.content_type.len;
183
+
184
+ if (r->headers_out.content_type_len == r->headers_out.content_type.len
185
+ && r->headers_out.charset.len)
186
+ {
187
+ len += sizeof("; charset=") - 1 + r->headers_out.charset.len;
188
+ }
189
+ }
190
+
191
+ if (r->headers_out.content_length == NULL
192
+ && r->headers_out.content_length_n >= 0)
193
+ {
194
+ len += ngx_http_spdy_nv_nsize("content-length")
195
+ + NGX_SPDY_NV_VLEN_SIZE + NGX_OFF_T_LEN;
196
+ }
197
+
198
+ if (r->headers_out.last_modified == NULL
199
+ && r->headers_out.last_modified_time != -1)
200
+ {
201
+ len += ngx_http_spdy_nv_nsize("last-modified")
202
+ + ngx_http_spdy_nv_vsize("Wed, 31 Dec 1986 10:00:00 GMT");
203
+ }
204
+
205
+ if (r->headers_out.location
206
+ && r->headers_out.location->value.len
207
+ && r->headers_out.location->value.data[0] == '/')
208
+ {
209
+ r->headers_out.location->hash = 0;
210
+
211
+ if (clcf->server_name_in_redirect) {
212
+ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
213
+ host = cscf->server_name;
214
+
215
+ } else if (r->headers_in.server.len) {
216
+ host = r->headers_in.server;
217
+
218
+ } else {
219
+ host.len = NGX_SOCKADDR_STRLEN;
220
+ host.data = addr;
221
+
222
+ if (ngx_connection_local_sockaddr(c, &host, 0) != NGX_OK) {
223
+ return NGX_ERROR;
224
+ }
225
+ }
226
+
227
+ switch (c->local_sockaddr->sa_family) {
228
+
229
+ #if (NGX_HAVE_INET6)
230
+ case AF_INET6:
231
+ sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
232
+ port = ntohs(sin6->sin6_port);
233
+ break;
234
+ #endif
235
+ #if (NGX_HAVE_UNIX_DOMAIN)
236
+ case AF_UNIX:
237
+ port = 0;
238
+ break;
239
+ #endif
240
+ default: /* AF_INET */
241
+ sin = (struct sockaddr_in *) c->local_sockaddr;
242
+ port = ntohs(sin->sin_port);
243
+ break;
244
+ }
245
+
246
+ len += ngx_http_spdy_nv_nsize("location")
247
+ + ngx_http_spdy_nv_vsize("https://")
248
+ + host.len
249
+ + r->headers_out.location->value.len;
250
+
251
+ if (clcf->port_in_redirect) {
252
+
253
+ #if (NGX_HTTP_SSL)
254
+ if (c->ssl)
255
+ port = (port == 443) ? 0 : port;
256
+ else
257
+ #endif
258
+ port = (port == 80) ? 0 : port;
259
+
260
+ } else {
261
+ port = 0;
262
+ }
263
+
264
+ if (port) {
265
+ len += sizeof(":65535") - 1;
266
+ }
267
+
268
+ } else {
269
+ ngx_str_null(&host);
270
+ port = 0;
271
+ }
272
+
273
+ part = &r->headers_out.headers.part;
274
+ header = part->elts;
275
+
276
+ for (i = 0; /* void */; i++) {
277
+
278
+ if (i >= part->nelts) {
279
+ if (part->next == NULL) {
280
+ break;
281
+ }
282
+
283
+ part = part->next;
284
+ header = part->elts;
285
+ i = 0;
286
+ }
287
+
288
+ if (header[i].hash == 0) {
289
+ continue;
290
+ }
291
+
292
+ len += NGX_SPDY_NV_NLEN_SIZE + header[i].key.len
293
+ + NGX_SPDY_NV_VLEN_SIZE + header[i].value.len;
294
+ }
295
+
296
+ buf = ngx_alloc(len, r->pool->log);
297
+ if (buf == NULL) {
298
+ return NGX_ERROR;
299
+ }
300
+
301
+ last = buf + NGX_SPDY_NV_NUM_SIZE;
302
+
303
+ last = ngx_http_spdy_nv_write_name(last, "version");
304
+ last = ngx_http_spdy_nv_write_val(last, "HTTP/1.1");
305
+
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);
309
+
310
+ count = 2;
311
+
312
+ if (r->headers_out.server == NULL) {
313
+ last = ngx_http_spdy_nv_write_name(last, "server");
314
+ last = clcf->server_tokens
315
+ ? ngx_http_spdy_nv_write_val(last, NGINX_VER)
316
+ : ngx_http_spdy_nv_write_val(last, "nginx");
317
+
318
+ count++;
319
+ }
320
+
321
+ if (r->headers_out.date == NULL) {
322
+ last = ngx_http_spdy_nv_write_name(last, "date");
323
+
324
+ last = ngx_http_spdy_nv_write_vlen(last, ngx_cached_http_time.len);
325
+
326
+ last = ngx_cpymem(last, ngx_cached_http_time.data,
327
+ ngx_cached_http_time.len);
328
+
329
+ count++;
330
+ }
331
+
332
+ if (r->headers_out.content_type.len) {
333
+
334
+ last = ngx_http_spdy_nv_write_name(last, "content-type");
335
+
336
+ p = last + NGX_SPDY_NV_VLEN_SIZE;
337
+
338
+ last = ngx_cpymem(p, r->headers_out.content_type.data,
339
+ r->headers_out.content_type.len);
340
+
341
+ if (r->headers_out.content_type_len == r->headers_out.content_type.len
342
+ && r->headers_out.charset.len)
343
+ {
344
+ last = ngx_cpymem(last, "; charset=", sizeof("; charset=") - 1);
345
+
346
+ last = ngx_cpymem(last, r->headers_out.charset.data,
347
+ r->headers_out.charset.len);
348
+
349
+ /* update r->headers_out.content_type for possible logging */
350
+
351
+ r->headers_out.content_type.len = last - p;
352
+ r->headers_out.content_type.data = p;
353
+ }
354
+
355
+ (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE,
356
+ r->headers_out.content_type.len);
357
+
358
+ count++;
359
+ }
360
+
361
+ if (r->headers_out.content_length == NULL
362
+ && r->headers_out.content_length_n >= 0)
363
+ {
364
+ last = ngx_http_spdy_nv_write_name(last, "content-length");
365
+
366
+ p = last + NGX_SPDY_NV_VLEN_SIZE;
367
+
368
+ last = ngx_sprintf(p, "%O", r->headers_out.content_length_n);
369
+
370
+ (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE,
371
+ last - p);
372
+
373
+ count++;
374
+ }
375
+
376
+ if (r->headers_out.last_modified == NULL
377
+ && r->headers_out.last_modified_time != -1)
378
+ {
379
+ last = ngx_http_spdy_nv_write_name(last, "last-modified");
380
+
381
+ p = last + NGX_SPDY_NV_VLEN_SIZE;
382
+
383
+ last = ngx_http_time(p, r->headers_out.last_modified_time);
384
+
385
+ (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE,
386
+ last - p);
387
+
388
+ count++;
389
+ }
390
+
391
+ if (host.data) {
392
+
393
+ last = ngx_http_spdy_nv_write_name(last, "location");
394
+
395
+ p = last + NGX_SPDY_NV_VLEN_SIZE;
396
+
397
+ last = ngx_cpymem(p, "http", sizeof("http") - 1);
398
+
399
+ #if (NGX_HTTP_SSL)
400
+ if (c->ssl) {
401
+ *last++ ='s';
402
+ }
403
+ #endif
404
+
405
+ *last++ = ':'; *last++ = '/'; *last++ = '/';
406
+
407
+ last = ngx_cpymem(last, host.data, host.len);
408
+
409
+ if (port) {
410
+ last = ngx_sprintf(last, ":%ui", port);
411
+ }
412
+
413
+ last = ngx_cpymem(last, r->headers_out.location->value.data,
414
+ r->headers_out.location->value.len);
415
+
416
+ /* update r->headers_out.location->value for possible logging */
417
+
418
+ r->headers_out.location->value.len = last - p;
419
+ r->headers_out.location->value.data = p;
420
+ ngx_str_set(&r->headers_out.location->key, "location");
421
+
422
+ (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE,
423
+ r->headers_out.location->value.len);
424
+
425
+ count++;
426
+ }
427
+
428
+ part = &r->headers_out.headers.part;
429
+ header = part->elts;
430
+
431
+ for (i = 0; /* void */; i++) {
432
+
433
+ if (i >= part->nelts) {
434
+ if (part->next == NULL) {
435
+ break;
436
+ }
437
+
438
+ part = part->next;
439
+ header = part->elts;
440
+ i = 0;
441
+ }
442
+
443
+ if (header[i].hash == 0 || header[i].hash == 2) {
444
+ continue;
445
+ }
446
+
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
+ last = ngx_http_spdy_nv_write_nlen(last, header[i].key.len);
459
+
460
+ ngx_strlow(last, header[i].key.data, header[i].key.len);
461
+ last += header[i].key.len;
462
+
463
+ p = last + NGX_SPDY_NV_VLEN_SIZE;
464
+
465
+ last = ngx_cpymem(p, header[i].value.data, header[i].value.len);
466
+
467
+ pt = part;
468
+ h = header;
469
+
470
+ for (j = i + 1; /* void */; j++) {
471
+
472
+ if (j >= pt->nelts) {
473
+ if (pt->next == NULL) {
474
+ break;
475
+ }
476
+
477
+ pt = pt->next;
478
+ h = pt->elts;
479
+ j = 0;
480
+ }
481
+
482
+ if (h[j].hash == 0 || h[j].hash == 2
483
+ || h[j].key.len != header[i].key.len
484
+ || ngx_strncasecmp(header[i].key.data, h[j].key.data,
485
+ header[i].key.len))
486
+ {
487
+ continue;
488
+ }
489
+
490
+ *last++ = '\0';
491
+
492
+ last = ngx_cpymem(last, h[j].value.data, h[j].value.len);
493
+
494
+ h[j].hash = 2;
495
+ }
496
+
497
+ (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE,
498
+ last - p);
499
+
500
+ count++;
501
+ }
502
+
503
+ (void) ngx_spdy_frame_write_uint16(buf, count);
504
+
505
+ stream = r->spdy_stream;
506
+ sc = stream->connection;
507
+
508
+ len = last - buf;
509
+
510
+ b = ngx_create_temp_buf(r->pool, NGX_SPDY_FRAME_HEADER_SIZE
511
+ + NGX_SPDY_SYN_REPLY_SIZE
512
+ + deflateBound(&sc->zstream_out, len));
513
+ if (b == NULL) {
514
+ ngx_free(buf);
515
+ return NGX_ERROR;
516
+ }
517
+
518
+ b->last += NGX_SPDY_FRAME_HEADER_SIZE + NGX_SPDY_SYN_REPLY_SIZE;
519
+
520
+ sc->zstream_out.next_in = buf;
521
+ sc->zstream_out.avail_in = len;
522
+ sc->zstream_out.next_out = b->last;
523
+ sc->zstream_out.avail_out = b->end - b->last;
524
+
525
+ rc = deflate(&sc->zstream_out, Z_SYNC_FLUSH);
526
+
527
+ ngx_free(buf);
528
+
529
+ if (rc != Z_OK) {
530
+ ngx_log_error(NGX_LOG_ALERT, c->log, 0,
531
+ "spdy deflate() failed: %d", rc);
532
+ return NGX_ERROR;
533
+ }
534
+
535
+ ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0,
536
+ "spdy deflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d",
537
+ sc->zstream_out.next_in, sc->zstream_out.next_out,
538
+ sc->zstream_out.avail_in, sc->zstream_out.avail_out,
539
+ rc);
540
+
541
+ b->last = sc->zstream_out.next_out;
542
+
543
+ p = b->pos;
544
+ p = ngx_spdy_frame_write_head(p, NGX_SPDY_SYN_REPLY);
545
+
546
+ len = b->last - b->pos;
547
+
548
+ r->header_size = len;
549
+
550
+ if (r->header_only) {
551
+ 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);
554
+ } else {
555
+ p = ngx_spdy_frame_write_flags_and_len(p, 0,
556
+ len - NGX_SPDY_FRAME_HEADER_SIZE);
557
+ }
558
+
559
+ (void) ngx_spdy_frame_write_sid(p, stream->id);
560
+
561
+ cl = ngx_alloc_chain_link(r->pool);
562
+ if (cl == NULL) {
563
+ return NGX_ERROR;
564
+ }
565
+
566
+ cl->buf = b;
567
+ cl->next = NULL;
568
+
569
+ frame = ngx_palloc(r->pool, sizeof(ngx_http_spdy_out_frame_t));
570
+ if (frame == NULL) {
571
+ return NGX_ERROR;
572
+ }
573
+
574
+ frame->first = cl;
575
+ frame->last = cl;
576
+ frame->handler = ngx_http_spdy_syn_frame_handler;
577
+ frame->free = NULL;
578
+ frame->stream = stream;
579
+ frame->size = len;
580
+ frame->priority = stream->priority;
581
+ frame->blocked = 1;
582
+ frame->fin = r->header_only;
583
+
584
+ 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);
587
+
588
+ ngx_http_spdy_queue_blocked_frame(sc, frame);
589
+
590
+ r->blocked++;
591
+
592
+ cln = ngx_http_cleanup_add(r, 0);
593
+ if (cln == NULL) {
594
+ return NGX_ERROR;
595
+ }
596
+
597
+ cln->handler = ngx_http_spdy_filter_cleanup;
598
+ cln->data = stream;
599
+
600
+ stream->waiting = 1;
601
+
602
+ return ngx_http_spdy_filter_send(c, stream);
603
+ }
604
+
605
+
606
+ static ngx_int_t
607
+ ngx_http_spdy_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
608
+ {
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
+
615
+ stream = r->spdy_stream;
616
+
617
+ if (stream == NULL) {
618
+ return ngx_http_next_body_filter(r, in);
619
+ }
620
+
621
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
622
+ "spdy body filter \"%V?%V\"", &r->uri, &r->args);
623
+
624
+ if (in == NULL || r->header_only) {
625
+
626
+ if (stream->waiting) {
627
+ return NGX_AGAIN;
628
+ }
629
+
630
+ r->connection->buffered &= ~NGX_SPDY_WRITE_BUFFERED;
631
+
632
+ return NGX_OK;
633
+ }
634
+
635
+ size = 0;
636
+ ln = &out;
637
+ ll = in;
638
+
639
+ 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;
658
+ }
659
+ #endif
660
+ cl = ngx_alloc_chain_link(r->pool);
661
+ if (cl == NULL) {
662
+ return NGX_ERROR;
663
+ }
664
+
665
+ size += ngx_buf_size(b);
666
+ cl->buf = b;
667
+
668
+ *ln = cl;
669
+ ln = &cl->next;
670
+
671
+ if (ll->next == NULL) {
672
+ break;
673
+ }
674
+
675
+ ll = ll->next;
676
+ }
677
+
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;
682
+ }
683
+
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;
688
+ }
689
+
690
+ ngx_http_spdy_queue_frame(stream->connection, frame);
691
+
692
+ stream->waiting++;
693
+
694
+ r->main->blocked++;
695
+
696
+ return ngx_http_spdy_filter_send(r->connection, stream);
697
+ }
698
+
699
+
700
+ static ngx_http_spdy_out_frame_t *
701
+ 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)
703
+ {
704
+ u_char *p;
705
+ ngx_buf_t *buf;
706
+ ngx_uint_t flags;
707
+ ngx_chain_t *cl;
708
+ ngx_http_spdy_out_frame_t *frame;
709
+
710
+
711
+ frame = stream->free_frames;
712
+
713
+ if (frame) {
714
+ stream->free_frames = frame->free;
715
+
716
+ } else {
717
+ frame = ngx_palloc(stream->request->pool,
718
+ sizeof(ngx_http_spdy_out_frame_t));
719
+ if (frame == NULL) {
720
+ return NULL;
721
+ }
722
+ }
723
+
724
+ 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);
727
+
728
+ if (len || fin) {
729
+
730
+ flags = fin ? NGX_SPDY_FLAG_FIN : 0;
731
+
732
+ cl = ngx_chain_get_free_buf(stream->request->pool,
733
+ &stream->free_data_headers);
734
+ if (cl == NULL) {
735
+ return NULL;
736
+ }
737
+
738
+ buf = cl->buf;
739
+
740
+ if (buf->start) {
741
+ p = buf->start;
742
+ buf->pos = p;
743
+
744
+ p += sizeof(uint32_t);
745
+
746
+ (void) ngx_spdy_frame_write_flags_and_len(p, flags, len);
747
+
748
+ } else {
749
+ p = ngx_palloc(stream->request->pool, NGX_SPDY_FRAME_HEADER_SIZE);
750
+ if (p == NULL) {
751
+ return NULL;
752
+ }
753
+
754
+ buf->pos = p;
755
+ buf->start = p;
756
+
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;
762
+
763
+ buf->tag = (ngx_buf_tag_t) &ngx_http_spdy_filter_module;
764
+ buf->memory = 1;
765
+ }
766
+
767
+ cl->next = first;
768
+ first = cl;
769
+ }
770
+
771
+ frame->first = first;
772
+ frame->last = last;
773
+ frame->handler = ngx_http_spdy_data_frame_handler;
774
+ frame->free = NULL;
775
+ frame->stream = stream;
776
+ frame->size = NGX_SPDY_FRAME_HEADER_SIZE + len;
777
+ frame->priority = stream->priority;
778
+ frame->blocked = 0;
779
+ frame->fin = fin;
780
+
781
+ return frame;
782
+ }
783
+
784
+
785
+ static ngx_inline ngx_int_t
786
+ ngx_http_spdy_filter_send(ngx_connection_t *fc, ngx_http_spdy_stream_t *stream)
787
+ {
788
+ if (ngx_http_spdy_send_output_queue(stream->connection) == NGX_ERROR) {
789
+ fc->error = 1;
790
+ return NGX_ERROR;
791
+ }
792
+
793
+ if (stream->waiting) {
794
+ fc->buffered |= NGX_SPDY_WRITE_BUFFERED;
795
+ fc->write->delayed = 1;
796
+ return NGX_AGAIN;
797
+ }
798
+
799
+ fc->buffered &= ~NGX_SPDY_WRITE_BUFFERED;
800
+
801
+ return NGX_OK;
802
+ }
803
+
804
+
805
+ static ngx_int_t
806
+ ngx_http_spdy_syn_frame_handler(ngx_http_spdy_connection_t *sc,
807
+ ngx_http_spdy_out_frame_t *frame)
808
+ {
809
+ ngx_buf_t *buf;
810
+ ngx_http_spdy_stream_t *stream;
811
+
812
+ buf = frame->first->buf;
813
+
814
+ if (buf->pos != buf->last) {
815
+ return NGX_AGAIN;
816
+ }
817
+
818
+ stream = frame->stream;
819
+
820
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
821
+ "spdy:%ui SYN_REPLY frame %p was sent", stream->id, frame);
822
+
823
+ ngx_free_chain(stream->request->pool, frame->first);
824
+
825
+ ngx_http_spdy_handle_frame(stream, frame);
826
+
827
+ ngx_http_spdy_handle_stream(sc, stream);
828
+
829
+ return NGX_OK;
830
+ }
831
+
832
+
833
+ static ngx_int_t
834
+ ngx_http_spdy_data_frame_handler(ngx_http_spdy_connection_t *sc,
835
+ ngx_http_spdy_out_frame_t *frame)
836
+ {
837
+ ngx_chain_t *cl, *ln;
838
+ ngx_http_spdy_stream_t *stream;
839
+
840
+ stream = frame->stream;
841
+
842
+ cl = frame->first;
843
+
844
+ if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_module) {
845
+
846
+ if (cl->buf->pos != cl->buf->last) {
847
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
848
+ "spdy:%ui DATA frame %p was sent partially",
849
+ stream->id, frame);
850
+
851
+ return NGX_AGAIN;
852
+ }
853
+
854
+ ln = cl->next;
855
+
856
+ cl->next = stream->free_data_headers;
857
+ stream->free_data_headers = cl;
858
+
859
+ if (cl == frame->last) {
860
+ goto done;
861
+ }
862
+
863
+ cl = ln;
864
+ }
865
+
866
+ for ( ;; ) {
867
+ if (ngx_buf_size(cl->buf) != 0) {
868
+
869
+ if (cl != frame->first) {
870
+ frame->first = cl;
871
+ ngx_http_spdy_handle_stream(sc, stream);
872
+ }
873
+
874
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
875
+ "spdy:%ui DATA frame %p was sent partially",
876
+ stream->id, frame);
877
+
878
+ return NGX_AGAIN;
879
+ }
880
+
881
+ ln = cl->next;
882
+
883
+ ngx_free_chain(stream->request->pool, cl);
884
+
885
+ if (cl == frame->last) {
886
+ goto done;
887
+ }
888
+
889
+ cl = ln;
890
+ }
891
+
892
+ done:
893
+
894
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
895
+ "spdy:%ui DATA frame %p was sent", stream->id, frame);
896
+
897
+ stream->request->header_size += NGX_SPDY_FRAME_HEADER_SIZE;
898
+
899
+ ngx_http_spdy_handle_frame(stream, frame);
900
+
901
+ ngx_http_spdy_handle_stream(sc, stream);
902
+
903
+ return NGX_OK;
904
+ }
905
+
906
+
907
+ static ngx_inline void
908
+ ngx_http_spdy_handle_frame(ngx_http_spdy_stream_t *stream,
909
+ ngx_http_spdy_out_frame_t *frame)
910
+ {
911
+ ngx_http_request_t *r;
912
+
913
+ r = stream->request;
914
+
915
+ r->connection->sent += frame->size;
916
+ r->blocked--;
917
+
918
+ if (frame->fin) {
919
+ stream->out_closed = 1;
920
+ }
921
+
922
+ frame->free = stream->free_frames;
923
+ stream->free_frames = frame;
924
+
925
+ stream->waiting--;
926
+ }
927
+
928
+
929
+ static ngx_inline void
930
+ ngx_http_spdy_handle_stream(ngx_http_spdy_connection_t *sc,
931
+ ngx_http_spdy_stream_t *stream)
932
+ {
933
+ ngx_connection_t *fc;
934
+
935
+ fc = stream->request->connection;
936
+
937
+ fc->write->delayed = 0;
938
+
939
+ if (stream->handled) {
940
+ return;
941
+ }
942
+
943
+ if (sc->blocked == 2) {
944
+ stream->handled = 1;
945
+
946
+ stream->next = sc->last_stream;
947
+ sc->last_stream = stream;
948
+ }
949
+ }
950
+
951
+
952
+ static void
953
+ ngx_http_spdy_filter_cleanup(void *data)
954
+ {
955
+ ngx_http_spdy_stream_t *stream = data;
956
+
957
+ ngx_http_request_t *r;
958
+ ngx_http_spdy_out_frame_t *frame, **fn;
959
+
960
+ if (stream->waiting == 0) {
961
+ return;
962
+ }
963
+
964
+ r = stream->request;
965
+
966
+ fn = &stream->connection->last_out;
967
+
968
+ for ( ;; ) {
969
+ frame = *fn;
970
+
971
+ if (frame == NULL) {
972
+ break;
973
+ }
974
+
975
+ if (frame->stream == stream && !frame->blocked) {
976
+
977
+ stream->waiting--;
978
+ r->blocked--;
979
+
980
+ *fn = frame->next;
981
+ continue;
982
+ }
983
+
984
+ fn = &frame->next;
985
+ }
986
+ }
987
+
988
+
989
+ static ngx_int_t
990
+ ngx_http_spdy_filter_init(ngx_conf_t *cf)
991
+ {
992
+ ngx_http_next_header_filter = ngx_http_top_header_filter;
993
+ ngx_http_top_header_filter = ngx_http_spdy_header_filter;
994
+
995
+ ngx_http_next_body_filter = ngx_http_top_body_filter;
996
+ ngx_http_top_body_filter = ngx_http_spdy_body_filter;
997
+
998
+ return NGX_OK;
999
+ }