comparison src/http/v2/ngx_http_v2.c @ 6495:92464ebace8e

HTTP/2: sending RST_STREAM with NO_ERROR to discard request body. RFC 7540 states that "A server can send a complete response prior to the client sending an entire request if the response does not depend on any portion of the request that has not been sent and received. When this is true, a server MAY request that the client abort transmission of a request without error by sending a RST_STREAM with an error code of NO_ERROR after sending a complete response (i.e., a frame with the END_STREAM flag)." This should prevent a client from blocking on the stream window, since it isn't maintained for closed streams. Currently, quite big initial stream windows are used, so such blocking is very unlikly, but that will be changed in the further patches.
author Valentin Bartenev <vbart@nginx.com>
date Fri, 01 Apr 2016 15:56:03 +0300
parents f01ab2dbcfdc
children 887cca40ba6a
comparison
equal deleted inserted replaced
6494:5805301f990f 6495:92464ebace8e
3707 == NGX_ERROR) 3707 == NGX_ERROR)
3708 { 3708 {
3709 return NGX_ERROR; 3709 return NGX_ERROR;
3710 } 3710 }
3711 3711
3712 stream->out_closed = 1; 3712 stream->rst_sent = 1;
3713 3713
3714 fc = stream->request->connection; 3714 fc = stream->request->connection;
3715 fc->error = 1; 3715 fc->error = 1;
3716 3716
3717 rev = fc->read; 3717 rev = fc->read;
3742 if (stream->queued) { 3742 if (stream->queued) {
3743 fc->write->handler = ngx_http_v2_close_stream_handler; 3743 fc->write->handler = ngx_http_v2_close_stream_handler;
3744 return; 3744 return;
3745 } 3745 }
3746 3746
3747 if (!stream->out_closed) { 3747 if (!stream->rst_sent && !h2c->connection->error) {
3748 if (ngx_http_v2_send_rst_stream(h2c, node->id, 3748
3749 fc->timedout ? NGX_HTTP_V2_PROTOCOL_ERROR 3749 if (!stream->out_closed) {
3750 : NGX_HTTP_V2_INTERNAL_ERROR) 3750 if (ngx_http_v2_send_rst_stream(h2c, node->id,
3751 != NGX_OK) 3751 fc->timedout ? NGX_HTTP_V2_PROTOCOL_ERROR
3752 { 3752 : NGX_HTTP_V2_INTERNAL_ERROR)
3753 h2c->connection->error = 1; 3753 != NGX_OK)
3754 {
3755 h2c->connection->error = 1;
3756 }
3757
3758 } else if (!stream->in_closed) {
3759 if (ngx_http_v2_send_rst_stream(h2c, node->id, NGX_HTTP_V2_NO_ERROR)
3760 != NGX_OK)
3761 {
3762 h2c->connection->error = 1;
3763 }
3754 } 3764 }
3755 } 3765 }
3756 3766
3757 if (h2c->state.stream == stream) { 3767 if (h2c->state.stream == stream) {
3758 h2c->state.stream = NULL; 3768 h2c->state.stream = NULL;
3940 ngx_http_v2_stream_t *stream; 3950 ngx_http_v2_stream_t *stream;
3941 ngx_http_v2_srv_conf_t *h2scf; 3951 ngx_http_v2_srv_conf_t *h2scf;
3942 3952
3943 c = h2c->connection; 3953 c = h2c->connection;
3944 3954
3945 if (h2c->state.stream) {
3946 h2c->state.stream->out_closed = 1;
3947 ngx_http_v2_close_stream(h2c->state.stream, NGX_HTTP_BAD_REQUEST);
3948 }
3949
3950 h2c->blocked = 1; 3955 h2c->blocked = 1;
3951 3956
3952 if (!c->error && ngx_http_v2_send_goaway(h2c, status) != NGX_ERROR) { 3957 if (!c->error && ngx_http_v2_send_goaway(h2c, status) != NGX_ERROR) {
3953 (void) ngx_http_v2_send_output_queue(h2c); 3958 (void) ngx_http_v2_send_output_queue(h2c);
3959 }
3960
3961 c->error = 1;
3962
3963 if (h2c->state.stream) {
3964 ngx_http_v2_close_stream(h2c->state.stream, NGX_HTTP_BAD_REQUEST);
3954 } 3965 }
3955 3966
3956 if (!h2c->processing) { 3967 if (!h2c->processing) {
3957 ngx_http_close_connection(c); 3968 ngx_http_close_connection(c);
3958 return; 3969 return;
3959 } 3970 }
3960 3971
3961 c->error = 1;
3962 c->read->handler = ngx_http_empty_handler; 3972 c->read->handler = ngx_http_empty_handler;
3963 c->write->handler = ngx_http_empty_handler; 3973 c->write->handler = ngx_http_empty_handler;
3964 3974
3965 h2c->last_out = NULL; 3975 h2c->last_out = NULL;
3966 3976