diff --git a/src/cowboy_http3.erl b/src/cowboy_http3.erl index 21729073..2fbe9316 100644 --- a/src/cowboy_http3.erl +++ b/src/cowboy_http3.erl @@ -258,10 +258,10 @@ parse1(State=#state{http3_machine=HTTP3Machine0}, %% @todo Handle when IsFin = fin which must terminate the WT session. parse1(State, Stream=#stream{id=SessionID, status=webtransport_session}, Data, IsFin) -> case cow_capsule:parse(Data) of - {ok, drain_wt_session, Rest} -> + {ok, wt_drain_session, Rest} -> webtransport_event(State, SessionID, close_initiated), parse1(State, Stream, Rest, IsFin); - {ok, {close_wt_session, AppCode, AppMsg}, Rest} -> + {ok, {wt_close_session, AppCode, AppMsg}, Rest} -> %% This event will be handled specially and lead %% to the termination of the session process. webtransport_event(State, SessionID, {closed, AppCode, AppMsg}), @@ -969,9 +969,9 @@ wt_commands(State=#state{conn=Conn}, Session, [{send, StreamID, IsFin, Data}|Tai %% @todo Handle errors. end; wt_commands(State=#state{conn=Conn}, Session=#stream{id=SessionID}, [initiate_close|Tail]) -> - %% We must send a DRAIN_WEBTRANSPORT_SESSION capsule on the CONNECT stream. + %% We must send a WT_DRAIN_SESSION capsule on the CONNECT stream. %% @todo I don't think capsules should go over stream handlers. - Capsule = cow_capsule:drain_wt_session(), + Capsule = cow_capsule:wt_drain_session(), case cowboy_quicer:send(Conn, SessionID, Capsule, nofin) of ok -> wt_commands(State, Session, Tail) @@ -979,13 +979,13 @@ wt_commands(State=#state{conn=Conn}, Session=#stream{id=SessionID}, [initiate_cl end; wt_commands(State0=#state{conn=Conn}, Session=#stream{id=SessionID}, [Cmd|Tail]) when Cmd =:= close; element(1, Cmd) =:= close -> - %% We must send a CLOSE_WEBTRANSPORT_SESSION capsule on the CONNECT stream. + %% We must send a WT_CLOSE_SESSION capsule on the CONNECT stream. {AppCode, AppMsg} = case Cmd of close -> {0, <<>>}; {close, AppCode0} -> {AppCode0, <<>>}; {close, AppCode0, AppMsg0} -> {AppCode0, AppMsg0} end, - Capsule = cow_capsule:close_wt_session(AppCode, AppMsg), + Capsule = cow_capsule:wt_close_session(AppCode, AppMsg), case cowboy_quicer:send(Conn, SessionID, Capsule, fin) of ok -> %% @todo The endpoint MAY send a STOP_SENDING to indicate it is no longer reading from the CONNECT stream. diff --git a/test/draft_h3_webtransport_SUITE.erl b/test/draft_h3_webtransport_SUITE.erl index d962a2f0..756ec1b1 100644 --- a/test/draft_h3_webtransport_SUITE.erl +++ b/test/draft_h3_webtransport_SUITE.erl @@ -273,7 +273,7 @@ datagrams(Config) -> % {datagram, SessionID, <<"TEST:close_initiated">>} = do_receive_datagram(Conn), % ok. -drain_wt_session_client(Config) -> +wt_drain_session_client(Config) -> doc("The WT client can initiate the close of a single session. " "(draft_webtrans_http3 4.6)"), %% Connect to the WebTransport server. @@ -282,13 +282,13 @@ drain_wt_session_client(Config) -> connect_stream_ref := ConnectStreamRef, session_id := SessionID } = do_webtransport_connect(Config), - %% Send the DRAIN_WEBTRANSPORT_SESSION capsule on the CONNECT stream. - {ok, _} = quicer:send(ConnectStreamRef, cow_capsule:drain_wt_session()), + %% Send the WT_DRAIN_SESSION capsule on the CONNECT stream. + {ok, _} = quicer:send(ConnectStreamRef, cow_capsule:wt_drain_session()), %% Receive a datagram indicating processing by the WT handler. {datagram, SessionID, <<"TEST:close_initiated">>} = do_receive_datagram(Conn), ok. -drain_wt_session_server(Config) -> +wt_drain_session_server(Config) -> doc("The WT server can initiate the close of a single session. " "(draft_webtrans_http3 4.6)"), %% Connect to the WebTransport server. @@ -300,12 +300,12 @@ drain_wt_session_server(Config) -> %% Create a bidi stream, send a special instruction to make it initiate the close. {ok, LocalStreamRef} = quicer:start_stream(Conn, #{}), {ok, _} = quicer:send(LocalStreamRef, <<1:2, 16#41:14, 0:2, SessionID:6, "TEST:initiate_close">>), - %% Receive the DRAIN_WEBTRANSPORT_SESSION capsule on the CONNECT stream. - DrainWTSessionCapsule = cow_capsule:drain_wt_session(), + %% Receive the WT_DRAIN_SESSION capsule on the CONNECT stream. + DrainWTSessionCapsule = cow_capsule:wt_drain_session(), {nofin, DrainWTSessionCapsule} = do_receive_data(ConnectStreamRef), ok. -drain_wt_session_continue_client(Config) -> +wt_drain_session_continue_client(Config) -> doc("After the WT client has initiated the close of the session, " "both client and server can continue using the session and " "open new streams. (draft_webtrans_http3 4.6)"), @@ -315,8 +315,8 @@ drain_wt_session_continue_client(Config) -> connect_stream_ref := ConnectStreamRef, session_id := SessionID } = do_webtransport_connect(Config), - %% Send the DRAIN_WEBTRANSPORT_SESSION capsule on the CONNECT stream. - {ok, _} = quicer:send(ConnectStreamRef, cow_capsule:drain_wt_session()), + %% Send the WT_DRAIN_SESSION capsule on the CONNECT stream. + {ok, _} = quicer:send(ConnectStreamRef, cow_capsule:wt_drain_session()), %% Receive a datagram indicating processing by the WT handler. {datagram, SessionID, <<"TEST:close_initiated">>} = do_receive_datagram(Conn), %% Create a new bidi stream, send Hello, get Hello back. @@ -325,7 +325,7 @@ drain_wt_session_continue_client(Config) -> {nofin, <<"Hello">>} = do_receive_data(ContinueStreamRef), ok. -drain_wt_session_continue_server(Config) -> +wt_drain_session_continue_server(Config) -> doc("After the WT server has initiated the close of the session, " "both client and server can continue using the session and " "open new streams. (draft_webtrans_http3 4.6)"), @@ -338,8 +338,8 @@ drain_wt_session_continue_server(Config) -> %% Create a bidi stream, send a special instruction to make it initiate the close. {ok, LocalStreamRef} = quicer:start_stream(Conn, #{}), {ok, _} = quicer:send(LocalStreamRef, <<1:2, 16#41:14, 0:2, SessionID:6, "TEST:initiate_close">>), - %% Receive the DRAIN_WEBTRANSPORT_SESSION capsule on the CONNECT stream. - DrainWTSessionCapsule = cow_capsule:drain_wt_session(), + %% Receive the WT_DRAIN_SESSION capsule on the CONNECT stream. + DrainWTSessionCapsule = cow_capsule:wt_drain_session(), {nofin, DrainWTSessionCapsule} = do_receive_data(ConnectStreamRef), %% Create a new bidi stream, send Hello, get Hello back. {ok, ContinueStreamRef} = quicer:start_stream(Conn, #{}), @@ -427,18 +427,18 @@ drain_wt_session_continue_server(Config) -> %% A WebTransport session over HTTP/3 is considered terminated when either of the following conditions is met: %% * the CONNECT stream is closed, either cleanly or abruptly, on either side; or -%% * a CLOSE_WEBTRANSPORT_SESSION capsule is either sent or received. +%% * a WT_CLOSE_SESSION capsule is either sent or received. %% (6) -close_wt_session_client(Config) -> +wt_close_session_client(Config) -> doc("The WT client can close a single session. (draft_webtrans_http3 4.6)"), %% Connect to the WebTransport server. #{ connect_stream_ref := ConnectStreamRef } = do_webtransport_connect(Config), - %% Send the CLOSE_WEBTRANSPORT_SESSION capsule on the CONNECT stream. + %% Send the WT_CLOSE_SESSION capsule on the CONNECT stream. {ok, _} = quicer:send(ConnectStreamRef, - cow_capsule:close_wt_session(0, <<>>), + cow_capsule:wt_close_session(0, <<>>), ?QUIC_SEND_FLAG_FIN), %% Normally we should also stop reading but in order to detect %% that the server stops the stream we must not otherwise the @@ -452,7 +452,7 @@ close_wt_session_client(Config) -> error({timeout, waiting_for_stream_closed}) end. -close_wt_session_server(Config) -> +wt_close_session_server(Config) -> doc("The WT server can close a single session. (draft_webtrans_http3 4.6)"), %% Connect to the WebTransport server. #{ @@ -463,8 +463,8 @@ close_wt_session_server(Config) -> %% Create a bidi stream, send a special instruction to make it initiate the close. {ok, LocalStreamRef} = quicer:start_stream(Conn, #{}), {ok, _} = quicer:send(LocalStreamRef, <<1:2, 16#41:14, 0:2, SessionID:6, "TEST:close">>), - %% Receive the CLOSE_WEBTRANSPORT_SESSION capsule on the CONNECT stream. - CloseWTSessionCapsule = cow_capsule:close_wt_session(0, <<>>), + %% Receive the WT_CLOSE_SESSION capsule on the CONNECT stream. + CloseWTSessionCapsule = cow_capsule:wt_close_session(0, <<>>), {fin, CloseWTSessionCapsule} = do_receive_data(ConnectStreamRef), ok. @@ -496,9 +496,9 @@ wt_session_gone_client(Config) -> {nofin, <<1:2, 16#41:14, 0:2, SessionID:6>>} = do_receive_data(RemoteBidiStreamRef), {ok, _} = quicer:send(RemoteBidiStreamRef, <<"Hello">>), {nofin, <<"Hello">>} = do_receive_data(RemoteBidiStreamRef), - %% Send the CLOSE_WEBTRANSPORT_SESSION capsule on the CONNECT stream. + %% Send the WT_CLOSE_SESSION capsule on the CONNECT stream. {ok, _} = quicer:send(ConnectStreamRef, - cow_capsule:close_wt_session(0, <<>>), + cow_capsule:wt_close_session(0, <<>>), ?QUIC_SEND_FLAG_FIN), %% All streams from that WT session have been aborted. #{reason := webtransport_session_gone} = do_wait_stream_aborted(LocalUnidiStreamRef), @@ -538,8 +538,8 @@ wt_session_gone_server(Config) -> %% Send a special instruction to make the server initiate the close. {ok, _} = quicer:send(LocalBidiStreamRef, <<"TEST:close">>), - %% Receive the CLOSE_WEBTRANSPORT_SESSION capsule on the CONNECT stream. - CloseWTSessionCapsule = cow_capsule:close_wt_session(0, <<>>), + %% Receive the WT_CLOSE_SESSION capsule on the CONNECT stream. + CloseWTSessionCapsule = cow_capsule:wt_close_session(0, <<>>), {fin, CloseWTSessionCapsule} = do_receive_data(ConnectStreamRef), %% All streams from that WT session have been aborted. #{reason := webtransport_session_gone} = do_wait_stream_aborted(LocalUnidiStreamRef), @@ -551,7 +551,7 @@ wt_session_gone_server(Config) -> %% Application Error Message: A UTF-8 encoded error message string provided by the application closing the session. The message takes up the remainder of the capsule, and its length MUST NOT exceed 1024 bytes. (6) %% @todo What if it's larger? -close_wt_session_app_code_msg_client(Config) -> +wt_close_session_app_code_msg_client(Config) -> doc("The WT client can close a single session with an application error code " "and an application error message. (draft_webtrans_http3 4.6)"), %% Connect to the WebTransport server. @@ -565,9 +565,9 @@ close_wt_session_app_code_msg_client(Config) -> EventPidBin = term_to_binary(self()), {ok, _} = quicer:send(LocalStreamRef, <<1:2, 16#41:14, 0:2, SessionID:6, "TEST:event_pid:", EventPidBin/binary>>), - %% Send the CLOSE_WEBTRANSPORT_SESSION capsule on the CONNECT stream. + %% Send the WT_CLOSE_SESSION capsule on the CONNECT stream. {ok, _} = quicer:send(ConnectStreamRef, - cow_capsule:close_wt_session(17, <<"seventeen">>), + cow_capsule:wt_close_session(17, <<"seventeen">>), ?QUIC_SEND_FLAG_FIN), %% @todo Stop reading from the CONNECt stream too. (STOP_SENDING) %% Receive the terminate event from the WT handler. @@ -578,7 +578,7 @@ close_wt_session_app_code_msg_client(Config) -> error({timeout, waiting_for_terminate_event}) end. -close_wt_session_app_code_server(Config) -> +wt_close_session_app_code_server(Config) -> doc("The WT server can close a single session with an application error code. " "(draft_webtrans_http3 4.6)"), %% Connect to the WebTransport server. @@ -591,12 +591,12 @@ close_wt_session_app_code_server(Config) -> {ok, LocalStreamRef} = quicer:start_stream(Conn, #{}), {ok, _} = quicer:send(LocalStreamRef, <<1:2, 16#41:14, 0:2, SessionID:6, "TEST:close_app_code">>), - %% Receive the CLOSE_WEBTRANSPORT_SESSION capsule on the CONNECT stream. - CloseWTSessionCapsule = cow_capsule:close_wt_session(1234567890, <<>>), + %% Receive the WT_CLOSE_SESSION capsule on the CONNECT stream. + CloseWTSessionCapsule = cow_capsule:wt_close_session(1234567890, <<>>), {fin, CloseWTSessionCapsule} = do_receive_data(ConnectStreamRef), ok. -close_wt_session_app_code_msg_server(Config) -> +wt_close_session_app_code_msg_server(Config) -> doc("The WT server can close a single session with an application error code " "and an application error message. (draft_webtrans_http3 4.6)"), %% Connect to the WebTransport server. @@ -609,18 +609,18 @@ close_wt_session_app_code_msg_server(Config) -> {ok, LocalStreamRef} = quicer:start_stream(Conn, #{}), {ok, _} = quicer:send(LocalStreamRef, <<1:2, 16#41:14, 0:2, SessionID:6, "TEST:close_app_code_msg">>), - %% Receive the CLOSE_WEBTRANSPORT_SESSION capsule on the CONNECT stream. - CloseWTSessionCapsule = iolist_to_binary(cow_capsule:close_wt_session(1234567890, + %% Receive the WT_CLOSE_SESSION capsule on the CONNECT stream. + CloseWTSessionCapsule = iolist_to_binary(cow_capsule:wt_close_session(1234567890, <<"onetwothreefourfivesixseveneightnineten">>)), {fin, CloseWTSessionCapsule} = do_receive_data(ConnectStreamRef), ok. -%% An endpoint that sends a CLOSE_WEBTRANSPORT_SESSION capsule MUST immediately send a FIN. The endpoint MAY send a STOP_SENDING to indicate it is no longer reading from the CONNECT stream. The recipient MUST either close or reset the stream in response. (6) -%% @todo close_wt_session_server_fin -%% @todo The part about close/reset should be tested in close_wt_session_client. +%% An endpoint that sends a WT_CLOSE_SESSION capsule MUST immediately send a FIN. The endpoint MAY send a STOP_SENDING to indicate it is no longer reading from the CONNECT stream. The recipient MUST either close or reset the stream in response. (6) +%% @todo wt_close_session_server_fin +%% @todo The part about close/reset should be tested in wt_close_session_client. -%% If any additional stream data is received on the CONNECT stream after receiving a CLOSE_WEBTRANSPORT_SESSION capsule, the stream MUST be reset with code H3_MESSAGE_ERROR. (6) -%% @todo close_wt_session_followed_by_data +%% If any additional stream data is received on the CONNECT stream after receiving a WT_CLOSE_SESSION capsule, the stream MUST be reset with code H3_MESSAGE_ERROR. (6) +%% @todo wt_close_session_followed_by_data connect_stream_closed_cleanly_fin(Config) -> doc("The WT client closing the CONNECT stream cleanly "