46 | 46 |
#define NGX_HTTP_V2_FRAME_BUFFER_SIZE 24
|
47 | 47 |
|
48 | 48 |
#define NGX_HTTP_V2_DEFAULT_FRAME_SIZE (1 << 14)
|
49 | |
|
50 | |
#define NGX_HTTP_V2_MAX_WINDOW ((1U << 31) - 1)
|
51 | |
#define NGX_HTTP_V2_DEFAULT_WINDOW 65535
|
52 | |
|
53 | |
#define NGX_HTTP_V2_INITIAL_WINDOW 0
|
54 | 49 |
|
55 | 50 |
#define NGX_HTTP_V2_ROOT (void *) -1
|
56 | 51 |
|
|
878 | 873 |
return ngx_http_v2_state_skip_padded(h2c, pos, end);
|
879 | 874 |
}
|
880 | 875 |
|
881 | |
stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG;
|
882 | |
|
883 | 876 |
h2c->state.stream = stream;
|
884 | 877 |
|
885 | 878 |
return ngx_http_v2_state_read_data(h2c, pos, end);
|
|
890 | 883 |
ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos,
|
891 | 884 |
u_char *end)
|
892 | 885 |
{
|
893 | |
size_t size;
|
894 | |
ngx_int_t rc;
|
895 | |
ngx_uint_t last;
|
896 | |
ngx_http_v2_stream_t *stream;
|
|
886 |
size_t size;
|
|
887 |
ngx_buf_t *buf;
|
|
888 |
ngx_int_t rc;
|
|
889 |
ngx_http_request_t *r;
|
|
890 |
ngx_http_v2_stream_t *stream;
|
|
891 |
ngx_http_v2_srv_conf_t *h2scf;
|
897 | 892 |
|
898 | 893 |
stream = h2c->state.stream;
|
899 | 894 |
|
|
912 | 907 |
|
913 | 908 |
if (size >= h2c->state.length) {
|
914 | 909 |
size = h2c->state.length;
|
915 | |
last = stream->in_closed;
|
916 | |
|
917 | |
} else {
|
918 | |
last = 0;
|
919 | |
}
|
920 | |
|
921 | |
rc = ngx_http_v2_process_request_body(stream->request, pos, size, last);
|
922 | |
|
923 | |
if (rc != NGX_OK) {
|
924 | |
stream->skip_data = 1;
|
925 | |
ngx_http_finalize_request(stream->request, rc);
|
|
910 |
stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG;
|
|
911 |
}
|
|
912 |
|
|
913 |
r = stream->request;
|
|
914 |
|
|
915 |
if (r->request_body) {
|
|
916 |
rc = ngx_http_v2_process_request_body(r, pos, size, stream->in_closed);
|
|
917 |
|
|
918 |
if (rc != NGX_OK) {
|
|
919 |
stream->skip_data = 1;
|
|
920 |
ngx_http_finalize_request(r, rc);
|
|
921 |
}
|
|
922 |
|
|
923 |
} else if (size) {
|
|
924 |
buf = stream->preread;
|
|
925 |
|
|
926 |
if (buf == NULL) {
|
|
927 |
h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module);
|
|
928 |
|
|
929 |
buf = ngx_create_temp_buf(r->pool, h2scf->preread_size);
|
|
930 |
if (buf == NULL) {
|
|
931 |
return ngx_http_v2_connection_error(h2c,
|
|
932 |
NGX_HTTP_V2_INTERNAL_ERROR);
|
|
933 |
}
|
|
934 |
|
|
935 |
stream->preread = buf;
|
|
936 |
}
|
|
937 |
|
|
938 |
if (size > (size_t) (buf->end - buf->last)) {
|
|
939 |
ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0,
|
|
940 |
"http2 preread buffer overflow");
|
|
941 |
return ngx_http_v2_connection_error(h2c,
|
|
942 |
NGX_HTTP_V2_INTERNAL_ERROR);
|
|
943 |
}
|
|
944 |
|
|
945 |
buf->last = ngx_cpymem(buf->last, pos, size);
|
926 | 946 |
}
|
927 | 947 |
|
928 | 948 |
pos += size;
|
|
1057 | 1077 |
goto rst_stream;
|
1058 | 1078 |
}
|
1059 | 1079 |
|
1060 | |
if (!h2c->settings_ack && !(h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG))
|
|
1080 |
if (!h2c->settings_ack
|
|
1081 |
&& !(h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG)
|
|
1082 |
&& h2scf->preread_size < NGX_HTTP_V2_DEFAULT_WINDOW)
|
1061 | 1083 |
{
|
1062 | 1084 |
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
|
1063 | 1085 |
"client sent stream with data "
|
|
2433 | 2455 |
|
2434 | 2456 |
buf->last = ngx_http_v2_write_uint16(buf->last,
|
2435 | 2457 |
NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING);
|
2436 | |
buf->last = ngx_http_v2_write_uint32(buf->last,
|
2437 | |
NGX_HTTP_V2_INITIAL_WINDOW);
|
|
2458 |
buf->last = ngx_http_v2_write_uint32(buf->last, h2scf->preread_size);
|
2438 | 2459 |
|
2439 | 2460 |
buf->last = ngx_http_v2_write_uint16(buf->last,
|
2440 | 2461 |
NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING);
|
|
2642 | 2663 |
ngx_http_log_ctx_t *ctx;
|
2643 | 2664 |
ngx_http_request_t *r;
|
2644 | 2665 |
ngx_http_v2_stream_t *stream;
|
|
2666 |
ngx_http_v2_srv_conf_t *h2scf;
|
2645 | 2667 |
ngx_http_core_srv_conf_t *cscf;
|
2646 | 2668 |
|
2647 | 2669 |
fc = h2c->free_fake_connections;
|
|
2755 | 2777 |
stream->request = r;
|
2756 | 2778 |
stream->connection = h2c;
|
2757 | 2779 |
|
|
2780 |
h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module);
|
|
2781 |
|
2758 | 2782 |
stream->send_window = h2c->init_window;
|
2759 | |
stream->recv_window = NGX_HTTP_V2_INITIAL_WINDOW;
|
|
2783 |
stream->recv_window = h2scf->preread_size;
|
2760 | 2784 |
|
2761 | 2785 |
h2c->processing++;
|
2762 | 2786 |
|
|
3410 | 3434 |
ngx_http_client_body_handler_pt post_handler)
|
3411 | 3435 |
{
|
3412 | 3436 |
off_t len;
|
|
3437 |
size_t size;
|
|
3438 |
ngx_buf_t *buf;
|
|
3439 |
ngx_int_t rc;
|
3413 | 3440 |
ngx_http_v2_stream_t *stream;
|
|
3441 |
ngx_http_v2_srv_conf_t *h2scf;
|
3414 | 3442 |
ngx_http_request_body_t *rb;
|
3415 | 3443 |
ngx_http_core_loc_conf_t *clcf;
|
3416 | 3444 |
ngx_http_v2_connection_t *h2c;
|
|
3443 | 3471 |
|
3444 | 3472 |
r->request_body = rb;
|
3445 | 3473 |
|
|
3474 |
h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module);
|
3446 | 3475 |
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
3447 | 3476 |
|
3448 | 3477 |
len = r->headers_in.content_length_n;
|
3449 | 3478 |
|
3450 | 3479 |
if (r->request_body_no_buffering && !stream->in_closed) {
|
3451 | |
r->request_body_in_file_only = 0;
|
3452 | 3480 |
|
3453 | 3481 |
if (len < 0 || len > (off_t) clcf->client_body_buffer_size) {
|
3454 | 3482 |
len = clcf->client_body_buffer_size;
|
3455 | 3483 |
}
|
3456 | 3484 |
|
|
3485 |
/*
|
|
3486 |
* We need a room to store data up to the stream's initial window size,
|
|
3487 |
* at least until this window will be exhausted.
|
|
3488 |
*/
|
|
3489 |
|
|
3490 |
if (len < (off_t) h2scf->preread_size) {
|
|
3491 |
len = h2scf->preread_size;
|
|
3492 |
}
|
|
3493 |
|
3457 | 3494 |
if (len > NGX_HTTP_V2_MAX_WINDOW) {
|
3458 | 3495 |
len = NGX_HTTP_V2_MAX_WINDOW;
|
3459 | 3496 |
}
|
3460 | |
}
|
3461 | |
|
3462 | |
if (len >= 0 && len <= (off_t) clcf->client_body_buffer_size
|
3463 | |
&& !r->request_body_in_file_only)
|
|
3497 |
|
|
3498 |
rb->buf = ngx_create_temp_buf(r->pool, (size_t) len);
|
|
3499 |
|
|
3500 |
} else if (len >= 0 && len <= (off_t) clcf->client_body_buffer_size
|
|
3501 |
&& !r->request_body_in_file_only)
|
3464 | 3502 |
{
|
3465 | 3503 |
rb->buf = ngx_create_temp_buf(r->pool, (size_t) len);
|
3466 | 3504 |
|
|
3477 | 3515 |
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
3478 | 3516 |
}
|
3479 | 3517 |
|
|
3518 |
buf = stream->preread;
|
|
3519 |
|
3480 | 3520 |
if (stream->in_closed) {
|
3481 | 3521 |
r->request_body_no_buffering = 0;
|
|
3522 |
|
|
3523 |
if (buf) {
|
|
3524 |
rc = ngx_http_v2_process_request_body(r, buf->pos,
|
|
3525 |
buf->last - buf->pos, 1);
|
|
3526 |
ngx_pfree(r->pool, buf->start);
|
|
3527 |
return rc;
|
|
3528 |
}
|
|
3529 |
|
3482 | 3530 |
return ngx_http_v2_process_request_body(r, NULL, 0, 1);
|
3483 | 3531 |
}
|
3484 | 3532 |
|
3485 | |
if (len) {
|
3486 | |
if (r->request_body_no_buffering) {
|
3487 | |
stream->recv_window = (size_t) len;
|
3488 | |
|
3489 | |
} else {
|
3490 | |
stream->no_flow_control = 1;
|
3491 | |
stream->recv_window = NGX_HTTP_V2_MAX_WINDOW;
|
3492 | |
}
|
3493 | |
|
3494 | |
if (ngx_http_v2_send_window_update(stream->connection, stream->node->id,
|
3495 | |
stream->recv_window)
|
|
3533 |
if (buf) {
|
|
3534 |
rc = ngx_http_v2_process_request_body(r, buf->pos,
|
|
3535 |
buf->last - buf->pos, 0);
|
|
3536 |
|
|
3537 |
ngx_pfree(r->pool, buf->start);
|
|
3538 |
|
|
3539 |
if (rc != NGX_OK) {
|
|
3540 |
stream->skip_data = 1;
|
|
3541 |
return rc;
|
|
3542 |
}
|
|
3543 |
}
|
|
3544 |
|
|
3545 |
if (r->request_body_no_buffering) {
|
|
3546 |
size = len - h2scf->preread_size;
|
|
3547 |
|
|
3548 |
} else {
|
|
3549 |
stream->no_flow_control = 1;
|
|
3550 |
size = NGX_HTTP_V2_MAX_WINDOW - stream->recv_window;
|
|
3551 |
}
|
|
3552 |
|
|
3553 |
if (size) {
|
|
3554 |
if (ngx_http_v2_send_window_update(stream->connection,
|
|
3555 |
stream->node->id, size)
|
3496 | 3556 |
== NGX_ERROR)
|
3497 | 3557 |
{
|
3498 | 3558 |
stream->skip_data = 1;
|
|
3507 | 3567 |
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
3508 | 3568 |
}
|
3509 | 3569 |
}
|
3510 | |
}
|
3511 | |
|
3512 | |
ngx_add_timer(r->connection->read, clcf->client_body_timeout);
|
|
3570 |
|
|
3571 |
stream->recv_window += size;
|
|
3572 |
}
|
|
3573 |
|
|
3574 |
if (!buf) {
|
|
3575 |
ngx_add_timer(r->connection->read, clcf->client_body_timeout);
|
|
3576 |
}
|
3513 | 3577 |
|
3514 | 3578 |
r->read_event_handler = ngx_http_v2_read_client_request_body_handler;
|
3515 | 3579 |
r->write_event_handler = ngx_http_request_empty_handler;
|
|
3528 | 3592 |
ngx_http_request_body_t *rb;
|
3529 | 3593 |
ngx_http_core_loc_conf_t *clcf;
|
3530 | 3594 |
|
|
3595 |
fc = r->connection;
|
3531 | 3596 |
rb = r->request_body;
|
3532 | |
|
3533 | |
if (rb == NULL) {
|
3534 | |
return NGX_OK;
|
3535 | |
}
|
3536 | |
|
3537 | |
fc = r->connection;
|
3538 | 3597 |
buf = rb->buf;
|
3539 | 3598 |
|
3540 | 3599 |
if (size) {
|
|
3788 | 3847 |
window -= h2c->state.length;
|
3789 | 3848 |
}
|
3790 | 3849 |
|
3791 | |
if (window == stream->recv_window) {
|
|
3850 |
if (window <= stream->recv_window) {
|
|
3851 |
if (window < stream->recv_window) {
|
|
3852 |
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
|
3853 |
"http2 negative window update");
|
|
3854 |
stream->skip_data = 1;
|
|
3855 |
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
|
3856 |
}
|
|
3857 |
|
3792 | 3858 |
return NGX_AGAIN;
|
3793 | 3859 |
}
|
3794 | 3860 |
|