%% This module echoes client events back, %% including creating new streams. -module(wt_echo_h). %% @todo -behavior(cowboy_webtransport). -export([init/2]). -export([webtransport_handle/2]). -export([webtransport_info/2]). init(Req0, _) -> Req = case cowboy_req:parse_header(<<"wt-available-protocols">>, Req0) of undefined -> Req0; [Protocol|_] -> cowboy_req:set_resp_header(<<"wt-protocol">>, Protocol, Req0) end, {cowboy_webtransport, Req, #{}}. %% @todo WT handle {stream_open,4,bidi} webtransport_handle(Event = {stream_open, StreamID, bidi}, Streams) -> ct:pal("WT handle ~p~n", [Event]), {[], Streams#{StreamID => bidi}}; webtransport_handle(Event = {stream_open, StreamID, unidi}, Streams) -> ct:pal("WT handle ~p~n", [Event]), OpenStreamRef = make_ref(), {[{open_stream, OpenStreamRef, unidi, <<>>}], Streams#{ StreamID => {unidi_remote, OpenStreamRef}, OpenStreamRef => {unidi_local, StreamID}}}; webtransport_handle(Event = {opened_stream_id, OpenStreamRef, OpenStreamID}, Streams) -> ct:pal("WT handle ~p~n", [Event]), case Streams of #{OpenStreamRef := bidi} -> {[], maps:remove(OpenStreamRef, Streams#{ OpenStreamID => bidi })}; #{OpenStreamRef := {unidi_local, RemoteStreamID}} -> #{RemoteStreamID := {unidi_remote, OpenStreamRef}} = Streams, {[], maps:remove(OpenStreamRef, Streams#{ RemoteStreamID => {unidi_remote, OpenStreamID}, OpenStreamID => {unidi_local, RemoteStreamID} })} end; webtransport_handle(Event = {stream_data, _StreamID, _IsFin, <<"TEST:", Test/bits>>}, Streams) -> ct:pal("WT handle ~p~n", [Event]), case Test of <<"open_bidi">> -> OpenStreamRef = make_ref(), {[{open_stream, OpenStreamRef, bidi, <<>>}], Streams#{OpenStreamRef => bidi}}; <<"initiate_close">> -> {[initiate_close], Streams}; <<"close">> -> {[close], Streams} end; webtransport_handle(Event = {stream_data, StreamID, IsFin, Data}, Streams) -> ct:pal("WT handle ~p~n", [Event]), case Streams of #{StreamID := bidi} -> {[{send, StreamID, IsFin, Data}], Streams}; #{StreamID := {unidi_remote, Ref}} when is_reference(Ref) -> %% The stream isn't ready. We try again later. erlang:send_after(100, self(), {try_again, Event}), {[], Streams}; #{StreamID := {unidi_remote, LocalStreamID}} -> {[{send, LocalStreamID, IsFin, Data}], Streams} end; webtransport_handle(Event = {datagram, Data}, Streams) -> ct:pal("WT handle ~p~n", [Event]), {[{send, datagram, Data}], Streams}; webtransport_handle(Event = close_initiated, Streams) -> ct:pal("WT handle ~p~n", [Event]), {[{send, datagram, <<"TEST:close_initiated">>}], Streams}; webtransport_handle(Event, Streams) -> ct:pal("WT handle ignore ~p~n", [Event]), {[], Streams}. webtransport_info({try_again, Event}, Streams) -> ct:pal("try_again ~p", [Event]), webtransport_handle(Event, Streams).