mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 12:20:24 +00:00
WIP fixes for Chromium
This commit is contained in:
parent
ee534f4e2b
commit
46c53cd4fb
6 changed files with 94 additions and 7 deletions
|
@ -95,8 +95,12 @@ start_quic(Ref, TransOpts, ProtoOpts) ->
|
||||||
end,
|
end,
|
||||||
SocketOpts = [
|
SocketOpts = [
|
||||||
{alpn, ["h3"]}, %% @todo Why not binary?
|
{alpn, ["h3"]}, %% @todo Why not binary?
|
||||||
{peer_unidi_stream_count, 3}, %% We only need control and QPACK enc/dec.
|
{peer_unidi_stream_count, 100}, %% We only need control and QPACK enc/dec.
|
||||||
{peer_bidi_stream_count, 100}
|
{peer_bidi_stream_count, 100},
|
||||||
|
%% For WebTransport. @todo Also increase default unidi stream count.
|
||||||
|
%% @todo We probably don't want it enabled if WT isn't used.
|
||||||
|
{datagram_send_enabled, 1},
|
||||||
|
{datagram_receive_enabled, 1}
|
||||||
|SocketOpts2],
|
|SocketOpts2],
|
||||||
_ListenerPid = spawn(fun() ->
|
_ListenerPid = spawn(fun() ->
|
||||||
{ok, Listener} = quicer:listen(Port, SocketOpts),
|
{ok, Listener} = quicer:listen(Port, SocketOpts),
|
||||||
|
|
|
@ -716,9 +716,10 @@ commands(State, Stream, [Error = {internal_error, _, _}|_Tail]) ->
|
||||||
reset_stream(State, Stream, Error);
|
reset_stream(State, Stream, Error);
|
||||||
%% Use a different protocol within the stream (CONNECT :protocol).
|
%% Use a different protocol within the stream (CONNECT :protocol).
|
||||||
%% @todo Make sure we error out when the feature is disabled.
|
%% @todo Make sure we error out when the feature is disabled.
|
||||||
commands(State0=#state{http3_machine=HTTP3Machine0}, Stream0=#stream{id=StreamID},
|
commands(State0, Stream0=#stream{id=StreamID},
|
||||||
[{switch_protocol, Headers, cowboy_webtransport, WTState=#{}}|Tail]) ->
|
[{switch_protocol, Headers, cowboy_webtransport, WTState=#{}}|Tail]) ->
|
||||||
State = info(stream_store(State0, Stream0), StreamID, {headers, 200, Headers}),
|
State = info(stream_store(State0, Stream0), StreamID, {headers, 200, Headers}),
|
||||||
|
#state{http3_machine=HTTP3Machine0} = State,
|
||||||
Stream1 = #stream{state=StreamState} = stream_get(State, StreamID),
|
Stream1 = #stream{state=StreamState} = stream_get(State, StreamID),
|
||||||
%% The stream becomes a WT session at that point. It is the
|
%% The stream becomes a WT session at that point. It is the
|
||||||
%% parent stream of all streams in this WT session. The
|
%% parent stream of all streams in this WT session. The
|
||||||
|
@ -864,7 +865,7 @@ webtransport_event(State, SessionID, Event) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
webtransport_commands(State, SessionID, Commands) ->
|
webtransport_commands(State, SessionID, Commands) ->
|
||||||
Session = #stream{status=webtransport_session} = stream_get(SessionID, State),
|
Session = #stream{status=webtransport_session} = stream_get(State, SessionID),
|
||||||
wt_commands(State, Session, Commands).
|
wt_commands(State, Session, Commands).
|
||||||
|
|
||||||
wt_commands(State, _, []) ->
|
wt_commands(State, _, []) ->
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
-export_type([opts/0]).
|
-export_type([opts/0]).
|
||||||
|
|
||||||
-record(state, {
|
-record(state, {
|
||||||
|
id :: cow_http3:stream_id(),
|
||||||
parent :: pid(),
|
parent :: pid(),
|
||||||
opts = #{} :: opts(),
|
opts = #{} :: opts(),
|
||||||
handler :: module(),
|
handler :: module(),
|
||||||
|
@ -72,7 +73,7 @@ upgrade(Req=#{version := 'HTTP/3', pid := Pid, streamid := StreamID}, Env, Handl
|
||||||
FilterFun -> FilterFun(Req)
|
FilterFun -> FilterFun(Req)
|
||||||
end,
|
end,
|
||||||
%% @todo add parent, ref, streamid here directly
|
%% @todo add parent, ref, streamid here directly
|
||||||
State = #state{parent=Pid, opts=Opts, handler=Handler, req=FilteredReq},
|
State = #state{id=StreamID, parent=Pid, opts=Opts, handler=Handler, req=FilteredReq},
|
||||||
|
|
||||||
%% @todo Must check is_upgrade_request (rename, not an upgrade)
|
%% @todo Must check is_upgrade_request (rename, not an upgrade)
|
||||||
%% and also ensure that all the relevant settings are enabled (quic and h3)
|
%% and also ensure that all the relevant settings are enabled (quic and h3)
|
||||||
|
@ -179,8 +180,8 @@ handler_call_result(State0, HandlerState, Commands) ->
|
||||||
|
|
||||||
commands([], State, []) ->
|
commands([], State, []) ->
|
||||||
{ok, State};
|
{ok, State};
|
||||||
commands([], State=#state{parent=Pid}, Commands) ->
|
commands([], State=#state{id=SessionID, parent=Pid}, Commands) ->
|
||||||
Pid ! {'$webtransport_commands', lists:reverse(Commands)},
|
Pid ! {'$webtransport_commands', SessionID, lists:reverse(Commands)},
|
||||||
{ok, State};
|
{ok, State};
|
||||||
%% {open_stream, OpenStreamRef, StreamType, InitialData}.
|
%% {open_stream, OpenStreamRef, StreamType, InitialData}.
|
||||||
commands([Command={open_stream, _, _, _}|Tail], State, Acc) ->
|
commands([Command={open_stream, _, _, _}|Tail], State, Acc) ->
|
||||||
|
|
|
@ -53,6 +53,7 @@ init_http3(Ref, ProtoOpts, Config) ->
|
||||||
},
|
},
|
||||||
{ok, Listener} = cowboy:start_quic(Ref, TransOpts, ProtoOpts),
|
{ok, Listener} = cowboy:start_quic(Ref, TransOpts, ProtoOpts),
|
||||||
{ok, {_, Port}} = quicer:sockname(Listener),
|
{ok, {_, Port}} = quicer:sockname(Listener),
|
||||||
|
ct:pal("port ~p", [Port]),
|
||||||
%% @todo Keep listener information around in a better place.
|
%% @todo Keep listener information around in a better place.
|
||||||
persistent_term:put({cowboy_test_quic, Ref}, Listener),
|
persistent_term:put({cowboy_test_quic, Ref}, Listener),
|
||||||
[{ref, Ref}, {type, quic}, {protocol, http3}, {port, Port}, {opts, TransOpts}|Config].
|
[{ref, Ref}, {type, quic}, {protocol, http3}, {port, Port}, {opts, TransOpts}|Config].
|
||||||
|
|
59
test/draft_h3_webtransport_SUITE.erl
Normal file
59
test/draft_h3_webtransport_SUITE.erl
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
%% Copyright (c) Loïc Hoguin <essen@ninenines.eu>
|
||||||
|
%%
|
||||||
|
%% Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
%% purpose with or without fee is hereby granted, provided that the above
|
||||||
|
%% copyright notice and this permission notice appear in all copies.
|
||||||
|
%%
|
||||||
|
%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
-module(draft_h3_webtransport_SUITE).
|
||||||
|
-compile(export_all).
|
||||||
|
-compile(nowarn_export_all).
|
||||||
|
|
||||||
|
-import(ct_helper, [config/2]).
|
||||||
|
-import(ct_helper, [doc/1]).
|
||||||
|
|
||||||
|
all() ->
|
||||||
|
[{group, enabled}].
|
||||||
|
|
||||||
|
groups() ->
|
||||||
|
Tests = ct_helper:all(?MODULE),
|
||||||
|
[{enabled, [], Tests}]. %% @todo Enable parallel when all is better.
|
||||||
|
|
||||||
|
init_per_group(Name = enabled, Config) ->
|
||||||
|
cowboy_test:init_http3(Name, #{
|
||||||
|
enable_connect_protocol => true,
|
||||||
|
h3_datagram => true,
|
||||||
|
enable_webtransport => true, %% For compatibility with draft-02.
|
||||||
|
webtransport_max_sessions => 10,
|
||||||
|
env => #{dispatch => cowboy_router:compile(init_routes(Config))}
|
||||||
|
}, Config).
|
||||||
|
|
||||||
|
end_per_group(Name, _) ->
|
||||||
|
cowboy_test:stop_group(Name).
|
||||||
|
|
||||||
|
init_routes(_) -> [
|
||||||
|
{"localhost", [
|
||||||
|
{"/wt", wt_echo_h, []}
|
||||||
|
]}
|
||||||
|
].
|
||||||
|
|
||||||
|
%% Temporary.
|
||||||
|
|
||||||
|
%% To start Chromium the command line is roughly:
|
||||||
|
%% chromium --ignore-certificate-errors-spki-list=LeLykt63i2FRAm+XO91yBoSjKfrXnAFygqe5xt0zgDA= --ignore-certificate-errors --user-data-dir=/tmp/chromium-wt --allow-insecure-localhost --webtransport-developer-mode --enable-quic https://googlechrome.github.io/samples/webtransport/client.html
|
||||||
|
%%
|
||||||
|
%% To find the SPKI the command is roughly:
|
||||||
|
%% openssl x509 -in ~/ninenines/cowboy/test/rfc9114_SUITE_data/server.pem -pubkey -noout | \
|
||||||
|
%% openssl pkey -pubin -outform der | \
|
||||||
|
%% openssl dgst -sha256 -binary | \
|
||||||
|
%% openssl enc -base64
|
||||||
|
|
||||||
|
run(_Config) ->
|
||||||
|
timer:sleep(infinity).
|
21
test/handlers/wt_echo_h.erl
Normal file
21
test/handlers/wt_echo_h.erl
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
%% 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]).
|
||||||
|
|
||||||
|
init(Req, _) ->
|
||||||
|
{cowboy_webtransport, Req, undefined}.
|
||||||
|
|
||||||
|
%% @todo WT handle {stream_open,4,bidi}
|
||||||
|
%% @todo WT handle {stream_data,4,nofin,<<>>} %% skip?
|
||||||
|
|
||||||
|
webtransport_handle(Event = {stream_data, StreamID, IsFin, Data}, HandlerState) ->
|
||||||
|
ct:pal("WT handle ~p~n", [Event]),
|
||||||
|
{[{send, StreamID, Data}], HandlerState};
|
||||||
|
webtransport_handle(Event, HandlerState) ->
|
||||||
|
ct:pal("WT handle ~p~n", [Event]),
|
||||||
|
{[], HandlerState}.
|
Loading…
Add table
Add a link
Reference in a new issue