aboutsummaryrefslogtreecommitdiffstats
path: root/test/rfc7540_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'test/rfc7540_SUITE.erl')
-rw-r--r--test/rfc7540_SUITE.erl54
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)"),