diff options
author | Viktor Söderqvist <[email protected]> | 2022-05-12 23:37:49 +0200 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2022-12-06 16:47:40 +0100 |
commit | c1f9122ab2a646df9182e51e3181de6ffa71af0c (patch) | |
tree | f51cf3f1374745eddbdaf712f400156371772825 /test | |
parent | f9b886e52493740f297a7091387f2e492d8f50f3 (diff) | |
download | gun-c1f9122ab2a646df9182e51e3181de6ffa71af0c.tar.gz gun-c1f9122ab2a646df9182e51e3181de6ffa71af0c.tar.bz2 gun-c1f9122ab2a646df9182e51e3181de6ffa71af0c.zip |
Add keepalive_tolerance http2 option
The number of unacknowledged pings that can be tolerated
before the connection is forcefully closed.
When a keepalive ping is sent to the peer, a counter is
incremented and if this counter exceeds the tolerance limit,
the connection is forcefully closed. The counter is
decremented whenever a ping ack is received from the peer.
By default, the mechanism for closing the connection based
on ping and ping ack is disabled.
Loïc Hoguin: I have edited a lot of the code and renamed
a few things as well as simplified the docs and increased
test timeouts to avoid race conditions.
Diffstat (limited to 'test')
-rw-r--r-- | test/rfc7540_SUITE.erl | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/test/rfc7540_SUITE.erl b/test/rfc7540_SUITE.erl index 159d036..a494128 100644 --- a/test/rfc7540_SUITE.erl +++ b/test/rfc7540_SUITE.erl @@ -435,6 +435,60 @@ settings_ack_timeout(_) -> timer:sleep(6000), gun:close(ConnPid). +keepalive_tolerance_ping_ack_timeout(_) -> + doc("The PING frame may be used to easily test a connection. (RFC7540 8.1.4)"), + {ok, OriginPid, OriginPort} = init_origin(tcp, http2, do_ping_ack_loop_fun()), + {ok, Pid} = gun:open("localhost", OriginPort, #{ + protocols => [http2], + http2_opts => #{keepalive => 100, keepalive_tolerance => 2} + }), + {ok, http2} = gun:await_up(Pid), + handshake_completed = receive_from(OriginPid), + %% When Gun sends the first ping, the server acks immediately. + receive ping_received -> OriginPid ! send_ping_ack end, + timer:sleep(250), %% Gun sends 2 pings while we sleep. 2 pings not acked. + %% Server acks one ping. One ping still not acked. + receive ping_received -> OriginPid ! send_ping_ack end, + timer:sleep(100), %% Gun sends 1 ping while we sleep. 2 pings not acked. + %% Server acks one ping. One ping still not acked. + receive ping_received -> OriginPid ! send_ping_ack end, + timer:sleep(100), %% Gun sends 1 ping while we sleep. 2 pings not acked. + %% Check that we haven't received a gun_down yet. + receive + GunDown when element(1, GunDown) =:= gun_down -> + error(unexpected) + after 0 -> + ok + end, + %% Within the next 10ms, Gun wants to send another ping, which would + %% result in 3 outstanding pings. Instead, Gun goes down. + receive + {gun_down, Pid, http2, {error, {connection_error, no_error, _}}, []} -> + gun:close(Pid) + after 100 -> + error(timeout) + end. + +do_ping_ack_loop_fun() -> + %% Receive ping, sync with parent, send ping ack, loop. + fun Loop(Parent, Socket, Transport) -> + {ok, Data} = Transport:recv(Socket, 9, infinity), + <<Len:24, 6:8, %% PING + 0:8, %% Flags + 0:1, 0:31>> = Data, + {ok, Payload} = Transport:recv(Socket, Len, 1000), + 8 = Len = byte_size(Payload), + Parent ! ping_received, + receive + send_ping_ack -> + Ack = <<8:24, 6:8, %% PING + 1:8, %% Ack flag + 0:1, 0:31, Payload/binary>>, + ok = Transport:send(Socket, Ack) + end, + Loop(Parent, Socket, Transport) + end. + connect_http_via_h2c(_) -> doc("CONNECT can be used to establish a TCP connection " "to an HTTP/1.1 server via a TCP HTTP/2 proxy. (RFC7540 8.3)"), |