Opened 5 years ago
Closed 5 years ago
#1957 closed defect (invalid)
http2 window_size
Reported by: | Owned by: | ||
---|---|---|---|
Priority: | minor | Milestone: | |
Component: | nginx-module | Version: | 1.17.x |
Keywords: | Cc: | ||
uname -a: | FreeBSD host 12.1-RELEASE-p3 FreeBSD 12.1-RELEASE-p3 GENERIC amd64 | ||
nginx -V: |
nginx version: nginx/1.17.9
built with OpenSSL 1.1.1d-freebsd 10 Sep 2019 TLS SNI support enabled configure arguments: --prefix=/usr/local/etc/nginx --with-cc-opt='-I /usr/local/include' --with-ld-opt='-L /usr/local/lib' --conf-path=/usr/local/etc/nginx/nginx.conf --sbin-path=/usr/local/sbin/nginx --pid-path=/var/run/nginx.pid --error-log-path=/var/log/nginx/error.log --user=www --group=www --modules-path=/usr/local/libexec/nginx --with-file-aio --http-client-body-temp-path=/var/tmp/nginx/client_body_temp --http-fastcgi-temp-path=/var/tmp/nginx/fastcgi_temp --http-proxy-temp-path=/var/tmp/nginx/proxy_temp --http-scgi-temp-path=/var/tmp/nginx/scgi_temp --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi_temp --http-log-path=/var/log/nginx/access.log --with-http_v2_module --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-pcre --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --without-mail_imap_module --without-mail_pop3_module --without-mail_smtp_module --with-mail_ssl_module --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads --with-mail=dynamic --with-stream=dynamic |
Description
This is tested on both NGINX 1.17 and 1.16 with the same results.
Basically, I'm doing a simple GET request with my HTTP/2 implementation.
Upon connection I'm receiving a SETTINGS frame for an INITIAL_WINDOW_SIZE of 65536, and adjusting the window size accordingly from the default INITIAL_WINDOW_SIZE (65535) by adding the difference between the new and the old value 65535 + (65536 - 65535) = 1, so the new connection window_size is 65536.
Then I'm receiving a WINDOW_UPDATE frame with an INCREMENT of 2147418112. This would increment the connection WINDOW_SIZE to 65536 + 2147418112 = 2147483648 which exceeds by 1 the maximum HTTP/2 allowed window size. So I'm sending a GO_AWAY frame with error FLOW_CONTROL_ERROR.
Client behaviour looks correct to me, so it seems to be an off-by-one in the server HTTP/2 flow control window management.
15:17:57.945 [debug] SENT %Ankh.HTTP2.Frame.Settings{flags: %Ankh.HTTP2.Frame.Settings.Flags{ack: false}, length: 36, payload: %Ankh.HTTP2.Frame.Settings.Payload{settings: [header_table_size: 4096, enable_push: true, max_concurrent_streams: 128, initial_window_size: 65535, max_frame_size: 16384, max_header_list_size: 128]}, stream_id: 0, type: 4} [<<0, 0, 36, 4, 0, 0, 0, 0, 0>>, <<0, 1, 0, 0, 16, 0>>, <<0, 2, 0, 0, 0, 1>>, <<0, 3, 0, 0, 0, 128>>, <<0, 4, 0, 0, 255, 255>>, <<0, 5, 0, 0, 64, 0>>, <<0, 6, 0, 0, 0, 128>>] 15:18:00.055 [debug] STREAM 1 :idle -> :open hbf: nil 15:18:00.055 [debug] SENT %Ankh.HTTP2.Frame.Headers{flags: %Ankh.HTTP2.Frame.Headers.Flags{end_headers: true, end_stream: false, padded: false, priority: false}, length: 17, payload: %Ankh.HTTP2.Frame.Headers.Payload{exclusive: false, hbf: <<132, 135, 65, 140, 241, 227, 194, 242, 142, 164, 140, 131, 66, 87, 50, 127, 130>>, pad_length: 0, stream_dependency: 0, weight: 0}, stream_id: 1, type: 1} [<<0, 0, 17, 1, 4, 0, 0, 0, 1>>, <<132, 135, 65, 140, 241, 227, 194, 242, 142, 164, 140, 131, 66, 87, 50, 127, 130>>] 15:18:00.056 [debug] RECVD %Ankh.HTTP2.Frame.Settings{flags: %Ankh.HTTP2.Frame.Settings.Flags{ack: true}, length: 0, payload: nil, stream_id: 0, type: 4} <<0, 0, 0, 4, 1, 0, 0, 0, 0>> 15:18:00.056 [debug] RECVD %Ankh.HTTP2.Frame.Settings{flags: %Ankh.HTTP2.Frame.Settings.Flags{ack: false}, length: 18, payload: %Ankh.HTTP2.Frame.Settings.Payload{settings: [max_frame_size: 16777215, initial_window_size: 65536, max_concurrent_streams: 128]}, stream_id: 0, type: 4} <<0, 0, 18, 4, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 128, 0, 4, 0, 1, 0, 0, 0, 5, 0, 255, 255, 255>> 15:18:00.056 [debug] SENT %Ankh.HTTP2.Frame.Settings{flags: %Ankh.HTTP2.Frame.Settings.Flags{ack: true}, length: 0, payload: nil, stream_id: 0, type: 4} [<<0, 0, 0, 4, 1, 0, 0, 0, 0>>] 15:18:00.056 [debug] window_size: 65535 + (65536 - 65535) = 65536 15:18:00.056 [debug] STREAM 1 window_size: 65535 + (65536 - 65535) = 65536 15:18:00.056 [debug] RECVD %Ankh.HTTP2.Frame.WindowUpdate{flags: nil, length: 4, payload: %Ankh.HTTP2.Frame.WindowUpdate.Payload{increment: 2147418112}, stream_id: 0, type: 8} <<0, 0, 4, 8, 0, 0, 0, 0, 0, 127, 255, 0, 0>> 15:18:00.057 [debug] SENT %Ankh.HTTP2.Frame.GoAway{flags: nil, length: 8, payload: %Ankh.HTTP2.Frame.GoAway.Payload{data: "", error_code: :flow_control_error, last_stream_id: 0}, stream_id: 0, type: 7} [<<0, 0, 8, 7, 0, 0, 0, 0, 0>>, <<0, 0, 0, 0>>, <<0, 0, 0, 3>>, ""]
Hi Luca,
Thank you for your report!
Please see RFC 7540, Section 6.5.2. Defined SETTINGS Parameters:
Please see RFC 7540, Section 6.9. WINDOW_UPDATE:
So, you mixed stream-level and connection-level flow control.