comparison src/http/ngx_http_spdy.c @ 5549:39d7eef2e332

SPDY: protocol implementation switched to spdy/3.1.
author Valentin Bartenev <vbart@nginx.com>
date Fri, 31 Jan 2014 19:17:26 +0400
parents 827e53c136b0
children 60c4179f76ad
comparison
equal deleted inserted replaced
5548:4d47722d76b2 5549:39d7eef2e332
40 40
41 #endif 41 #endif
42 42
43 #define ngx_spdy_frame_parse_sid(p) \ 43 #define ngx_spdy_frame_parse_sid(p) \
44 (ngx_spdy_frame_parse_uint32(p) & 0x7fffffff) 44 (ngx_spdy_frame_parse_uint32(p) & 0x7fffffff)
45 #define ngx_spdy_frame_parse_delta(p) \
46 (ngx_spdy_frame_parse_uint32(p) & 0x7fffffff)
45 47
46 48
47 #define ngx_spdy_ctl_frame_check(h) \ 49 #define ngx_spdy_ctl_frame_check(h) \
48 (((h) & 0xffffff00) == ngx_spdy_ctl_frame_head(0)) 50 (((h) & 0xffffff00) == ngx_spdy_ctl_frame_head(0))
49 #define ngx_spdy_data_frame_check(h) \ 51 #define ngx_spdy_data_frame_check(h) \
50 (!((h) & (uint32_t) NGX_SPDY_CTL_BIT << 31)) 52 (!((h) & (uint32_t) NGX_SPDY_CTL_BIT << 31))
51 53
52 #define ngx_spdy_ctl_frame_type(h) ((h) & 0x000000ff) 54 #define ngx_spdy_ctl_frame_type(h) ((h) & 0x000000ff)
53 #define ngx_spdy_frame_flags(p) ((p) >> 24) 55 #define ngx_spdy_frame_flags(p) ((p) >> 24)
54 #define ngx_spdy_frame_length(p) ((p) & 0x00ffffff) 56 #define ngx_spdy_frame_length(p) ((p) & 0x00ffffff)
57 #define ngx_spdy_frame_id(p) ((p) & 0x00ffffff)
55 58
56 59
57 #define NGX_SPDY_SKIP_HEADERS_BUFFER_SIZE 4096 60 #define NGX_SPDY_SKIP_HEADERS_BUFFER_SIZE 4096
58 #define NGX_SPDY_CTL_FRAME_BUFFER_SIZE 16 61 #define NGX_SPDY_CTL_FRAME_BUFFER_SIZE 16
59 62
62 #define NGX_SPDY_REFUSED_STREAM 3 65 #define NGX_SPDY_REFUSED_STREAM 3
63 #define NGX_SPDY_UNSUPPORTED_VERSION 4 66 #define NGX_SPDY_UNSUPPORTED_VERSION 4
64 #define NGX_SPDY_CANCEL 5 67 #define NGX_SPDY_CANCEL 5
65 #define NGX_SPDY_INTERNAL_ERROR 6 68 #define NGX_SPDY_INTERNAL_ERROR 6
66 #define NGX_SPDY_FLOW_CONTROL_ERROR 7 69 #define NGX_SPDY_FLOW_CONTROL_ERROR 7
70 #define NGX_SPDY_STREAM_IN_USE 8
71 #define NGX_SPDY_STREAM_ALREADY_CLOSED 9
72 /* deprecated 10 */
73 #define NGX_SPDY_FRAME_TOO_LARGE 11
67 74
68 #define NGX_SPDY_SETTINGS_MAX_STREAMS 4 75 #define NGX_SPDY_SETTINGS_MAX_STREAMS 4
76 #define NGX_SPDY_SETTINGS_INIT_WINDOW 7
69 77
70 #define NGX_SPDY_SETTINGS_FLAG_PERSIST 0x01 78 #define NGX_SPDY_SETTINGS_FLAG_PERSIST 0x01
79 #define NGX_SPDY_SETTINGS_FLAG_PERSISTED 0x02
80
81 #define NGX_SPDY_MAX_WINDOW NGX_MAX_INT32_VALUE
82 #define NGX_SPDY_CONNECTION_WINDOW 65536
83 #define NGX_SPDY_INIT_STREAM_WINDOW 65536
84 #define NGX_SPDY_STREAM_WINDOW NGX_SPDY_MAX_WINDOW
71 85
72 typedef struct { 86 typedef struct {
73 ngx_uint_t hash; 87 ngx_uint_t hash;
74 u_char len; 88 u_char len;
75 u_char header[7]; 89 u_char header[7];
89 u_char *pos, u_char *end); 103 u_char *pos, u_char *end);
90 static u_char *ngx_http_spdy_state_headers_error(ngx_http_spdy_connection_t *sc, 104 static u_char *ngx_http_spdy_state_headers_error(ngx_http_spdy_connection_t *sc,
91 u_char *pos, u_char *end); 105 u_char *pos, u_char *end);
92 static u_char *ngx_http_spdy_state_headers_skip(ngx_http_spdy_connection_t *sc, 106 static u_char *ngx_http_spdy_state_headers_skip(ngx_http_spdy_connection_t *sc,
93 u_char *pos, u_char *end); 107 u_char *pos, u_char *end);
108 static u_char *ngx_http_spdy_state_window_update(ngx_http_spdy_connection_t *sc,
109 u_char *pos, u_char *end);
94 static u_char *ngx_http_spdy_state_data(ngx_http_spdy_connection_t *sc, 110 static u_char *ngx_http_spdy_state_data(ngx_http_spdy_connection_t *sc,
111 u_char *pos, u_char *end);
112 static u_char *ngx_http_spdy_state_read_data(ngx_http_spdy_connection_t *sc,
95 u_char *pos, u_char *end); 113 u_char *pos, u_char *end);
96 static u_char *ngx_http_spdy_state_rst_stream(ngx_http_spdy_connection_t *sc, 114 static u_char *ngx_http_spdy_state_rst_stream(ngx_http_spdy_connection_t *sc,
97 u_char *pos, u_char *end); 115 u_char *pos, u_char *end);
98 static u_char *ngx_http_spdy_state_ping(ngx_http_spdy_connection_t *sc, 116 static u_char *ngx_http_spdy_state_ping(ngx_http_spdy_connection_t *sc,
99 u_char *pos, u_char *end); 117 u_char *pos, u_char *end);
100 static u_char *ngx_http_spdy_state_skip(ngx_http_spdy_connection_t *sc, 118 static u_char *ngx_http_spdy_state_skip(ngx_http_spdy_connection_t *sc,
101 u_char *pos, u_char *end); 119 u_char *pos, u_char *end);
102 #if 0
103 static u_char *ngx_http_spdy_state_settings(ngx_http_spdy_connection_t *sc, 120 static u_char *ngx_http_spdy_state_settings(ngx_http_spdy_connection_t *sc,
104 u_char *pos, u_char *end);
105 #endif
106 static u_char *ngx_http_spdy_state_noop(ngx_http_spdy_connection_t *sc,
107 u_char *pos, u_char *end); 121 u_char *pos, u_char *end);
108 static u_char *ngx_http_spdy_state_complete(ngx_http_spdy_connection_t *sc, 122 static u_char *ngx_http_spdy_state_complete(ngx_http_spdy_connection_t *sc,
109 u_char *pos, u_char *end); 123 u_char *pos, u_char *end);
110 static u_char *ngx_http_spdy_state_save(ngx_http_spdy_connection_t *sc, 124 static u_char *ngx_http_spdy_state_save(ngx_http_spdy_connection_t *sc,
111 u_char *pos, u_char *end, ngx_http_spdy_handler_pt handler); 125 u_char *pos, u_char *end, ngx_http_spdy_handler_pt handler);
112 static u_char *ngx_http_spdy_state_protocol_error( 126 static u_char *ngx_http_spdy_state_protocol_error(
113 ngx_http_spdy_connection_t *sc); 127 ngx_http_spdy_connection_t *sc);
114 static u_char *ngx_http_spdy_state_internal_error( 128 static u_char *ngx_http_spdy_state_internal_error(
115 ngx_http_spdy_connection_t *sc); 129 ngx_http_spdy_connection_t *sc);
116 130
131 static ngx_int_t ngx_http_spdy_send_window_update(
132 ngx_http_spdy_connection_t *sc, ngx_uint_t sid, ngx_uint_t delta);
117 static ngx_int_t ngx_http_spdy_send_rst_stream(ngx_http_spdy_connection_t *sc, 133 static ngx_int_t ngx_http_spdy_send_rst_stream(ngx_http_spdy_connection_t *sc,
118 ngx_uint_t sid, ngx_uint_t status, ngx_uint_t priority); 134 ngx_uint_t sid, ngx_uint_t status, ngx_uint_t priority);
119 static ngx_int_t ngx_http_spdy_send_settings(ngx_http_spdy_connection_t *sc); 135 static ngx_int_t ngx_http_spdy_send_settings(ngx_http_spdy_connection_t *sc);
120 static ngx_int_t ngx_http_spdy_settings_frame_handler( 136 static ngx_int_t ngx_http_spdy_settings_frame_handler(
121 ngx_http_spdy_connection_t *sc, ngx_http_spdy_out_frame_t *frame); 137 ngx_http_spdy_connection_t *sc, ngx_http_spdy_out_frame_t *frame);
136 static ngx_int_t ngx_http_spdy_alloc_large_header_buffer(ngx_http_request_t *r); 152 static ngx_int_t ngx_http_spdy_alloc_large_header_buffer(ngx_http_request_t *r);
137 153
138 static ngx_int_t ngx_http_spdy_handle_request_header(ngx_http_request_t *r); 154 static ngx_int_t ngx_http_spdy_handle_request_header(ngx_http_request_t *r);
139 static ngx_int_t ngx_http_spdy_parse_method(ngx_http_request_t *r); 155 static ngx_int_t ngx_http_spdy_parse_method(ngx_http_request_t *r);
140 static ngx_int_t ngx_http_spdy_parse_scheme(ngx_http_request_t *r); 156 static ngx_int_t ngx_http_spdy_parse_scheme(ngx_http_request_t *r);
141 static ngx_int_t ngx_http_spdy_parse_url(ngx_http_request_t *r); 157 static ngx_int_t ngx_http_spdy_parse_host(ngx_http_request_t *r);
158 static ngx_int_t ngx_http_spdy_parse_path(ngx_http_request_t *r);
142 static ngx_int_t ngx_http_spdy_parse_version(ngx_http_request_t *r); 159 static ngx_int_t ngx_http_spdy_parse_version(ngx_http_request_t *r);
143 160
144 static ngx_int_t ngx_http_spdy_construct_request_line(ngx_http_request_t *r); 161 static ngx_int_t ngx_http_spdy_construct_request_line(ngx_http_request_t *r);
145 static void ngx_http_spdy_run_request(ngx_http_request_t *r); 162 static void ngx_http_spdy_run_request(ngx_http_request_t *r);
146 static ngx_int_t ngx_http_spdy_init_request_body(ngx_http_request_t *r); 163 static ngx_int_t ngx_http_spdy_init_request_body(ngx_http_request_t *r);
164
165 static ngx_int_t ngx_http_spdy_terminate_stream(ngx_http_spdy_connection_t *sc,
166 ngx_http_spdy_stream_t *stream, ngx_uint_t status);
147 167
148 static void ngx_http_spdy_close_stream_handler(ngx_event_t *ev); 168 static void ngx_http_spdy_close_stream_handler(ngx_event_t *ev);
149 169
150 static void ngx_http_spdy_handle_connection_handler(ngx_event_t *rev); 170 static void ngx_http_spdy_handle_connection_handler(ngx_event_t *rev);
151 static void ngx_http_spdy_keepalive_handler(ngx_event_t *rev); 171 static void ngx_http_spdy_keepalive_handler(ngx_event_t *rev);
152 static void ngx_http_spdy_finalize_connection(ngx_http_spdy_connection_t *sc, 172 static void ngx_http_spdy_finalize_connection(ngx_http_spdy_connection_t *sc,
153 ngx_int_t rc); 173 ngx_int_t rc);
154 174
175 static ngx_int_t ngx_http_spdy_adjust_windows(ngx_http_spdy_connection_t *sc,
176 ssize_t delta);
177
155 static void ngx_http_spdy_pool_cleanup(void *data); 178 static void ngx_http_spdy_pool_cleanup(void *data);
156 179
157 static void *ngx_http_spdy_zalloc(void *opaque, u_int items, u_int size); 180 static void *ngx_http_spdy_zalloc(void *opaque, u_int items, u_int size);
158 static void ngx_http_spdy_zfree(void *opaque, void *address); 181 static void ngx_http_spdy_zfree(void *opaque, void *address);
159 182
160 183
161 static const u_char ngx_http_spdy_dict[] = 184 static const u_char ngx_http_spdy_dict[] = {
162 "options" "get" "head" "post" "put" "delete" "trace" 185 0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, /* - - - - o p t i */
163 "accept" "accept-charset" "accept-encoding" "accept-language" 186 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, /* o n s - - - - h */
164 "authorization" "expect" "from" "host" 187 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, /* e a d - - - - p */
165 "if-modified-since" "if-match" "if-none-match" "if-range" 188 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, /* o s t - - - - p */
166 "if-unmodifiedsince" "max-forwards" "proxy-authorization" 189 0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, /* u t - - - - d e */
167 "range" "referer" "te" "user-agent" 190 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, /* l e t e - - - - */
168 "100" "101" "200" "201" "202" "203" "204" "205" "206" 191 0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, /* t r a c e - - - */
169 "300" "301" "302" "303" "304" "305" "306" "307" 192 0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, /* - a c c e p t - */
170 "400" "401" "402" "403" "404" "405" "406" "407" "408" "409" "410" 193 0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, /* - - - a c c e p */
171 "411" "412" "413" "414" "415" "416" "417" 194 0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, /* t - c h a r s e */
172 "500" "501" "502" "503" "504" "505" 195 0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, /* t - - - - a c c */
173 "accept-ranges" "age" "etag" "location" "proxy-authenticate" "public" 196 0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, /* e p t - e n c o */
174 "retry-after" "server" "vary" "warning" "www-authenticate" "allow" 197 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, /* d i n g - - - - */
175 "content-base" "content-encoding" "cache-control" "connection" "date" 198 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, /* a c c e p t - l */
176 "trailer" "transfer-encoding" "upgrade" "via" "warning" 199 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, /* a n g u a g e - */
177 "content-language" "content-length" "content-location" 200 0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, /* - - - a c c e p */
178 "content-md5" "content-range" "content-type" "etag" "expires" 201 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, /* t - r a n g e s */
179 "last-modified" "set-cookie" 202 0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, /* - - - - a g e - */
180 "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday" "Sunday" 203 0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, /* - - - a l l o w */
181 "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec" 204 0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, /* - - - - a u t h */
182 "chunked" "text/html" "image/png" "image/jpg" "image/gif" 205 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, /* o r i z a t i o */
183 "application/xml" "application/xhtml" "text/plain" "public" "max-age" 206 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, /* n - - - - c a c */
184 "charset=iso-8859-1" "utf-8" "gzip" "deflate" "HTTP/1.1" "status" 207 0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, /* h e - c o n t r */
185 "version" "url"; 208 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, /* o l - - - - c o */
209 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, /* n n e c t i o n */
210 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, /* - - - - c o n t */
211 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, /* e n t - b a s e */
212 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, /* - - - - c o n t */
213 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, /* e n t - e n c o */
214 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, /* d i n g - - - - */
215 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, /* c o n t e n t - */
216 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, /* l a n g u a g e */
217 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, /* - - - - c o n t */
218 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, /* e n t - l e n g */
219 0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, /* t h - - - - c o */
220 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, /* n t e n t - l o */
221 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, /* c a t i o n - - */
222 0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, /* - - c o n t e n */
223 0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, /* t - m d 5 - - - */
224 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, /* - c o n t e n t */
225 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, /* - r a n g e - - */
226 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, /* - - c o n t e n */
227 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, /* t - t y p e - - */
228 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, /* - - d a t e - - */
229 0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, /* - - e t a g - - */
230 0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, /* - - e x p e c t */
231 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, /* - - - - e x p i */
232 0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, /* r e s - - - - f */
233 0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, /* r o m - - - - h */
234 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, /* o s t - - - - i */
235 0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, /* f - m a t c h - */
236 0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, /* - - - i f - m o */
237 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, /* d i f i e d - s */
238 0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, /* i n c e - - - - */
239 0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, /* i f - n o n e - */
240 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, /* m a t c h - - - */
241 0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, /* - i f - r a n g */
242 0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, /* e - - - - i f - */
243 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, /* u n m o d i f i */
244 0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, /* e d - s i n c e */
245 0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, /* - - - - l a s t */
246 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, /* - m o d i f i e */
247 0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, /* d - - - - l o c */
248 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, /* a t i o n - - - */
249 0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, /* - m a x - f o r */
250 0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, /* w a r d s - - - */
251 0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, /* - p r a g m a - */
252 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, /* - - - p r o x y */
253 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, /* - a u t h e n t */
254 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, /* i c a t e - - - */
255 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, /* - p r o x y - a */
256 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, /* u t h o r i z a */
257 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, /* t i o n - - - - */
258 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, /* r a n g e - - - */
259 0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, /* - r e f e r e r */
260 0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, /* - - - - r e t r */
261 0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, /* y - a f t e r - */
262 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, /* - - - s e r v e */
263 0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, /* r - - - - t e - */
264 0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, /* - - - t r a i l */
265 0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, /* e r - - - - t r */
266 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, /* a n s f e r - e */
267 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, /* n c o d i n g - */
268 0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, /* - - - u p g r a */
269 0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, /* d e - - - - u s */
270 0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, /* e r - a g e n t */
271 0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, /* - - - - v a r y */
272 0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, /* - - - - v i a - */
273 0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, /* - - - w a r n i */
274 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, /* n g - - - - w w */
275 0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, /* w - a u t h e n */
276 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, /* t i c a t e - - */
277 0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, /* - - m e t h o d */
278 0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, /* - - - - g e t - */
279 0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, /* - - - s t a t u */
280 0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, /* s - - - - 2 0 0 */
281 0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, /* - O K - - - - v */
282 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, /* e r s i o n - - */
283 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, /* - - H T T P - 1 */
284 0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, /* - 1 - - - - u r */
285 0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, /* l - - - - p u b */
286 0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, /* l i c - - - - s */
287 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, /* e t - c o o k i */
288 0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, /* e - - - - k e e */
289 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, /* p - a l i v e - */
290 0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, /* - - - o r i g i */
291 0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, /* n 1 0 0 1 0 1 2 */
292 0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, /* 0 1 2 0 2 2 0 5 */
293 0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, /* 2 0 6 3 0 0 3 0 */
294 0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, /* 2 3 0 3 3 0 4 3 */
295 0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, /* 0 5 3 0 6 3 0 7 */
296 0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, /* 4 0 2 4 0 5 4 0 */
297 0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, /* 6 4 0 7 4 0 8 4 */
298 0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, /* 0 9 4 1 0 4 1 1 */
299 0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, /* 4 1 2 4 1 3 4 1 */
300 0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, /* 4 4 1 5 4 1 6 4 */
301 0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, /* 1 7 5 0 2 5 0 4 */
302 0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, /* 5 0 5 2 0 3 - N */
303 0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, /* o n - A u t h o */
304 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, /* r i t a t i v e */
305 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, /* - I n f o r m a */
306 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, /* t i o n 2 0 4 - */
307 0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, /* N o - C o n t e */
308 0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, /* n t 3 0 1 - M o */
309 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, /* v e d - P e r m */
310 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, /* a n e n t l y 4 */
311 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, /* 0 0 - B a d - R */
312 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, /* e q u e s t 4 0 */
313 0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, /* 1 - U n a u t h */
314 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, /* o r i z e d 4 0 */
315 0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, /* 3 - F o r b i d */
316 0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, /* d e n 4 0 4 - N */
317 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, /* o t - F o u n d */
318 0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, /* 5 0 0 - I n t e */
319 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, /* r n a l - S e r */
320 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, /* v e r - E r r o */
321 0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, /* r 5 0 1 - N o t */
322 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, /* - I m p l e m e */
323 0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, /* n t e d 5 0 3 - */
324 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, /* S e r v i c e - */
325 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, /* U n a v a i l a */
326 0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, /* b l e J a n - F */
327 0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, /* e b - M a r - A */
328 0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, /* p r - M a y - J */
329 0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, /* u n - J u l - A */
330 0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, /* u g - S e p t - */
331 0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, /* O c t - N o v - */
332 0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, /* D e c - 0 0 - 0 */
333 0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, /* 0 - 0 0 - M o n */
334 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, /* - - T u e - - W */
335 0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, /* e d - - T h u - */
336 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, /* - F r i - - S a */
337 0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, /* t - - S u n - - */
338 0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, /* G M T c h u n k */
339 0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, /* e d - t e x t - */
340 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, /* h t m l - i m a */
341 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, /* g e - p n g - i */
342 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, /* m a g e - j p g */
343 0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, /* - i m a g e - g */
344 0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, /* i f - a p p l i */
345 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, /* c a t i o n - x */
346 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, /* m l - a p p l i */
347 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, /* c a t i o n - x */
348 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, /* h t m l - x m l */
349 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, /* - t e x t - p l */
350 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, /* a i n - t e x t */
351 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, /* - j a v a s c r */
352 0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, /* i p t - p u b l */
353 0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, /* i c p r i v a t */
354 0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, /* e m a x - a g e */
355 0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, /* - g z i p - d e */
356 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, /* f l a t e - s d */
357 0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, /* c h c h a r s e */
358 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, /* t - u t f - 8 c */
359 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, /* h a r s e t - i */
360 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, /* s o - 8 8 5 9 - */
361 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, /* 1 - u t f - - - */
362 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e /* - e n q - 0 - */
363 };
186 364
187 365
188 static ngx_http_spdy_request_header_t ngx_http_spdy_request_headers[] = { 366 static ngx_http_spdy_request_header_t ngx_http_spdy_request_headers[] = {
189 { 0, 6, "method", ngx_http_spdy_parse_method }, 367 { 0, 6, "method", ngx_http_spdy_parse_method },
190 { 0, 6, "scheme", ngx_http_spdy_parse_scheme }, 368 { 0, 6, "scheme", ngx_http_spdy_parse_scheme },
191 { 0, 3, "url", ngx_http_spdy_parse_url }, 369 { 0, 4, "host", ngx_http_spdy_parse_host },
370 { 0, 4, "path", ngx_http_spdy_parse_path },
192 { 0, 7, "version", ngx_http_spdy_parse_version }, 371 { 0, 7, "version", ngx_http_spdy_parse_version },
193 }; 372 };
194 373
195 #define NGX_SPDY_REQUEST_HEADERS \ 374 #define NGX_SPDY_REQUEST_HEADERS \
196 (sizeof(ngx_http_spdy_request_headers) \ 375 (sizeof(ngx_http_spdy_request_headers) \
233 } 412 }
234 413
235 sc->connection = c; 414 sc->connection = c;
236 sc->http_connection = hc; 415 sc->http_connection = hc;
237 416
417 sc->send_window = NGX_SPDY_CONNECTION_WINDOW;
418 sc->recv_window = NGX_SPDY_CONNECTION_WINDOW;
419
420 sc->init_window = NGX_SPDY_INIT_STREAM_WINDOW;
421
238 sc->handler = ngx_http_spdy_state_head; 422 sc->handler = ngx_http_spdy_state_head;
239 423
240 sc->zstream_in.zalloc = ngx_http_spdy_zalloc; 424 sc->zstream_in.zalloc = ngx_http_spdy_zalloc;
241 sc->zstream_in.zfree = ngx_http_spdy_zfree; 425 sc->zstream_in.zfree = ngx_http_spdy_zfree;
242 sc->zstream_in.opaque = sc; 426 sc->zstream_in.opaque = sc;
300 if (ngx_http_spdy_send_settings(sc) == NGX_ERROR) { 484 if (ngx_http_spdy_send_settings(sc) == NGX_ERROR) {
301 ngx_http_close_connection(c); 485 ngx_http_close_connection(c);
302 return; 486 return;
303 } 487 }
304 488
489 if (ngx_http_spdy_send_window_update(sc, 0, NGX_SPDY_MAX_WINDOW
490 - sc->recv_window)
491 == NGX_ERROR)
492 {
493 ngx_http_close_connection(c);
494 return;
495 }
496
497 sc->recv_window = NGX_SPDY_MAX_WINDOW;
498
499 ngx_queue_init(&sc->waiting);
305 ngx_queue_init(&sc->posted); 500 ngx_queue_init(&sc->posted);
306 501
307 c->data = sc; 502 c->data = sc;
308 503
309 rev->handler = ngx_http_spdy_read_handler; 504 rev->handler = ngx_http_spdy_read_handler;
651 846
652 case NGX_SPDY_RST_STREAM: 847 case NGX_SPDY_RST_STREAM:
653 return ngx_http_spdy_state_rst_stream(sc, pos, end); 848 return ngx_http_spdy_state_rst_stream(sc, pos, end);
654 849
655 case NGX_SPDY_SETTINGS: 850 case NGX_SPDY_SETTINGS:
656 return ngx_http_spdy_state_skip(sc, pos, end); 851 return ngx_http_spdy_state_settings(sc, pos, end);
657
658 case NGX_SPDY_NOOP:
659 return ngx_http_spdy_state_noop(sc, pos, end);
660 852
661 case NGX_SPDY_PING: 853 case NGX_SPDY_PING:
662 return ngx_http_spdy_state_ping(sc, pos, end); 854 return ngx_http_spdy_state_ping(sc, pos, end);
663 855
664 case NGX_SPDY_GOAWAY: 856 case NGX_SPDY_GOAWAY:
665 return ngx_http_spdy_state_skip(sc, pos, end); /* TODO */ 857 return ngx_http_spdy_state_skip(sc, pos, end); /* TODO */
666 858
667 case NGX_SPDY_HEADERS: 859 case NGX_SPDY_HEADERS:
668 return ngx_http_spdy_state_protocol_error(sc); 860 return ngx_http_spdy_state_protocol_error(sc);
861
862 case NGX_SPDY_WINDOW_UPDATE:
863 return ngx_http_spdy_state_window_update(sc, pos, end);
669 864
670 default: /* TODO logging */ 865 default: /* TODO logging */
671 return ngx_http_spdy_state_skip(sc, pos, end); 866 return ngx_http_spdy_state_skip(sc, pos, end);
672 } 867 }
673 } 868 }
833 if (buf->last - buf->pos < NGX_SPDY_NV_NUM_SIZE) { 1028 if (buf->last - buf->pos < NGX_SPDY_NV_NUM_SIZE) {
834 return ngx_http_spdy_state_save(sc, pos, end, 1029 return ngx_http_spdy_state_save(sc, pos, end,
835 ngx_http_spdy_state_headers); 1030 ngx_http_spdy_state_headers);
836 } 1031 }
837 1032
838 sc->entries = ngx_spdy_frame_parse_uint16(buf->pos); 1033 sc->entries = ngx_spdy_frame_parse_uint32(buf->pos);
839 1034
840 buf->pos += NGX_SPDY_NV_NUM_SIZE; 1035 buf->pos += NGX_SPDY_NV_NUM_SIZE;
841 1036
842 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 1037 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
843 "spdy HEADERS block consists of %ui entries", 1038 "spdy HEADERS block consists of %ui entries",
1051 return ngx_http_spdy_state_complete(sc, pos, end); 1246 return ngx_http_spdy_state_complete(sc, pos, end);
1052 } 1247 }
1053 1248
1054 1249
1055 static u_char * 1250 static u_char *
1251 ngx_http_spdy_state_window_update(ngx_http_spdy_connection_t *sc, u_char *pos,
1252 u_char *end)
1253 {
1254 size_t delta;
1255 ngx_uint_t sid;
1256 ngx_event_t *wev;
1257 ngx_queue_t *q;
1258 ngx_http_spdy_stream_t *stream;
1259
1260 if (end - pos < NGX_SPDY_WINDOW_UPDATE_SIZE) {
1261 return ngx_http_spdy_state_save(sc, pos, end,
1262 ngx_http_spdy_state_window_update);
1263 }
1264
1265 if (sc->length != NGX_SPDY_WINDOW_UPDATE_SIZE) {
1266 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1267 "client sent WINDOW_UPDATE frame "
1268 "with incorrect length %uz", sc->length);
1269
1270 return ngx_http_spdy_state_protocol_error(sc);
1271 }
1272
1273 sid = ngx_spdy_frame_parse_sid(pos);
1274
1275 pos += NGX_SPDY_SID_SIZE;
1276
1277 delta = ngx_spdy_frame_parse_delta(pos);
1278
1279 pos += NGX_SPDY_DELTA_SIZE;
1280
1281 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1282 "spdy WINDOW_UPDATE sid:%ui delta:%ui", sid, delta);
1283
1284 if (sid) {
1285 stream = ngx_http_spdy_get_stream_by_id(sc, sid);
1286
1287 if (stream == NULL) {
1288 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1289 "client sent WINDOW_UPDATE frame "
1290 "for unknown stream %ui", sid);
1291
1292 if (ngx_http_spdy_send_rst_stream(sc, sid, NGX_SPDY_INVALID_STREAM,
1293 NGX_SPDY_LOWEST_PRIORITY)
1294 == NGX_ERROR)
1295 {
1296 return ngx_http_spdy_state_internal_error(sc);
1297 }
1298
1299 return ngx_http_spdy_state_complete(sc, pos, end);
1300 }
1301
1302 if (stream->send_window > (ssize_t) (NGX_SPDY_MAX_WINDOW - delta)) {
1303
1304 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1305 "client violated flow control for stream %ui: "
1306 "received WINDOW_UPDATE frame with delta %uz "
1307 "that is not allowed for window %z",
1308 sid, delta, stream->send_window);
1309
1310 if (ngx_http_spdy_terminate_stream(sc, stream,
1311 NGX_SPDY_FLOW_CONTROL_ERROR)
1312 == NGX_ERROR)
1313 {
1314 return ngx_http_spdy_state_internal_error(sc);
1315 }
1316
1317 return ngx_http_spdy_state_complete(sc, pos, end);
1318 }
1319
1320 stream->send_window += delta;
1321
1322 if (stream->exhausted) {
1323 stream->exhausted = 0;
1324
1325 wev = stream->request->connection->write;
1326
1327 if (!wev->timer_set) {
1328 wev->delayed = 0;
1329 wev->handler(wev);
1330 }
1331 }
1332
1333 } else {
1334 sc->send_window += delta;
1335
1336 if (sc->send_window > NGX_SPDY_MAX_WINDOW) {
1337 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1338 "client violated connection flow control: "
1339 "received WINDOW_UPDATE frame with delta %uz "
1340 "that is not allowed for window %uz",
1341 delta, sc->send_window);
1342
1343 return ngx_http_spdy_state_protocol_error(sc);
1344 }
1345
1346 while (!ngx_queue_empty(&sc->waiting)) {
1347 q = ngx_queue_head(&sc->waiting);
1348
1349 ngx_queue_remove(q);
1350
1351 stream = ngx_queue_data(q, ngx_http_spdy_stream_t, queue);
1352
1353 stream->handled = 0;
1354
1355 wev = stream->request->connection->write;
1356
1357 if (!wev->timer_set) {
1358 wev->delayed = 0;
1359 wev->handler(wev);
1360
1361 if (sc->send_window == 0) {
1362 break;
1363 }
1364 }
1365 }
1366 }
1367
1368 return ngx_http_spdy_state_complete(sc, pos, end);
1369 }
1370
1371
1372 static u_char *
1056 ngx_http_spdy_state_data(ngx_http_spdy_connection_t *sc, u_char *pos, 1373 ngx_http_spdy_state_data(ngx_http_spdy_connection_t *sc, u_char *pos,
1374 u_char *end)
1375 {
1376 ngx_http_spdy_stream_t *stream;
1377
1378 stream = sc->stream;
1379
1380 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1381 "spdy DATA frame");
1382
1383 if (sc->length > sc->recv_window) {
1384 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1385 "client violated connection flow control: length of "
1386 "received DATA frame %uz, while available window %uz",
1387 stream->id, sc->length, sc->recv_window);
1388
1389 return ngx_http_spdy_state_protocol_error(sc);
1390 }
1391
1392 sc->recv_window -= sc->length;
1393
1394 if (sc->recv_window < NGX_SPDY_MAX_WINDOW / 4) {
1395
1396 if (ngx_http_spdy_send_window_update(sc, 0,
1397 NGX_SPDY_MAX_WINDOW
1398 - sc->recv_window)
1399 == NGX_ERROR)
1400 {
1401 return ngx_http_spdy_state_internal_error(sc);
1402 }
1403
1404 sc->recv_window = NGX_SPDY_MAX_WINDOW;
1405 }
1406
1407 if (stream == NULL) {
1408 return ngx_http_spdy_state_skip(sc, pos, end);
1409 }
1410
1411 if (sc->length > stream->recv_window) {
1412 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1413 "client violated flow control for stream %ui: length of "
1414 "received DATA frame %uz, while available window %uz",
1415 stream->id, sc->length, stream->recv_window);
1416
1417 if (ngx_http_spdy_terminate_stream(sc, stream,
1418 NGX_SPDY_FLOW_CONTROL_ERROR)
1419 == NGX_ERROR)
1420 {
1421 return ngx_http_spdy_state_internal_error(sc);
1422 }
1423
1424 return ngx_http_spdy_state_skip(sc, pos, end);
1425 }
1426
1427 stream->recv_window -= sc->length;
1428
1429 if (stream->recv_window < NGX_SPDY_STREAM_WINDOW / 4) {
1430
1431 if (ngx_http_spdy_send_window_update(sc, stream->id,
1432 NGX_SPDY_STREAM_WINDOW
1433 - stream->recv_window)
1434 == NGX_ERROR)
1435 {
1436 return ngx_http_spdy_state_internal_error(sc);
1437 }
1438
1439 stream->recv_window = NGX_SPDY_STREAM_WINDOW;
1440 }
1441
1442 if (stream->in_closed) {
1443 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1444 "client sent DATA frame for half closed stream %ui",
1445 stream->id);
1446
1447 if (ngx_http_spdy_terminate_stream(sc, stream,
1448 NGX_SPDY_STREAM_ALREADY_CLOSED)
1449 == NGX_ERROR)
1450 {
1451 return ngx_http_spdy_state_internal_error(sc);
1452 }
1453
1454 return ngx_http_spdy_state_skip(sc, pos, end);
1455 }
1456
1457 return ngx_http_spdy_state_read_data(sc, pos, end);
1458 }
1459
1460
1461 static u_char *
1462 ngx_http_spdy_state_read_data(ngx_http_spdy_connection_t *sc, u_char *pos,
1057 u_char *end) 1463 u_char *end)
1058 { 1464 {
1059 size_t size; 1465 size_t size;
1060 ssize_t n; 1466 ssize_t n;
1061 ngx_buf_t *buf; 1467 ngx_buf_t *buf;
1067 ngx_http_request_body_t *rb; 1473 ngx_http_request_body_t *rb;
1068 ngx_http_core_loc_conf_t *clcf; 1474 ngx_http_core_loc_conf_t *clcf;
1069 1475
1070 stream = sc->stream; 1476 stream = sc->stream;
1071 1477
1072 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1073 "spdy DATA frame");
1074
1075 if (stream == NULL) { 1478 if (stream == NULL) {
1076 return ngx_http_spdy_state_skip(sc, pos, end); 1479 return ngx_http_spdy_state_skip(sc, pos, end);
1077 }
1078
1079 if (stream->in_closed) {
1080 /* TODO log */
1081 return ngx_http_spdy_state_protocol_error(sc);
1082 } 1480 }
1083 1481
1084 if (stream->skip_data) { 1482 if (stream->skip_data) {
1085 1483
1086 if (sc->flags & NGX_SPDY_FLAG_FIN) { 1484 if (sc->flags & NGX_SPDY_FLAG_FIN) {
1169 r->request_length += size; 1567 r->request_length += size;
1170 } 1568 }
1171 1569
1172 if (!complete) { 1570 if (!complete) {
1173 return ngx_http_spdy_state_save(sc, pos, end, 1571 return ngx_http_spdy_state_save(sc, pos, end,
1174 ngx_http_spdy_state_data); 1572 ngx_http_spdy_state_read_data);
1175 } 1573 }
1176 1574
1177 if (sc->flags & NGX_SPDY_FLAG_FIN) { 1575 if (sc->flags & NGX_SPDY_FLAG_FIN) {
1178 1576
1179 stream->in_closed = 1; 1577 stream->in_closed = 1;
1355 1753
1356 return ngx_http_spdy_state_complete(sc, pos + sc->length, end); 1754 return ngx_http_spdy_state_complete(sc, pos + sc->length, end);
1357 } 1755 }
1358 1756
1359 1757
1360 #if 0
1361
1362 static u_char * 1758 static u_char *
1363 ngx_http_spdy_state_settings(ngx_http_spdy_connection_t *sc, u_char *pos, 1759 ngx_http_spdy_state_settings(ngx_http_spdy_connection_t *sc, u_char *pos,
1364 u_char *end) 1760 u_char *end)
1365 { 1761 {
1762 ngx_uint_t fid, val;
1763
1366 if (sc->entries == 0) { 1764 if (sc->entries == 0) {
1367 1765
1368 if (end - pos < NGX_SPDY_SETTINGS_NUM_SIZE) { 1766 if (end - pos < NGX_SPDY_SETTINGS_NUM_SIZE) {
1369 return ngx_http_spdy_state_save(sc, pos, end, 1767 return ngx_http_spdy_state_save(sc, pos, end,
1370 ngx_http_spdy_state_settings); 1768 ngx_http_spdy_state_settings);
1390 return ngx_http_spdy_state_save(sc, pos, end, 1788 return ngx_http_spdy_state_save(sc, pos, end,
1391 ngx_http_spdy_state_settings); 1789 ngx_http_spdy_state_settings);
1392 } 1790 }
1393 1791
1394 sc->entries--; 1792 sc->entries--;
1395
1396 pos += NGX_SPDY_SETTINGS_PAIR_SIZE;
1397 sc->length -= NGX_SPDY_SETTINGS_PAIR_SIZE; 1793 sc->length -= NGX_SPDY_SETTINGS_PAIR_SIZE;
1398 } 1794
1399 1795 fid = ngx_spdy_frame_parse_uint32(pos);
1400 return ngx_http_spdy_state_complete(sc, pos, end); 1796
1401 } 1797 pos += NGX_SPDY_SETTINGS_FID_SIZE;
1402 1798
1403 #endif 1799 val = ngx_spdy_frame_parse_uint32(pos);
1404 1800
1405 1801 pos += NGX_SPDY_SETTINGS_VAL_SIZE;
1406 static u_char * 1802
1407 ngx_http_spdy_state_noop(ngx_http_spdy_connection_t *sc, u_char *pos, 1803 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1408 u_char *end) 1804 "spdy SETTINGS entry fl:%ui id:%ui val:%ui",
1409 { 1805 ngx_spdy_frame_flags(fid), ngx_spdy_frame_id(fid), val);
1410 if (sc->length) { 1806
1411 /* TODO logging */ 1807 if (ngx_spdy_frame_flags(fid) == NGX_SPDY_SETTINGS_FLAG_PERSISTED) {
1412 return ngx_http_spdy_state_protocol_error(sc); 1808 continue;
1809 }
1810
1811 switch (ngx_spdy_frame_id(fid)) {
1812
1813 case NGX_SPDY_SETTINGS_INIT_WINDOW:
1814
1815 if (val > NGX_SPDY_MAX_WINDOW) {
1816 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1817 "client sent SETTINGS frame with "
1818 "incorrect INIT_WINDOW value: %ui", val);
1819
1820 return ngx_http_spdy_state_protocol_error(sc);
1821 }
1822
1823 if (ngx_http_spdy_adjust_windows(sc, val - sc->init_window)
1824 != NGX_OK)
1825 {
1826 return ngx_http_spdy_state_internal_error(sc);
1827 }
1828
1829 sc->init_window = val;
1830
1831 continue;
1832 }
1413 } 1833 }
1414 1834
1415 return ngx_http_spdy_state_complete(sc, pos, end); 1835 return ngx_http_spdy_state_complete(sc, pos, end);
1416 } 1836 }
1417 1837
1471 return NULL; 1891 return NULL;
1472 } 1892 }
1473 1893
1474 1894
1475 static ngx_int_t 1895 static ngx_int_t
1896 ngx_http_spdy_send_window_update(ngx_http_spdy_connection_t *sc, ngx_uint_t sid,
1897 ngx_uint_t delta)
1898 {
1899 u_char *p;
1900 ngx_buf_t *buf;
1901 ngx_http_spdy_out_frame_t *frame;
1902
1903 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1904 "spdy write WINDOW_UPDATE sid:%ui delta:%ui", sid, delta);
1905
1906 frame = ngx_http_spdy_get_ctl_frame(sc, NGX_SPDY_WINDOW_UPDATE_SIZE,
1907 NGX_SPDY_HIGHEST_PRIORITY);
1908 if (frame == NULL) {
1909 return NGX_ERROR;
1910 }
1911
1912 buf = frame->first->buf;
1913
1914 p = buf->pos;
1915
1916 p = ngx_spdy_frame_write_head(p, NGX_SPDY_WINDOW_UPDATE);
1917 p = ngx_spdy_frame_write_flags_and_len(p, 0, NGX_SPDY_WINDOW_UPDATE_SIZE);
1918
1919 p = ngx_spdy_frame_write_sid(p, sid);
1920 p = ngx_spdy_frame_aligned_write_uint32(p, delta);
1921
1922 buf->last = p;
1923
1924 ngx_http_spdy_queue_frame(sc, frame);
1925
1926 return NGX_OK;
1927 }
1928
1929
1930 static ngx_int_t
1476 ngx_http_spdy_send_rst_stream(ngx_http_spdy_connection_t *sc, ngx_uint_t sid, 1931 ngx_http_spdy_send_rst_stream(ngx_http_spdy_connection_t *sc, ngx_uint_t sid,
1477 ngx_uint_t status, ngx_uint_t priority) 1932 ngx_uint_t status, ngx_uint_t priority)
1478 { 1933 {
1479 u_char *p; 1934 u_char *p;
1480 ngx_buf_t *buf; 1935 ngx_buf_t *buf;
1568 return NGX_ERROR; 2023 return NGX_ERROR;
1569 } 2024 }
1570 2025
1571 buf = ngx_create_temp_buf(sc->pool, NGX_SPDY_FRAME_HEADER_SIZE 2026 buf = ngx_create_temp_buf(sc->pool, NGX_SPDY_FRAME_HEADER_SIZE
1572 + NGX_SPDY_SETTINGS_NUM_SIZE 2027 + NGX_SPDY_SETTINGS_NUM_SIZE
1573 + NGX_SPDY_SETTINGS_PAIR_SIZE); 2028 + 2 * NGX_SPDY_SETTINGS_PAIR_SIZE);
1574 if (buf == NULL) { 2029 if (buf == NULL) {
1575 return NGX_ERROR; 2030 return NGX_ERROR;
1576 } 2031 }
1577 2032
1578 buf->last_buf = 1; 2033 buf->last_buf = 1;
1583 frame->first = cl; 2038 frame->first = cl;
1584 frame->last = cl; 2039 frame->last = cl;
1585 frame->handler = ngx_http_spdy_settings_frame_handler; 2040 frame->handler = ngx_http_spdy_settings_frame_handler;
1586 frame->stream = NULL; 2041 frame->stream = NULL;
1587 #if (NGX_DEBUG) 2042 #if (NGX_DEBUG)
1588 frame->length = NGX_SPDY_SETTINGS_NUM_SIZE + NGX_SPDY_SETTINGS_PAIR_SIZE; 2043 frame->length = NGX_SPDY_SETTINGS_NUM_SIZE
2044 + 2 * NGX_SPDY_SETTINGS_PAIR_SIZE;
1589 #endif 2045 #endif
1590 frame->priority = NGX_SPDY_HIGHEST_PRIORITY; 2046 frame->priority = NGX_SPDY_HIGHEST_PRIORITY;
1591 frame->blocked = 0; 2047 frame->blocked = 0;
1592 2048
1593 p = buf->pos; 2049 p = buf->pos;
1594 2050
1595 p = ngx_spdy_frame_write_head(p, NGX_SPDY_SETTINGS); 2051 p = ngx_spdy_frame_write_head(p, NGX_SPDY_SETTINGS);
1596 p = ngx_spdy_frame_write_flags_and_len(p, NGX_SPDY_FLAG_CLEAR_SETTINGS, 2052 p = ngx_spdy_frame_write_flags_and_len(p, NGX_SPDY_FLAG_CLEAR_SETTINGS,
1597 NGX_SPDY_SETTINGS_NUM_SIZE 2053 NGX_SPDY_SETTINGS_NUM_SIZE
1598 + NGX_SPDY_SETTINGS_PAIR_SIZE); 2054 + 2 * NGX_SPDY_SETTINGS_PAIR_SIZE);
1599 2055
1600 p = ngx_spdy_frame_aligned_write_uint32(p, 1); 2056 p = ngx_spdy_frame_aligned_write_uint32(p, 2);
1601 p = ngx_spdy_frame_aligned_write_uint32(p,
1602 NGX_SPDY_SETTINGS_MAX_STREAMS << 24);
1603 2057
1604 sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx, 2058 sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx,
1605 ngx_http_spdy_module); 2059 ngx_http_spdy_module);
1606 2060
2061 p = ngx_spdy_frame_write_flags_and_id(p, 0, NGX_SPDY_SETTINGS_MAX_STREAMS);
1607 p = ngx_spdy_frame_aligned_write_uint32(p, sscf->concurrent_streams); 2062 p = ngx_spdy_frame_aligned_write_uint32(p, sscf->concurrent_streams);
2063
2064 p = ngx_spdy_frame_write_flags_and_id(p, 0, NGX_SPDY_SETTINGS_INIT_WINDOW);
2065 p = ngx_spdy_frame_aligned_write_uint32(p, NGX_SPDY_STREAM_WINDOW);
1608 2066
1609 buf->last = p; 2067 buf->last = p;
1610 2068
1611 ngx_http_spdy_queue_frame(sc, frame); 2069 ngx_http_spdy_queue_frame(sc, frame);
1612 2070
1818 r->spdy_stream = stream; 2276 r->spdy_stream = stream;
1819 2277
1820 stream->id = id; 2278 stream->id = id;
1821 stream->request = r; 2279 stream->request = r;
1822 stream->connection = sc; 2280 stream->connection = sc;
2281
2282 stream->send_window = sc->init_window;
2283 stream->recv_window = NGX_SPDY_STREAM_WINDOW;
2284
1823 stream->priority = priority; 2285 stream->priority = priority;
1824 2286
1825 sscf = ngx_http_get_module_srv_conf(r, ngx_http_spdy_module); 2287 sscf = ngx_http_get_module_srv_conf(r, ngx_http_spdy_module);
1826 2288
1827 index = ngx_http_spdy_stream_index(sscf, id); 2289 index = ngx_http_spdy_stream_index(sscf, id);
1884 2346
1885 if (end - p < NGX_SPDY_NV_NLEN_SIZE) { 2347 if (end - p < NGX_SPDY_NV_NLEN_SIZE) {
1886 return NGX_AGAIN; 2348 return NGX_AGAIN;
1887 } 2349 }
1888 2350
1889 len = ngx_spdy_frame_parse_uint16(p); 2351 len = ngx_spdy_frame_parse_uint32(p);
1890 2352
1891 if (!len) { 2353 if (!len) {
1892 return NGX_HTTP_PARSE_INVALID_HEADER; 2354 return NGX_HTTP_PARSE_INVALID_HEADER;
1893 } 2355 }
1894 2356
1912 } 2374 }
1913 2375
1914 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); 2376 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1915 2377
1916 r->header_name_start = p; 2378 r->header_name_start = p;
2379
2380 if (p[0] == ':') {
2381 r->lowcase_index--;
2382 p++;
2383 }
1917 2384
1918 hash = 0; 2385 hash = 0;
1919 2386
1920 for ( /* void */ ; p != r->header_name_end; p++) { 2387 for ( /* void */ ; p != r->header_name_end; p++) {
1921 2388
1956 2423
1957 if (end - p < NGX_SPDY_NV_VLEN_SIZE) { 2424 if (end - p < NGX_SPDY_NV_VLEN_SIZE) {
1958 break; 2425 break;
1959 } 2426 }
1960 2427
1961 len = ngx_spdy_frame_parse_uint16(p); 2428 len = ngx_spdy_frame_parse_uint32(p);
1962 2429
1963 /* null-terminate header name */ 2430 /* null-terminate header name */
1964 *p = '\0'; 2431 *p = '\0';
1965 2432
1966 p += NGX_SPDY_NV_VLEN_SIZE; 2433 p += NGX_SPDY_NV_VLEN_SIZE;
2091 r->header_end - r->header_name_start, 2558 r->header_end - r->header_name_start,
2092 r->header_name_start); 2559 r->header_name_start);
2093 return NGX_OK; 2560 return NGX_OK;
2094 } 2561 }
2095 2562
2096 } else { 2563 }
2564
2565 if (r->header_name_start[0] == ':') {
2097 for (i = 0; i < NGX_SPDY_REQUEST_HEADERS; i++) { 2566 for (i = 0; i < NGX_SPDY_REQUEST_HEADERS; i++) {
2098 sh = &ngx_http_spdy_request_headers[i]; 2567 sh = &ngx_http_spdy_request_headers[i];
2099 2568
2100 if (sh->hash != r->header_hash 2569 if (sh->hash != r->header_hash
2101 || sh->len != r->lowcase_index 2570 || sh->len != r->lowcase_index
2102 || ngx_strncmp(sh->header, r->header_name_start, 2571 || ngx_strncmp(sh->header, &r->header_name_start[1],
2103 r->lowcase_index) 2572 r->lowcase_index)
2104 != 0) 2573 != 0)
2105 { 2574 {
2106 continue; 2575 continue;
2107 } 2576 }
2108 2577
2109 return sh->handler(r); 2578 return sh->handler(r);
2110 } 2579 }
2580
2581 return NGX_HTTP_PARSE_INVALID_REQUEST;
2111 } 2582 }
2112 2583
2113 h = ngx_list_push(&r->headers_in.headers); 2584 h = ngx_list_push(&r->headers_in.headers);
2114 if (h == NULL) { 2585 if (h == NULL) {
2115 ngx_http_spdy_close_stream(r->spdy_stream, 2586 ngx_http_spdy_close_stream(r->spdy_stream,
2241 return NGX_OK; 2712 return NGX_OK;
2242 } 2713 }
2243 2714
2244 2715
2245 static ngx_int_t 2716 static ngx_int_t
2246 ngx_http_spdy_parse_url(ngx_http_request_t *r) 2717 ngx_http_spdy_parse_host(ngx_http_request_t *r)
2718 {
2719 ngx_table_elt_t *h;
2720
2721 if (r->headers_in.host) {
2722 return NGX_HTTP_PARSE_INVALID_HEADER;
2723 }
2724
2725 h = ngx_list_push(&r->headers_in.headers);
2726 if (h == NULL) {
2727 ngx_http_spdy_close_stream(r->spdy_stream,
2728 NGX_HTTP_INTERNAL_SERVER_ERROR);
2729 return NGX_ERROR;
2730 }
2731
2732 r->headers_in.host = h;
2733
2734 h->hash = r->header_hash;
2735
2736 h->key.len = r->lowcase_index;
2737 h->key.data = &r->header_name_start[1];
2738
2739 h->value.len = r->header_size;
2740 h->value.data = r->header_start;
2741
2742 h->lowcase_key = h->key.data;
2743
2744 return NGX_OK;
2745 }
2746
2747
2748 static ngx_int_t
2749 ngx_http_spdy_parse_path(ngx_http_request_t *r)
2247 { 2750 {
2248 if (r->unparsed_uri.len) { 2751 if (r->unparsed_uri.len) {
2249 return NGX_HTTP_PARSE_INVALID_HEADER; 2752 return NGX_HTTP_PARSE_INVALID_HEADER;
2250 } 2753 }
2251 2754
2558 3061
2559 return NGX_AGAIN; 3062 return NGX_AGAIN;
2560 } 3063 }
2561 3064
2562 3065
3066 static ngx_int_t
3067 ngx_http_spdy_terminate_stream(ngx_http_spdy_connection_t *sc,
3068 ngx_http_spdy_stream_t *stream, ngx_uint_t status)
3069 {
3070 ngx_event_t *rev;
3071 ngx_connection_t *fc;
3072
3073 if (ngx_http_spdy_send_rst_stream(sc, stream->id, status,
3074 NGX_SPDY_HIGHEST_PRIORITY)
3075 == NGX_ERROR)
3076 {
3077 return NGX_ERROR;
3078 }
3079
3080 stream->out_closed = 1;
3081
3082 fc = stream->request->connection;
3083 fc->error = 1;
3084
3085 rev = fc->read;
3086 rev->handler(rev);
3087
3088 return NGX_OK;
3089 }
3090
3091
2563 static void 3092 static void
2564 ngx_http_spdy_close_stream_handler(ngx_event_t *ev) 3093 ngx_http_spdy_close_stream_handler(ngx_event_t *ev)
2565 { 3094 {
2566 ngx_connection_t *fc; 3095 ngx_connection_t *fc;
2567 ngx_http_request_t *r; 3096 ngx_http_request_t *r;
2588 sc = stream->connection; 3117 sc = stream->connection;
2589 3118
2590 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, 3119 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
2591 "spdy close stream %ui, queued %ui, processing %ui", 3120 "spdy close stream %ui, queued %ui, processing %ui",
2592 stream->id, stream->queued, sc->processing); 3121 stream->id, stream->queued, sc->processing);
2593
2594 if (stream->handled) {
2595 stream->handled = 0;
2596 ngx_queue_remove(&stream->queue);
2597 }
2598 3122
2599 fc = stream->request->connection; 3123 fc = stream->request->connection;
2600 3124
2601 if (stream->queued) { 3125 if (stream->queued) {
2602 fc->write->handler = ngx_http_spdy_close_stream_handler; 3126 fc->write->handler = ngx_http_spdy_close_stream_handler;
2836 3360
2837 ngx_http_close_connection(c); 3361 ngx_http_close_connection(c);
2838 } 3362 }
2839 3363
2840 3364
3365 static ngx_int_t
3366 ngx_http_spdy_adjust_windows(ngx_http_spdy_connection_t *sc, ssize_t delta)
3367 {
3368 ngx_uint_t i, size;
3369 ngx_event_t *wev;
3370 ngx_http_spdy_stream_t *stream, *sn;
3371 ngx_http_spdy_srv_conf_t *sscf;
3372
3373 sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx,
3374 ngx_http_spdy_module);
3375
3376 size = ngx_http_spdy_streams_index_size(sscf);
3377
3378 for (i = 0; i < size; i++) {
3379
3380 for (stream = sc->streams_index[i]; stream; stream = sn) {
3381 sn = stream->index;
3382
3383 if (delta > 0
3384 && stream->send_window
3385 > (ssize_t) (NGX_SPDY_MAX_WINDOW - delta))
3386 {
3387 if (ngx_http_spdy_terminate_stream(sc, stream,
3388 NGX_SPDY_FLOW_CONTROL_ERROR)
3389 == NGX_ERROR)
3390 {
3391 return NGX_ERROR;
3392 }
3393
3394 continue;
3395 }
3396
3397 stream->send_window += delta;
3398
3399 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
3400 "spdy:%ui adjust window:%z",
3401 stream->id, stream->send_window);
3402
3403 if (stream->send_window > 0 && stream->exhausted) {
3404 stream->exhausted = 0;
3405
3406 wev = stream->request->connection->write;
3407
3408 if (!wev->timer_set) {
3409 wev->delayed = 0;
3410 wev->handler(wev);
3411 }
3412 }
3413 }
3414 }
3415
3416 return NGX_OK;
3417 }
3418
3419
2841 static void 3420 static void
2842 ngx_http_spdy_pool_cleanup(void *data) 3421 ngx_http_spdy_pool_cleanup(void *data)
2843 { 3422 {
2844 ngx_http_spdy_connection_t *sc = data; 3423 ngx_http_spdy_connection_t *sc = data;
2845 3424