comparison src/http/v2/ngx_http_v2_filter_module.c @ 7191:61d276dcd493

HTTP/2: more style, comments, and debugging.
author Ruslan Ermilov <ru@nginx.com>
date Mon, 29 Jan 2018 16:06:33 +0300
parents 2bf605c6edf7
children 641306096f5b
comparison
equal deleted inserted replaced
7190:e11a0679d349 7191:61d276dcd493
136 ngx_uint_t i, port; 136 ngx_uint_t i, port;
137 ngx_list_part_t *part; 137 ngx_list_part_t *part;
138 ngx_table_elt_t *header; 138 ngx_table_elt_t *header;
139 ngx_connection_t *fc; 139 ngx_connection_t *fc;
140 ngx_http_cleanup_t *cln; 140 ngx_http_cleanup_t *cln;
141 ngx_http_v2_stream_t *stream;
141 ngx_http_v2_out_frame_t *frame; 142 ngx_http_v2_out_frame_t *frame;
142 ngx_http_v2_connection_t *h2c; 143 ngx_http_v2_connection_t *h2c;
143 ngx_http_core_loc_conf_t *clcf; 144 ngx_http_core_loc_conf_t *clcf;
144 ngx_http_core_srv_conf_t *cscf; 145 ngx_http_core_srv_conf_t *cscf;
145 u_char addr[NGX_SOCKADDR_STRLEN]; 146 u_char addr[NGX_SOCKADDR_STRLEN];
155 156
156 static size_t nginx_ver_build_len = 157 static size_t nginx_ver_build_len =
157 ngx_http_v2_literal_size(NGINX_VER_BUILD); 158 ngx_http_v2_literal_size(NGINX_VER_BUILD);
158 static u_char nginx_ver_build[ngx_http_v2_literal_size(NGINX_VER_BUILD)]; 159 static u_char nginx_ver_build[ngx_http_v2_literal_size(NGINX_VER_BUILD)];
159 160
160 if (!r->stream) { 161 stream = r->stream;
162
163 if (!stream) {
161 return ngx_http_next_header_filter(r); 164 return ngx_http_next_header_filter(r);
162 } 165 }
163 166
164 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 167 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
165 "http2 header filter"); 168 "http2 header filter");
234 default: 237 default:
235 status = 0; 238 status = 0;
236 } 239 }
237 } 240 }
238 241
239 h2c = r->stream->connection; 242 h2c = stream->connection;
240 243
241 len = h2c->table_update ? 1 : 0; 244 len = h2c->table_update ? 1 : 0;
242 245
243 len += status ? 1 : 1 + ngx_http_v2_literal_size("418"); 246 len += status ? 1 : 1 + ngx_http_v2_literal_size("418");
244 247
631 frame = ngx_http_v2_create_headers_frame(r, start, pos, r->header_only); 634 frame = ngx_http_v2_create_headers_frame(r, start, pos, r->header_only);
632 if (frame == NULL) { 635 if (frame == NULL) {
633 return NGX_ERROR; 636 return NGX_ERROR;
634 } 637 }
635 638
636 ngx_http_v2_queue_blocked_frame(r->stream->connection, frame); 639 ngx_http_v2_queue_blocked_frame(h2c, frame);
637 640
638 r->stream->queued = 1; 641 stream->queued = 1;
639 642
640 cln = ngx_http_cleanup_add(r, 0); 643 cln = ngx_http_cleanup_add(r, 0);
641 if (cln == NULL) { 644 if (cln == NULL) {
642 return NGX_ERROR; 645 return NGX_ERROR;
643 } 646 }
644 647
645 cln->handler = ngx_http_v2_filter_cleanup; 648 cln->handler = ngx_http_v2_filter_cleanup;
646 cln->data = r->stream; 649 cln->data = stream;
647 650
648 fc->send_chain = ngx_http_v2_send_chain; 651 fc->send_chain = ngx_http_v2_send_chain;
649 fc->need_last_buf = 1; 652 fc->need_last_buf = 1;
650 653
651 return ngx_http_v2_filter_send(fc, r->stream); 654 return ngx_http_v2_filter_send(fc, stream);
652 }
653
654
655 static ngx_http_v2_out_frame_t *
656 ngx_http_v2_create_trailers_frame(ngx_http_request_t *r)
657 {
658 u_char *pos, *start, *tmp;
659 size_t len, tmp_len;
660 ngx_uint_t i;
661 ngx_list_part_t *part;
662 ngx_table_elt_t *header;
663
664 len = 0;
665 tmp_len = 0;
666
667 part = &r->headers_out.trailers.part;
668 header = part->elts;
669
670 for (i = 0; /* void */; i++) {
671
672 if (i >= part->nelts) {
673 if (part->next == NULL) {
674 break;
675 }
676
677 part = part->next;
678 header = part->elts;
679 i = 0;
680 }
681
682 if (header[i].hash == 0) {
683 continue;
684 }
685
686 if (header[i].key.len > NGX_HTTP_V2_MAX_FIELD) {
687 ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
688 "too long response trailer name: \"%V\"",
689 &header[i].key);
690 return NULL;
691 }
692
693 if (header[i].value.len > NGX_HTTP_V2_MAX_FIELD) {
694 ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
695 "too long response trailer value: \"%V: %V\"",
696 &header[i].key, &header[i].value);
697 return NULL;
698 }
699
700 len += 1 + NGX_HTTP_V2_INT_OCTETS + header[i].key.len
701 + NGX_HTTP_V2_INT_OCTETS + header[i].value.len;
702
703 if (header[i].key.len > tmp_len) {
704 tmp_len = header[i].key.len;
705 }
706
707 if (header[i].value.len > tmp_len) {
708 tmp_len = header[i].value.len;
709 }
710 }
711
712 if (len == 0) {
713 return NGX_HTTP_V2_NO_TRAILERS;
714 }
715
716 tmp = ngx_palloc(r->pool, tmp_len);
717 pos = ngx_pnalloc(r->pool, len);
718
719 if (pos == NULL || tmp == NULL) {
720 return NULL;
721 }
722
723 start = pos;
724
725 part = &r->headers_out.trailers.part;
726 header = part->elts;
727
728 for (i = 0; /* void */; i++) {
729
730 if (i >= part->nelts) {
731 if (part->next == NULL) {
732 break;
733 }
734
735 part = part->next;
736 header = part->elts;
737 i = 0;
738 }
739
740 if (header[i].hash == 0) {
741 continue;
742 }
743
744 #if (NGX_DEBUG)
745 if (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP) {
746 ngx_strlow(tmp, header[i].key.data, header[i].key.len);
747
748 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
749 "http2 output trailer: \"%*s: %V\"",
750 header[i].key.len, tmp, &header[i].value);
751 }
752 #endif
753
754 *pos++ = 0;
755
756 pos = ngx_http_v2_write_name(pos, header[i].key.data,
757 header[i].key.len, tmp);
758
759 pos = ngx_http_v2_write_value(pos, header[i].value.data,
760 header[i].value.len, tmp);
761 }
762
763 return ngx_http_v2_create_headers_frame(r, start, pos, 1);
764 } 655 }
765 656
766 657
767 static u_char * 658 static u_char *
768 ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, u_char *tmp, 659 ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, u_char *tmp,
912 "http2:%ui create HEADERS frame %p: len:%uz", 803 "http2:%ui create HEADERS frame %p: len:%uz",
913 stream->node->id, frame, frame->length); 804 stream->node->id, frame, frame->length);
914 805
915 return frame; 806 return frame;
916 } 807 }
808 }
809
810
811 static ngx_http_v2_out_frame_t *
812 ngx_http_v2_create_trailers_frame(ngx_http_request_t *r)
813 {
814 u_char *pos, *start, *tmp;
815 size_t len, tmp_len;
816 ngx_uint_t i;
817 ngx_list_part_t *part;
818 ngx_table_elt_t *header;
819 ngx_connection_t *fc;
820
821 fc = r->connection;
822 len = 0;
823 tmp_len = 0;
824
825 part = &r->headers_out.trailers.part;
826 header = part->elts;
827
828 for (i = 0; /* void */; i++) {
829
830 if (i >= part->nelts) {
831 if (part->next == NULL) {
832 break;
833 }
834
835 part = part->next;
836 header = part->elts;
837 i = 0;
838 }
839
840 if (header[i].hash == 0) {
841 continue;
842 }
843
844 if (header[i].key.len > NGX_HTTP_V2_MAX_FIELD) {
845 ngx_log_error(NGX_LOG_CRIT, fc->log, 0,
846 "too long response trailer name: \"%V\"",
847 &header[i].key);
848 return NULL;
849 }
850
851 if (header[i].value.len > NGX_HTTP_V2_MAX_FIELD) {
852 ngx_log_error(NGX_LOG_CRIT, fc->log, 0,
853 "too long response trailer value: \"%V: %V\"",
854 &header[i].key, &header[i].value);
855 return NULL;
856 }
857
858 len += 1 + NGX_HTTP_V2_INT_OCTETS + header[i].key.len
859 + NGX_HTTP_V2_INT_OCTETS + header[i].value.len;
860
861 if (header[i].key.len > tmp_len) {
862 tmp_len = header[i].key.len;
863 }
864
865 if (header[i].value.len > tmp_len) {
866 tmp_len = header[i].value.len;
867 }
868 }
869
870 if (len == 0) {
871 return NGX_HTTP_V2_NO_TRAILERS;
872 }
873
874 tmp = ngx_palloc(r->pool, tmp_len);
875 pos = ngx_pnalloc(r->pool, len);
876
877 if (pos == NULL || tmp == NULL) {
878 return NULL;
879 }
880
881 start = pos;
882
883 part = &r->headers_out.trailers.part;
884 header = part->elts;
885
886 for (i = 0; /* void */; i++) {
887
888 if (i >= part->nelts) {
889 if (part->next == NULL) {
890 break;
891 }
892
893 part = part->next;
894 header = part->elts;
895 i = 0;
896 }
897
898 if (header[i].hash == 0) {
899 continue;
900 }
901
902 #if (NGX_DEBUG)
903 if (fc->log->log_level & NGX_LOG_DEBUG_HTTP) {
904 ngx_strlow(tmp, header[i].key.data, header[i].key.len);
905
906 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, fc->log, 0,
907 "http2 output trailer: \"%*s: %V\"",
908 header[i].key.len, tmp, &header[i].value);
909 }
910 #endif
911
912 *pos++ = 0;
913
914 pos = ngx_http_v2_write_name(pos, header[i].key.data,
915 header[i].key.len, tmp);
916
917 pos = ngx_http_v2_write_value(pos, header[i].value.data,
918 header[i].value.len, tmp);
919 }
920
921 return ngx_http_v2_create_headers_frame(r, start, pos, 1);
917 } 922 }
918 923
919 924
920 static ngx_chain_t * 925 static ngx_chain_t *
921 ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) 926 ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit)
1238 return frame; 1243 return frame;
1239 } 1244 }
1240 1245
1241 1246
1242 static ngx_inline ngx_int_t 1247 static ngx_inline ngx_int_t
1243 ngx_http_v2_filter_send(ngx_connection_t *fc, ngx_http_v2_stream_t *stream)
1244 {
1245 stream->blocked = 1;
1246
1247 if (ngx_http_v2_send_output_queue(stream->connection) == NGX_ERROR) {
1248 fc->error = 1;
1249 return NGX_ERROR;
1250 }
1251
1252 stream->blocked = 0;
1253
1254 if (stream->queued) {
1255 fc->buffered |= NGX_HTTP_V2_BUFFERED;
1256 fc->write->active = 1;
1257 fc->write->ready = 0;
1258 return NGX_AGAIN;
1259 }
1260
1261 fc->buffered &= ~NGX_HTTP_V2_BUFFERED;
1262
1263 return NGX_OK;
1264 }
1265
1266
1267 static ngx_inline ngx_int_t
1268 ngx_http_v2_flow_control(ngx_http_v2_connection_t *h2c, 1248 ngx_http_v2_flow_control(ngx_http_v2_connection_t *h2c,
1269 ngx_http_v2_stream_t *stream) 1249 ngx_http_v2_stream_t *stream)
1270 { 1250 {
1271 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, 1251 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
1272 "http2:%ui windows: conn:%uz stream:%z", 1252 "http2:%ui windows: conn:%uz stream:%z",
1314 } 1294 }
1315 1295
1316 ngx_queue_insert_after(q, &stream->queue); 1296 ngx_queue_insert_after(q, &stream->queue);
1317 } 1297 }
1318 1298
1299
1300 static ngx_inline ngx_int_t
1301 ngx_http_v2_filter_send(ngx_connection_t *fc, ngx_http_v2_stream_t *stream)
1302 {
1303 stream->blocked = 1;
1304
1305 if (ngx_http_v2_send_output_queue(stream->connection) == NGX_ERROR) {
1306 fc->error = 1;
1307 return NGX_ERROR;
1308 }
1309
1310 stream->blocked = 0;
1311
1312 if (stream->queued) {
1313 fc->buffered |= NGX_HTTP_V2_BUFFERED;
1314 fc->write->active = 1;
1315 fc->write->ready = 0;
1316 return NGX_AGAIN;
1317 }
1318
1319 fc->buffered &= ~NGX_HTTP_V2_BUFFERED;
1320
1321 return NGX_OK;
1322 }
1319 1323
1320 1324
1321 static ngx_int_t 1325 static ngx_int_t
1322 ngx_http_v2_headers_frame_handler(ngx_http_v2_connection_t *h2c, 1326 ngx_http_v2_headers_frame_handler(ngx_http_v2_connection_t *h2c,
1323 ngx_http_v2_out_frame_t *frame) 1327 ngx_http_v2_out_frame_t *frame)