3 * Copyright (C) Nginx, Inc.
4 * Copyright (C) Valentin V. Bartenev
8 #include <ngx_config.h>
12 #include <ngx_http_spdy_module.h>
17 #define NGX_SPDY_WRITE_BUFFERED NGX_HTTP_WRITE_BUFFERED
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)
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
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)
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)
32 static ngx_inline ngx_int_t
ngx_http_spdy_filter_send(
33 ngx_connection_t
*fc
, ngx_http_spdy_stream_t
*stream
);
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
);
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
);
48 static void ngx_http_spdy_filter_cleanup(void *data
);
50 static ngx_int_t
ngx_http_spdy_filter_init(ngx_conf_t
*cf
);
53 static ngx_http_module_t ngx_http_spdy_filter_module_ctx
= {
54 NULL
, /* preconfiguration */
55 ngx_http_spdy_filter_init
, /* postconfiguration */
57 NULL
, /* create main configuration */
58 NULL
, /* init main configuration */
60 NULL
, /* create server configuration */
61 NULL
, /* merge server configuration */
63 NULL
, /* create location configuration */
64 NULL
/* merge location configuration */
68 ngx_module_t ngx_http_spdy_filter_module
= {
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 */
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
;
89 ngx_http_spdy_header_filter(ngx_http_request_t
*r
)
93 u_char
*p
, *buf
, *last
;
96 ngx_uint_t i
, j
, count
, port
;
98 ngx_list_part_t
*part
, *pt
;
99 ngx_table_elt_t
*header
, *h
;
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
;
109 struct sockaddr_in6
*sin6
;
111 u_char addr
[NGX_SOCKADDR_STRLEN
];
113 if (!r
->spdy_stream
) {
114 return ngx_http_next_header_filter(r
);
117 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
118 "spdy header filter");
120 if (r
->header_sent
) {
132 if (r
->method
== NGX_HTTP_HEAD
) {
136 switch (r
->headers_out
.status
) {
139 case NGX_HTTP_PARTIAL_CONTENT
:
142 case NGX_HTTP_NOT_MODIFIED
:
146 case NGX_HTTP_NO_CONTENT
:
149 ngx_str_null(&r
->headers_out
.content_type
);
151 r
->headers_out
.content_length
= NULL
;
152 r
->headers_out
.content_length_n
= -1;
157 r
->headers_out
.last_modified_time
= -1;
158 r
->headers_out
.last_modified
= NULL
;
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");
167 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
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");
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");
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
;
184 if (r
->headers_out
.content_type_len
== r
->headers_out
.content_type
.len
185 && r
->headers_out
.charset
.len
)
187 len
+= sizeof("; charset=") - 1 + r
->headers_out
.charset
.len
;
191 if (r
->headers_out
.content_length
== NULL
192 && r
->headers_out
.content_length_n
>= 0)
194 len
+= ngx_http_spdy_nv_nsize("content-length")
195 + NGX_SPDY_NV_VLEN_SIZE
+ NGX_OFF_T_LEN
;
198 if (r
->headers_out
.last_modified
== NULL
199 && r
->headers_out
.last_modified_time
!= -1)
201 len
+= ngx_http_spdy_nv_nsize("last-modified")
202 + ngx_http_spdy_nv_vsize("Wed, 31 Dec 1986 10:00:00 GMT");
205 if (r
->headers_out
.location
206 && r
->headers_out
.location
->value
.len
207 && r
->headers_out
.location
->value
.data
[0] == '/')
209 r
->headers_out
.location
->hash
= 0;
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
;
215 } else if (r
->headers_in
.server
.len
) {
216 host
= r
->headers_in
.server
;
219 host
.len
= NGX_SOCKADDR_STRLEN
;
222 if (ngx_connection_local_sockaddr(c
, &host
, 0) != NGX_OK
) {
227 switch (c
->local_sockaddr
->sa_family
) {
231 sin6
= (struct sockaddr_in6
*) c
->local_sockaddr
;
232 port
= ntohs(sin6
->sin6_port
);
235 #if (NGX_HAVE_UNIX_DOMAIN)
240 default: /* AF_INET */
241 sin
= (struct sockaddr_in
*) c
->local_sockaddr
;
242 port
= ntohs(sin
->sin_port
);
246 len
+= ngx_http_spdy_nv_nsize("location")
247 + ngx_http_spdy_nv_vsize("https://")
249 + r
->headers_out
.location
->value
.len
;
251 if (clcf
->port_in_redirect
) {
255 port
= (port
== 443) ? 0 : port
;
258 port
= (port
== 80) ? 0 : port
;
265 len
+= sizeof(":65535") - 1;
273 part
= &r
->headers_out
.headers
.part
;
276 for (i
= 0; /* void */; i
++) {
278 if (i
>= part
->nelts
) {
279 if (part
->next
== NULL
) {
288 if (header
[i
].hash
== 0) {
292 len
+= NGX_SPDY_NV_NLEN_SIZE
+ header
[i
].key
.len
293 + NGX_SPDY_NV_VLEN_SIZE
+ header
[i
].value
.len
;
296 buf
= ngx_alloc(len
, r
->pool
->log
);
301 last
= buf
+ NGX_SPDY_NV_NUM_SIZE
;
303 last
= ngx_http_spdy_nv_write_name(last
, "version");
304 last
= ngx_http_spdy_nv_write_val(last
, "HTTP/1.1");
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
);
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");
321 if (r
->headers_out
.date
== NULL
) {
322 last
= ngx_http_spdy_nv_write_name(last
, "date");
324 last
= ngx_http_spdy_nv_write_vlen(last
, ngx_cached_http_time
.len
);
326 last
= ngx_cpymem(last
, ngx_cached_http_time
.data
,
327 ngx_cached_http_time
.len
);
332 if (r
->headers_out
.content_type
.len
) {
334 last
= ngx_http_spdy_nv_write_name(last
, "content-type");
336 p
= last
+ NGX_SPDY_NV_VLEN_SIZE
;
338 last
= ngx_cpymem(p
, r
->headers_out
.content_type
.data
,
339 r
->headers_out
.content_type
.len
);
341 if (r
->headers_out
.content_type_len
== r
->headers_out
.content_type
.len
342 && r
->headers_out
.charset
.len
)
344 last
= ngx_cpymem(last
, "; charset=", sizeof("; charset=") - 1);
346 last
= ngx_cpymem(last
, r
->headers_out
.charset
.data
,
347 r
->headers_out
.charset
.len
);
349 /* update r->headers_out.content_type for possible logging */
351 r
->headers_out
.content_type
.len
= last
- p
;
352 r
->headers_out
.content_type
.data
= p
;
355 (void) ngx_http_spdy_nv_write_vlen(p
- NGX_SPDY_NV_VLEN_SIZE
,
356 r
->headers_out
.content_type
.len
);
361 if (r
->headers_out
.content_length
== NULL
362 && r
->headers_out
.content_length_n
>= 0)
364 last
= ngx_http_spdy_nv_write_name(last
, "content-length");
366 p
= last
+ NGX_SPDY_NV_VLEN_SIZE
;
368 last
= ngx_sprintf(p
, "%O", r
->headers_out
.content_length_n
);
370 (void) ngx_http_spdy_nv_write_vlen(p
- NGX_SPDY_NV_VLEN_SIZE
,
376 if (r
->headers_out
.last_modified
== NULL
377 && r
->headers_out
.last_modified_time
!= -1)
379 last
= ngx_http_spdy_nv_write_name(last
, "last-modified");
381 p
= last
+ NGX_SPDY_NV_VLEN_SIZE
;
383 last
= ngx_http_time(p
, r
->headers_out
.last_modified_time
);
385 (void) ngx_http_spdy_nv_write_vlen(p
- NGX_SPDY_NV_VLEN_SIZE
,
393 last
= ngx_http_spdy_nv_write_name(last
, "location");
395 p
= last
+ NGX_SPDY_NV_VLEN_SIZE
;
397 last
= ngx_cpymem(p
, "http", sizeof("http") - 1);
405 *last
++ = ':'; *last
++ = '/'; *last
++ = '/';
407 last
= ngx_cpymem(last
, host
.data
, host
.len
);
410 last
= ngx_sprintf(last
, ":%ui", port
);
413 last
= ngx_cpymem(last
, r
->headers_out
.location
->value
.data
,
414 r
->headers_out
.location
->value
.len
);
416 /* update r->headers_out.location->value for possible logging */
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");
422 (void) ngx_http_spdy_nv_write_vlen(p
- NGX_SPDY_NV_VLEN_SIZE
,
423 r
->headers_out
.location
->value
.len
);
428 part
= &r
->headers_out
.headers
.part
;
431 for (i
= 0; /* void */; i
++) {
433 if (i
>= part
->nelts
) {
434 if (part
->next
== NULL
) {
443 if (header
[i
].hash
== 0 || header
[i
].hash
== 2) {
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))
458 last
= ngx_http_spdy_nv_write_nlen(last
, header
[i
].key
.len
);
460 ngx_strlow(last
, header
[i
].key
.data
, header
[i
].key
.len
);
461 last
+= header
[i
].key
.len
;
463 p
= last
+ NGX_SPDY_NV_VLEN_SIZE
;
465 last
= ngx_cpymem(p
, header
[i
].value
.data
, header
[i
].value
.len
);
470 for (j
= i
+ 1; /* void */; j
++) {
472 if (j
>= pt
->nelts
) {
473 if (pt
->next
== NULL
) {
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
,
492 last
= ngx_cpymem(last
, h
[j
].value
.data
, h
[j
].value
.len
);
497 (void) ngx_http_spdy_nv_write_vlen(p
- NGX_SPDY_NV_VLEN_SIZE
,
503 (void) ngx_spdy_frame_write_uint16(buf
, count
);
505 stream
= r
->spdy_stream
;
506 sc
= stream
->connection
;
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
));
518 b
->last
+= NGX_SPDY_FRAME_HEADER_SIZE
+ NGX_SPDY_SYN_REPLY_SIZE
;
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
;
525 rc
= deflate(&sc
->zstream_out
, Z_SYNC_FLUSH
);
530 ngx_log_error(NGX_LOG_ALERT
, c
->log
, 0,
531 "spdy deflate() failed: %d", rc
);
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
,
541 b
->last
= sc
->zstream_out
.next_out
;
544 p
= ngx_spdy_frame_write_head(p
, NGX_SPDY_SYN_REPLY
);
546 len
= b
->last
- b
->pos
;
548 r
->header_size
= len
;
550 if (r
->header_only
) {
552 p
= ngx_spdy_frame_write_flags_and_len(p
, NGX_SPDY_FLAG_FIN
,
553 len
- NGX_SPDY_FRAME_HEADER_SIZE
);
555 p
= ngx_spdy_frame_write_flags_and_len(p
, 0,
556 len
- NGX_SPDY_FRAME_HEADER_SIZE
);
559 (void) ngx_spdy_frame_write_sid(p
, stream
->id
);
561 cl
= ngx_alloc_chain_link(r
->pool
);
569 frame
= ngx_palloc(r
->pool
, sizeof(ngx_http_spdy_out_frame_t
));
576 frame
->handler
= ngx_http_spdy_syn_frame_handler
;
578 frame
->stream
= stream
;
580 frame
->priority
= stream
->priority
;
582 frame
->fin
= r
->header_only
;
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
);
588 ngx_http_spdy_queue_blocked_frame(sc
, frame
);
592 cln
= ngx_http_cleanup_add(r
, 0);
597 cln
->handler
= ngx_http_spdy_filter_cleanup
;
602 return ngx_http_spdy_filter_send(c
, stream
);
607 ngx_http_spdy_body_filter(ngx_http_request_t
*r
, ngx_chain_t
*in
)
611 ngx_chain_t
*cl
, *ll
, *out
, **ln
;
612 ngx_http_spdy_stream_t
*stream
;
613 ngx_http_spdy_out_frame_t
*frame
;
615 stream
= r
->spdy_stream
;
617 if (stream
== NULL
) {
618 return ngx_http_next_body_filter(r
, in
);
621 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
622 "spdy body filter \"%V?%V\"", &r
->uri
, &r
->args
);
624 if (in
== NULL
|| r
->header_only
) {
626 if (stream
->waiting
) {
630 r
->connection
->buffered
&= ~NGX_SPDY_WRITE_BUFFERED
;
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",
660 cl
= ngx_alloc_chain_link(r
->pool
);
665 size
+= ngx_buf_size(b
);
671 if (ll
->next
== NULL
) {
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
);
684 frame
= ngx_http_spdy_filter_get_data_frame(stream
, (size_t) size
,
685 b
->last_buf
, out
, cl
);
690 ngx_http_spdy_queue_frame(stream
->connection
, frame
);
696 return ngx_http_spdy_filter_send(r
->connection
, stream
);
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
)
708 ngx_http_spdy_out_frame_t
*frame
;
711 frame
= stream
->free_frames
;
714 stream
->free_frames
= frame
->free
;
717 frame
= ngx_palloc(stream
->request
->pool
,
718 sizeof(ngx_http_spdy_out_frame_t
));
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
);
730 flags
= fin
? NGX_SPDY_FLAG_FIN
: 0;
732 cl
= ngx_chain_get_free_buf(stream
->request
->pool
,
733 &stream
->free_data_headers
);
744 p
+= sizeof(uint32_t);
746 (void) ngx_spdy_frame_write_flags_and_len(p
, flags
, len
);
749 p
= ngx_palloc(stream
->request
->pool
, NGX_SPDY_FRAME_HEADER_SIZE
);
757 p
= ngx_spdy_frame_write_sid(p
, stream
->id
);
758 p
= ngx_spdy_frame_write_flags_and_len(p
, flags
, len
);
763 buf
->tag
= (ngx_buf_tag_t
) &ngx_http_spdy_filter_module
;
771 frame
->first
= first
;
773 frame
->handler
= ngx_http_spdy_data_frame_handler
;
775 frame
->stream
= stream
;
776 frame
->size
= NGX_SPDY_FRAME_HEADER_SIZE
+ len
;
777 frame
->priority
= stream
->priority
;
785 static ngx_inline ngx_int_t
786 ngx_http_spdy_filter_send(ngx_connection_t
*fc
, ngx_http_spdy_stream_t
*stream
)
788 if (ngx_http_spdy_send_output_queue(stream
->connection
) == NGX_ERROR
) {
793 if (stream
->waiting
) {
794 fc
->buffered
|= NGX_SPDY_WRITE_BUFFERED
;
795 fc
->write
->delayed
= 1;
799 fc
->buffered
&= ~NGX_SPDY_WRITE_BUFFERED
;
806 ngx_http_spdy_syn_frame_handler(ngx_http_spdy_connection_t
*sc
,
807 ngx_http_spdy_out_frame_t
*frame
)
810 ngx_http_spdy_stream_t
*stream
;
812 buf
= frame
->first
->buf
;
814 if (buf
->pos
!= buf
->last
) {
818 stream
= frame
->stream
;
820 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, sc
->connection
->log
, 0,
821 "spdy:%ui SYN_REPLY frame %p was sent", stream
->id
, frame
);
823 ngx_free_chain(stream
->request
->pool
, frame
->first
);
825 ngx_http_spdy_handle_frame(stream
, frame
);
827 ngx_http_spdy_handle_stream(sc
, stream
);
834 ngx_http_spdy_data_frame_handler(ngx_http_spdy_connection_t
*sc
,
835 ngx_http_spdy_out_frame_t
*frame
)
837 ngx_chain_t
*cl
, *ln
;
838 ngx_http_spdy_stream_t
*stream
;
840 stream
= frame
->stream
;
844 if (cl
->buf
->tag
== (ngx_buf_tag_t
) &ngx_http_spdy_filter_module
) {
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",
856 cl
->next
= stream
->free_data_headers
;
857 stream
->free_data_headers
= cl
;
859 if (cl
== frame
->last
) {
867 if (ngx_buf_size(cl
->buf
) != 0) {
869 if (cl
!= frame
->first
) {
871 ngx_http_spdy_handle_stream(sc
, stream
);
874 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, sc
->connection
->log
, 0,
875 "spdy:%ui DATA frame %p was sent partially",
883 ngx_free_chain(stream
->request
->pool
, cl
);
885 if (cl
== frame
->last
) {
894 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, sc
->connection
->log
, 0,
895 "spdy:%ui DATA frame %p was sent", stream
->id
, frame
);
897 stream
->request
->header_size
+= NGX_SPDY_FRAME_HEADER_SIZE
;
899 ngx_http_spdy_handle_frame(stream
, frame
);
901 ngx_http_spdy_handle_stream(sc
, stream
);
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
)
911 ngx_http_request_t
*r
;
915 r
->connection
->sent
+= frame
->size
;
919 stream
->out_closed
= 1;
922 frame
->free
= stream
->free_frames
;
923 stream
->free_frames
= frame
;
929 static ngx_inline
void
930 ngx_http_spdy_handle_stream(ngx_http_spdy_connection_t
*sc
,
931 ngx_http_spdy_stream_t
*stream
)
933 ngx_connection_t
*fc
;
935 fc
= stream
->request
->connection
;
937 fc
->write
->delayed
= 0;
939 if (stream
->handled
) {
943 if (sc
->blocked
== 2) {
946 stream
->next
= sc
->last_stream
;
947 sc
->last_stream
= stream
;
953 ngx_http_spdy_filter_cleanup(void *data
)
955 ngx_http_spdy_stream_t
*stream
= data
;
957 ngx_http_request_t
*r
;
958 ngx_http_spdy_out_frame_t
*frame
, **fn
;
960 if (stream
->waiting
== 0) {
966 fn
= &stream
->connection
->last_out
;
975 if (frame
->stream
== stream
&& !frame
->blocked
) {
990 ngx_http_spdy_filter_init(ngx_conf_t
*cf
)
992 ngx_http_next_header_filter
= ngx_http_top_header_filter
;
993 ngx_http_top_header_filter
= ngx_http_spdy_header_filter
;
995 ngx_http_next_body_filter
= ngx_http_top_body_filter
;
996 ngx_http_top_body_filter
= ngx_http_spdy_body_filter
;