comparison src/http/ngx_http_spdy_filter_module.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 2bc609a4b516
comparison
equal deleted inserted replaced
5548:4d47722d76b2 5549:39d7eef2e332
15 15
16 16
17 #define ngx_http_spdy_nv_nsize(h) (NGX_SPDY_NV_NLEN_SIZE + sizeof(h) - 1) 17 #define ngx_http_spdy_nv_nsize(h) (NGX_SPDY_NV_NLEN_SIZE + sizeof(h) - 1)
18 #define ngx_http_spdy_nv_vsize(h) (NGX_SPDY_NV_VLEN_SIZE + sizeof(h) - 1) 18 #define ngx_http_spdy_nv_vsize(h) (NGX_SPDY_NV_VLEN_SIZE + sizeof(h) - 1)
19 19
20 #define ngx_http_spdy_nv_write_num ngx_spdy_frame_write_uint16 20 #define ngx_http_spdy_nv_write_num ngx_spdy_frame_write_uint32
21 #define ngx_http_spdy_nv_write_nlen ngx_spdy_frame_write_uint16 21 #define ngx_http_spdy_nv_write_nlen ngx_spdy_frame_write_uint32
22 #define ngx_http_spdy_nv_write_vlen ngx_spdy_frame_write_uint16 22 #define ngx_http_spdy_nv_write_vlen ngx_spdy_frame_write_uint32
23 23
24 #define ngx_http_spdy_nv_write_name(p, h) \ 24 #define ngx_http_spdy_nv_write_name(p, h) \
25 ngx_cpymem(ngx_http_spdy_nv_write_nlen(p, sizeof(h) - 1), h, sizeof(h) - 1) 25 ngx_cpymem(ngx_http_spdy_nv_write_nlen(p, sizeof(h) - 1), h, sizeof(h) - 1)
26 26
27 #define ngx_http_spdy_nv_write_val(p, h) \ 27 #define ngx_http_spdy_nv_write_val(p, h) \
31 static ngx_chain_t *ngx_http_spdy_send_chain(ngx_connection_t *fc, 31 static ngx_chain_t *ngx_http_spdy_send_chain(ngx_connection_t *fc,
32 ngx_chain_t *in, off_t limit); 32 ngx_chain_t *in, off_t limit);
33 33
34 static ngx_inline ngx_int_t ngx_http_spdy_filter_send( 34 static ngx_inline ngx_int_t ngx_http_spdy_filter_send(
35 ngx_connection_t *fc, ngx_http_spdy_stream_t *stream); 35 ngx_connection_t *fc, ngx_http_spdy_stream_t *stream);
36 static ngx_inline ngx_int_t ngx_http_spdy_flow_control(
37 ngx_http_spdy_connection_t *sc, ngx_http_spdy_stream_t *stream);
38 static void ngx_http_spdy_waiting_queue(ngx_http_spdy_connection_t *sc,
39 ngx_http_spdy_stream_t *stream);
36 40
37 static ngx_chain_t *ngx_http_spdy_filter_get_shadow( 41 static ngx_chain_t *ngx_http_spdy_filter_get_shadow(
38 ngx_http_spdy_stream_t *stream, ngx_buf_t *buf, off_t offset, off_t size); 42 ngx_http_spdy_stream_t *stream, ngx_buf_t *buf, off_t offset, off_t size);
39 static ngx_http_spdy_out_frame_t *ngx_http_spdy_filter_get_data_frame( 43 static ngx_http_spdy_out_frame_t *ngx_http_spdy_filter_get_data_frame(
40 ngx_http_spdy_stream_t *stream, size_t len, ngx_chain_t *first, 44 ngx_http_spdy_stream_t *stream, size_t len, ngx_chain_t *first,
160 r->headers_out.last_modified_time = -1; 164 r->headers_out.last_modified_time = -1;
161 r->headers_out.last_modified = NULL; 165 r->headers_out.last_modified = NULL;
162 } 166 }
163 167
164 len = NGX_SPDY_NV_NUM_SIZE 168 len = NGX_SPDY_NV_NUM_SIZE
165 + ngx_http_spdy_nv_nsize("version") 169 + ngx_http_spdy_nv_nsize(":version")
166 + ngx_http_spdy_nv_vsize("HTTP/1.1") 170 + ngx_http_spdy_nv_vsize("HTTP/1.1")
167 + ngx_http_spdy_nv_nsize("status") 171 + ngx_http_spdy_nv_nsize(":status")
168 + (r->headers_out.status_line.len 172 + (r->headers_out.status_line.len
169 ? NGX_SPDY_NV_VLEN_SIZE + r->headers_out.status_line.len 173 ? NGX_SPDY_NV_VLEN_SIZE + r->headers_out.status_line.len
170 : ngx_http_spdy_nv_vsize("418")); 174 : ngx_http_spdy_nv_vsize("418"));
171 175
172 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 176 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
303 return NGX_ERROR; 307 return NGX_ERROR;
304 } 308 }
305 309
306 last = buf + NGX_SPDY_NV_NUM_SIZE; 310 last = buf + NGX_SPDY_NV_NUM_SIZE;
307 311
308 last = ngx_http_spdy_nv_write_name(last, "version"); 312 last = ngx_http_spdy_nv_write_name(last, ":version");
309 last = ngx_http_spdy_nv_write_val(last, "HTTP/1.1"); 313 last = ngx_http_spdy_nv_write_val(last, "HTTP/1.1");
310 314
311 last = ngx_http_spdy_nv_write_name(last, "status"); 315 last = ngx_http_spdy_nv_write_name(last, ":status");
312 316
313 if (r->headers_out.status_line.len) { 317 if (r->headers_out.status_line.len) {
314 last = ngx_http_spdy_nv_write_vlen(last, 318 last = ngx_http_spdy_nv_write_vlen(last,
315 r->headers_out.status_line.len); 319 r->headers_out.status_line.len);
316 last = ngx_cpymem(last, r->headers_out.status_line.data, 320 last = ngx_cpymem(last, r->headers_out.status_line.data,
455 459
456 if (header[i].hash == 0 || header[i].hash == 2) { 460 if (header[i].hash == 0 || header[i].hash == 2) {
457 continue; 461 continue;
458 } 462 }
459 463
460 if ((header[i].key.len == 6
461 && ngx_strncasecmp(header[i].key.data,
462 (u_char *) "status", 6) == 0)
463 || (header[i].key.len == 7
464 && ngx_strncasecmp(header[i].key.data,
465 (u_char *) "version", 7) == 0))
466 {
467 header[i].hash = 0;
468 continue;
469 }
470
471 last = ngx_http_spdy_nv_write_nlen(last, header[i].key.len); 464 last = ngx_http_spdy_nv_write_nlen(last, header[i].key.len);
472 465
473 ngx_strlow(last, header[i].key.data, header[i].key.len); 466 ngx_strlow(last, header[i].key.data, header[i].key.len);
474 last += header[i].key.len; 467 last += header[i].key.len;
475 468
618 611
619 612
620 static ngx_chain_t * 613 static ngx_chain_t *
621 ngx_http_spdy_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) 614 ngx_http_spdy_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit)
622 { 615 {
623 off_t size, offset; 616 off_t size, offset;
624 size_t rest, frame_size; 617 size_t rest, frame_size;
625 ngx_chain_t *cl, *out, **ln; 618 ngx_chain_t *cl, *out, **ln;
626 ngx_http_request_t *r; 619 ngx_http_request_t *r;
627 ngx_http_spdy_stream_t *stream; 620 ngx_http_spdy_stream_t *stream;
628 ngx_http_spdy_loc_conf_t *slcf; 621 ngx_http_spdy_loc_conf_t *slcf;
629 ngx_http_spdy_out_frame_t *frame; 622 ngx_http_spdy_out_frame_t *frame;
623 ngx_http_spdy_connection_t *sc;
630 624
631 r = fc->data; 625 r = fc->data;
632 stream = r->spdy_stream; 626 stream = r->spdy_stream;
633 627
634 if (in == NULL) { 628 if (in == NULL) {
640 } 634 }
641 635
642 return NULL; 636 return NULL;
643 } 637 }
644 638
639 sc = stream->connection;
640
645 size = ngx_buf_size(in->buf); 641 size = ngx_buf_size(in->buf);
642
643 if (size && ngx_http_spdy_flow_control(sc, stream) == NGX_DECLINED) {
644 fc->write->delayed = 1;
645 return in;
646 }
647
648 if (limit == 0 || limit > (off_t) sc->send_window) {
649 limit = sc->send_window;
650 }
651
652 if (limit > stream->send_window) {
653 limit = (stream->send_window > 0) ? stream->send_window : 0;
654 }
646 655
647 if (in->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow) { 656 if (in->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow) {
648 cl = ngx_alloc_chain_link(r->pool); 657 cl = ngx_alloc_chain_link(r->pool);
649 if (cl == NULL) { 658 if (cl == NULL) {
650 return NGX_CHAIN_ERROR; 659 return NGX_CHAIN_ERROR;
668 cl = NULL; 677 cl = NULL;
669 #endif 678 #endif
670 679
671 slcf = ngx_http_get_module_loc_conf(r, ngx_http_spdy_module); 680 slcf = ngx_http_get_module_loc_conf(r, ngx_http_spdy_module);
672 681
673 frame_size = (limit && limit <= (off_t) slcf->chunk_size) 682 frame_size = (limit <= (off_t) slcf->chunk_size) ? (size_t) limit
674 ? (size_t) limit 683 : slcf->chunk_size;
675 : slcf->chunk_size;
676 684
677 for ( ;; ) { 685 for ( ;; ) {
678 ln = &out; 686 ln = &out;
679 rest = frame_size; 687 rest = frame_size;
680 688
733 out, cl); 741 out, cl);
734 if (frame == NULL) { 742 if (frame == NULL) {
735 return NGX_CHAIN_ERROR; 743 return NGX_CHAIN_ERROR;
736 } 744 }
737 745
738 ngx_http_spdy_queue_frame(stream->connection, frame); 746 ngx_http_spdy_queue_frame(sc, frame);
739 747
748 sc->send_window -= frame_size;
749
750 stream->send_window -= frame_size;
740 stream->queued++; 751 stream->queued++;
741 752
742 if (in == NULL) { 753 if (in == NULL) {
743 break; 754 break;
744 } 755 }
745 756
746 if (limit) { 757 limit -= frame_size;
747 limit -= frame_size; 758
748 759 if (limit == 0) {
749 if (limit == 0) { 760 break;
750 break; 761 }
751 } 762
752 763 if (limit < (off_t) slcf->chunk_size) {
753 if (limit < (off_t) slcf->chunk_size) { 764 frame_size = (size_t) limit;
754 frame_size = (size_t) limit;
755 }
756 } 765 }
757 } 766 }
758 767
759 if (offset) { 768 if (offset) {
760 cl = ngx_http_spdy_filter_get_shadow(stream, in->buf, offset, size); 769 cl = ngx_http_spdy_filter_get_shadow(stream, in->buf, offset, size);
766 ngx_free_chain(r->pool, cl); 775 ngx_free_chain(r->pool, cl);
767 } 776 }
768 777
769 if (ngx_http_spdy_filter_send(fc, stream) == NGX_ERROR) { 778 if (ngx_http_spdy_filter_send(fc, stream) == NGX_ERROR) {
770 return NGX_CHAIN_ERROR; 779 return NGX_CHAIN_ERROR;
780 }
781
782 if (in && ngx_http_spdy_flow_control(sc, stream) == NGX_DECLINED) {
783 fc->write->delayed = 1;
771 } 784 }
772 785
773 return in; 786 return in;
774 } 787 }
775 788
874 buf->memory = 1; 887 buf->memory = 1;
875 } 888 }
876 889
877 cl->next = first; 890 cl->next = first;
878 first = cl; 891 first = cl;
892
893 last->buf->flush = 1;
879 } 894 }
880 895
881 frame->first = first; 896 frame->first = first;
882 frame->last = last; 897 frame->last = last;
883 frame->handler = ngx_http_spdy_data_frame_handler; 898 frame->handler = ngx_http_spdy_data_frame_handler;
913 928
914 return NGX_OK; 929 return NGX_OK;
915 } 930 }
916 931
917 932
933 static ngx_inline ngx_int_t
934 ngx_http_spdy_flow_control(ngx_http_spdy_connection_t *sc,
935 ngx_http_spdy_stream_t *stream)
936 {
937 if (stream->send_window <= 0) {
938 stream->exhausted = 1;
939 return NGX_DECLINED;
940 }
941
942 if (sc->send_window == 0) {
943 ngx_http_spdy_waiting_queue(sc, stream);
944 return NGX_DECLINED;
945 }
946
947 return NGX_OK;
948 }
949
950
951 static void
952 ngx_http_spdy_waiting_queue(ngx_http_spdy_connection_t *sc,
953 ngx_http_spdy_stream_t *stream)
954 {
955 ngx_queue_t *q;
956 ngx_http_spdy_stream_t *s;
957
958 if (stream->handled) {
959 return;
960 }
961
962 stream->handled = 1;
963
964 for (q = ngx_queue_last(&sc->waiting);
965 q != ngx_queue_sentinel(&sc->waiting);
966 q = ngx_queue_prev(q))
967 {
968 s = ngx_queue_data(q, ngx_http_spdy_stream_t, queue);
969
970 if (s->priority >= stream->priority) {
971 break;
972 }
973 }
974
975 ngx_queue_insert_after(q, &stream->queue);
976 }
977
978
918 static ngx_int_t 979 static ngx_int_t
919 ngx_http_spdy_syn_frame_handler(ngx_http_spdy_connection_t *sc, 980 ngx_http_spdy_syn_frame_handler(ngx_http_spdy_connection_t *sc,
920 ngx_http_spdy_out_frame_t *frame) 981 ngx_http_spdy_out_frame_t *frame)
921 { 982 {
922 ngx_buf_t *buf; 983 ngx_buf_t *buf;
1061 ngx_http_spdy_handle_stream(ngx_http_spdy_connection_t *sc, 1122 ngx_http_spdy_handle_stream(ngx_http_spdy_connection_t *sc,
1062 ngx_http_spdy_stream_t *stream) 1123 ngx_http_spdy_stream_t *stream)
1063 { 1124 {
1064 ngx_event_t *wev; 1125 ngx_event_t *wev;
1065 1126
1066 if (stream->handled || stream->blocked) { 1127 if (stream->handled || stream->blocked || stream->exhausted) {
1067 return; 1128 return;
1068 } 1129 }
1069 1130
1070 wev = stream->request->connection->write; 1131 wev = stream->request->connection->write;
1071 1132
1081 static void 1142 static void
1082 ngx_http_spdy_filter_cleanup(void *data) 1143 ngx_http_spdy_filter_cleanup(void *data)
1083 { 1144 {
1084 ngx_http_spdy_stream_t *stream = data; 1145 ngx_http_spdy_stream_t *stream = data;
1085 1146
1086 ngx_http_spdy_out_frame_t *frame, **fn; 1147 size_t delta;
1148 ngx_http_spdy_out_frame_t *frame, **fn;
1149 ngx_http_spdy_connection_t *sc;
1150
1151 if (stream->handled) {
1152 stream->handled = 0;
1153 ngx_queue_remove(&stream->queue);
1154 }
1087 1155
1088 if (stream->queued == 0) { 1156 if (stream->queued == 0) {
1089 return; 1157 return;
1090 } 1158 }
1091 1159
1092 fn = &stream->connection->last_out; 1160 delta = 0;
1161 sc = stream->connection;
1162 fn = &sc->last_out;
1093 1163
1094 for ( ;; ) { 1164 for ( ;; ) {
1095 frame = *fn; 1165 frame = *fn;
1096 1166
1097 if (frame == NULL) { 1167 if (frame == NULL) {
1098 break; 1168 break;
1099 } 1169 }
1100 1170
1101 if (frame->stream == stream && !frame->blocked) { 1171 if (frame->stream == stream && !frame->blocked) {
1102 stream->queued--;
1103
1104 *fn = frame->next; 1172 *fn = frame->next;
1173
1174 delta += frame->length;
1175
1176 if (--stream->queued == 0) {
1177 break;
1178 }
1179
1105 continue; 1180 continue;
1106 } 1181 }
1107 1182
1108 fn = &frame->next; 1183 fn = &frame->next;
1109 } 1184 }
1185
1186 if (sc->send_window == 0 && delta && !ngx_queue_empty(&sc->waiting)) {
1187 ngx_queue_add(&sc->posted, &sc->waiting);
1188 ngx_queue_init(&sc->waiting);
1189 }
1190
1191 sc->send_window += delta;
1110 } 1192 }
1111 1193
1112 1194
1113 static ngx_int_t 1195 static ngx_int_t
1114 ngx_http_spdy_filter_init(ngx_conf_t *cf) 1196 ngx_http_spdy_filter_init(ngx_conf_t *cf)