init quic server
This commit is contained in:
parent
2e7e84193c
commit
0f15f1da57
21
apps/sdlan/priv/cert.pem
Normal file
21
apps/sdlan/priv/cert.pem
Normal file
@ -0,0 +1,21 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDazCCAlOgAwIBAgIUEhYvMYhAARHRpKd1EOTR7HiRIVkwDQYJKoZIhvcNAQEL
|
||||
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
|
||||
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNjAyMTEwOTMyMjlaFw0yNzAy
|
||||
MTEwOTMyMjlaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
|
||||
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
|
||||
AQUAA4IBDwAwggEKAoIBAQDWKHFkwDMH/XjY3joBwT3zzgh5WkqG7dKuj7YV7WdX
|
||||
JjOc46iqNsvyieHTfuJBuPirLDAX2hGzU0OheeQBg/a9pFQxxyRBN2UZUFwTHPTG
|
||||
TBBvdQGcC2vMQ3HnJwUoPzJRCYPBXQZ3JSmlq+y1uJzpLQfYeiRtowfGrRrd0jHJ
|
||||
Xt5amitoN7m9VshG7KCg2K8AVriP/X5oiyNJ0s8kVdMFclUNekvWbuxik98VLWbF
|
||||
dcB+kTaFUQkMj7y2ks6b6gWhw1wxPU4kWDEBaQMIICM2nZ+sTSUisKPBqpqlvC8N
|
||||
NFFUhA+QW5SQuTa8t4iUxWsfIeuvPSrb1E1QzPwvld8PAgMBAAGjUzBRMB0GA1Ud
|
||||
DgQWBBRKr5Ulk3xjskqncFCS22VxK2tCmTAfBgNVHSMEGDAWgBRKr5Ulk3xjskqn
|
||||
cFCS22VxK2tCmTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAc
|
||||
p/59bzORWJCKGJJ/GFrBIKKB9F1T1GoKy5rajxZeUCbCL22FaZ6VDmi8uUb4dYBU
|
||||
5bwKOea76+J/cM1/Irt7n8c0d5nhIXm/ZdqERYjtv3F/MPi/X8Q4TP8uY6bA+dJr
|
||||
enDaATGg+Jy2Iq6A6EGhYSmyxabgDkN2MNPtIwyekXoUMrA8D4jBGCQznjS3f1OW
|
||||
9DMpVyb1qoz7WyAftyZkhIcwrBoTZ+C7e7ys9L8Q9uu7dKvdsYoJ73JQn4Rsgk6Y
|
||||
jMGbxn6Td+z9m7aI6oPtY6UlxeA4scepX5Cx610cP0xnGJhf/o13e7jCxnr2/pTD
|
||||
TTtahnT+G0FeQmlUswb9
|
||||
-----END CERTIFICATE-----
|
||||
28
apps/sdlan/priv/key.pem
Normal file
28
apps/sdlan/priv/key.pem
Normal file
@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDWKHFkwDMH/XjY
|
||||
3joBwT3zzgh5WkqG7dKuj7YV7WdXJjOc46iqNsvyieHTfuJBuPirLDAX2hGzU0Oh
|
||||
eeQBg/a9pFQxxyRBN2UZUFwTHPTGTBBvdQGcC2vMQ3HnJwUoPzJRCYPBXQZ3JSml
|
||||
q+y1uJzpLQfYeiRtowfGrRrd0jHJXt5amitoN7m9VshG7KCg2K8AVriP/X5oiyNJ
|
||||
0s8kVdMFclUNekvWbuxik98VLWbFdcB+kTaFUQkMj7y2ks6b6gWhw1wxPU4kWDEB
|
||||
aQMIICM2nZ+sTSUisKPBqpqlvC8NNFFUhA+QW5SQuTa8t4iUxWsfIeuvPSrb1E1Q
|
||||
zPwvld8PAgMBAAECggEAQ5DB6cP7ta8iI+XEzk3t4lAj+0lhzv0UZa+Ahp1+Z4/t
|
||||
Y7etvHoKUUxwG35iGtMlXTfVOok54WZJJZZjuZitTXqdd5D5Hrw/4MMqMXuGvFM+
|
||||
MjPrnJQ739d9hayZY2/Ay7FhSK21PvzSDWtXBKQomSZ0Xbd3a8GuT9/IZKiOvZVl
|
||||
Caf9IpWsfBCTJQCO0IpNrktTzxEHPNHZLKBd7HmpRmb7SNdPPaDM5Sl9B5N8pV1j
|
||||
VafAsJjOcv2L0kTEc4Kq/VWO4fc625JTb7Zn3Q4VmQGdq/o+3Or1ojLME3GNz1YF
|
||||
j+5cKjJf+ezAdvXYLCYqRaWS8UuxhxR++S0B8tGI/QKBgQD84U+YRKB+bURUjKz3
|
||||
6OsSY6q78OeGiQjLZBBLoA/724xIPElstpy4j3wylmhV+AW696Dp8+PMMqSpdhS8
|
||||
ts9QAtvrqFchu5aIhs5ZltYrNioinRri7F/FrFeDpdmt+YcNnY5p2QNI+5Tt01oG
|
||||
i67qtxuVE+UOlUxDSaW+XpG2KwKBgQDYzNVKSX+IgB3aQV5SyRZJmEUsB8bxAnQ8
|
||||
K4vFBXtmAtOZibaJvokHe1Rp48NZHE4xlDKm4nfKx46XBW1EEPtaoyzL4gxwlSQN
|
||||
LL80PhZM0wQBhL6Ya6TZPYPLSqv+KMuIGL9OFmavrlDroQMJbiUy9UJS+xFaouHt
|
||||
EoaRq5tMrQKBgDErgjWCSo6qolmqTMubf3HA7WbDzdDr/kjF+SErS1BWfS1ig4he
|
||||
7ZQ5WhXgBwOISVz0X1Z+NLH0uu20Zw3WofLVy3tD7UVC219Kjv7+hEA8tO6sC5lK
|
||||
Csk93HpdmjjoxujP1Owh5TCgsnGX4e5Z5LYAyp0vFB/EyeJfhJnCe6SnAoGAfU5O
|
||||
zSQUAVpDZt23XdP5/Ml02ZEZLD3F3u0wWMzlWL2zfZ+6EH0/CEMBND6/ruaMT12f
|
||||
tRNaN6sFwEYTtG64SNfdUW4y0HNzJeZCETj9fKPOQe5ulvxIiINkhICBTmJX2S6s
|
||||
i76o1UvEW5xxe+bcu0pEbl/M1P0l5fd6LgHovfUCgYADQHISMiW1JqCnM/Mu0WhD
|
||||
i++BWMnUCb9BqFk/IPnKJUZUPLNKQ3izuvrNKpvd5HwSm7278h6SX2LaU+1D+Pcw
|
||||
vvQGMhK7FDhO0E7qOu/pNDRtaNnKIeG76GoYAkGdm2dc3kY8mxlLIgegL/ateuf0
|
||||
AXBDlbmJJZgDYNioytFKnw==
|
||||
-----END PRIVATE KEY-----
|
||||
108
apps/sdlan/src/quic/sdlan_quic_conn.erl
Normal file
108
apps/sdlan/src/quic/sdlan_quic_conn.erl
Normal file
@ -0,0 +1,108 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author anlicheng
|
||||
%%% @copyright (C) 2026, <COMPANY>
|
||||
%%% @doc
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 11. 2月 2026 23:00
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(sdlan_quic_conn).
|
||||
-author("anlicheng").
|
||||
|
||||
-behaviour(gen_statem).
|
||||
|
||||
%% API
|
||||
-export([start_link/1]).
|
||||
|
||||
%% gen_statem callbacks
|
||||
-export([init/1, handle_event/4, terminate/3, code_change/4, callback_mode/0]).
|
||||
|
||||
-record(state, {
|
||||
conn :: quicer:connection_handle(),
|
||||
stream_handle :: undefined | quicer:stream_handle()
|
||||
}).
|
||||
|
||||
%%%===================================================================
|
||||
%%% API
|
||||
%%%===================================================================
|
||||
|
||||
%% @doc Creates a gen_statem process which calls Module:init/1 to
|
||||
%% initialize. To ensure a synchronized start-up procedure, this
|
||||
%% function does not return until Module:init/1 has returned.
|
||||
start_link(Conn) ->
|
||||
gen_statem:start_link(?MODULE, [Conn], []).
|
||||
|
||||
%%%===================================================================
|
||||
%%% gen_statem callbacks
|
||||
%%%===================================================================
|
||||
|
||||
%% @private
|
||||
%% @doc Whenever a gen_statem is started using gen_statem:start/[3,4] or
|
||||
%% gen_statem:start_link/[3,4], this function is called by the new
|
||||
%% process to initialize.
|
||||
init([Conn]) ->
|
||||
{ok, initializing, #state{conn = Conn}, [{next_event, internal, do_init}]}.
|
||||
|
||||
%% @private
|
||||
%% @doc This function is called by a gen_statem when it needs to find out
|
||||
%% the callback mode of the callback module.
|
||||
callback_mode() ->
|
||||
handle_event_function.
|
||||
|
||||
%% @private
|
||||
%% @doc If callback_mode is handle_event_function, then whenever a
|
||||
%% gen_statem receives an event from call/2, cast/2, or as a normal
|
||||
%% process message, this function is called.
|
||||
|
||||
handle_event(internal, do_init, initializing, State = #state{conn = Conn}) ->
|
||||
case quicer:accept_stream(Conn, []) of
|
||||
{ok, Stream} ->
|
||||
{next_state, initialized, State#state{stream_handle = Stream}};
|
||||
{error, closed} ->
|
||||
{stop, connection_closed, State};
|
||||
{error, Reason} ->
|
||||
logger:error("accept stream failed: ~p", [Reason]),
|
||||
{stop, Reason, State}
|
||||
end;
|
||||
|
||||
%% 处理quicer相关的信息
|
||||
handle_event(info, {quic, Msg, Stream, _Props}, _StateName, State = #state{stream_handle = Stream}) ->
|
||||
logger:debug("[sdlan_quic_stream] get message: ~p", [Msg]),
|
||||
{keep_state, State};
|
||||
|
||||
handle_event(info, {quic_closed, Stream, _Props}, _StateName, State = #state{conn = Conn, stream_handle = Stream}) ->
|
||||
quicer:close_connection(Conn),
|
||||
{stop, connection_closed, State};
|
||||
|
||||
handle_event(info, {'EXIT', _, _}, _StateName, State = #state{conn = Conn}) ->
|
||||
quicer:close_connection(Conn),
|
||||
{stop, connection_closed, State};
|
||||
|
||||
handle_event(_EventType, _EventContent, _StateName, State = #state{}) ->
|
||||
NextStateName = the_next_state_name,
|
||||
{next_state, NextStateName, State}.
|
||||
|
||||
%% @private
|
||||
%% @doc This function is called by a gen_statem when it is about to
|
||||
%% terminate. It should be the opposite of Module:init/1 and do any
|
||||
%% necessary cleaning up. When it returns, the gen_statem terminates with
|
||||
%% Reason. The return value is ignored.
|
||||
terminate(Reason, _StateName, _State = #state{conn = Conn, stream_handle = Stream}) ->
|
||||
case Stream /= undefined of
|
||||
true ->
|
||||
quicer:close_stream(Stream);
|
||||
false ->
|
||||
ok
|
||||
end,
|
||||
quicer:close_connection(Conn),
|
||||
logger:warning("[sdlan_quic_conn] terminate closed with reason: ~p", [Reason]),
|
||||
ok.
|
||||
|
||||
%% @private
|
||||
%% @doc Convert process state when code is changed
|
||||
code_change(_OldVsn, StateName, State = #state{}, _Extra) ->
|
||||
{ok, StateName, State}.
|
||||
|
||||
%%%===================================================================
|
||||
%%% Internal functions
|
||||
%%%===================================================================
|
||||
49
apps/sdlan/src/quic/sdlan_quic_server.erl
Normal file
49
apps/sdlan/src/quic/sdlan_quic_server.erl
Normal file
@ -0,0 +1,49 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author anlicheng
|
||||
%%% @copyright (C) 2026, <COMPANY>
|
||||
%%% @doc
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 11. 2月 2026 21:26
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(sdlan_quic_server).
|
||||
-author("anlicheng").
|
||||
|
||||
%% API
|
||||
-export([start_link/0, init/0]).
|
||||
|
||||
start_link() ->
|
||||
{ok, spawn_link(?MODULE, init, [])}.
|
||||
|
||||
init() ->
|
||||
{ok, Props} = application:get_env(sdlan, quic_server),
|
||||
Port = proplists:get_value(port, Props),
|
||||
Alpn = proplists:get_value(alpn, Props),
|
||||
|
||||
Path = code:priv_dir(sdlan),
|
||||
|
||||
LOptions = [
|
||||
{certfile, Path ++ "/cert.pem"},
|
||||
{keyfile, Path ++ "/key.pem"},
|
||||
{alpn, Alpn},
|
||||
{peer_bidi_stream_count, 1}
|
||||
],
|
||||
{ok, L} = quicer:listen(Port, LOptions),
|
||||
loop_accept(L).
|
||||
|
||||
loop_accept(L) ->
|
||||
case quicer:accept(L, [], infinity) of
|
||||
{ok, Conn} ->
|
||||
case quicer:handshake(Conn) of
|
||||
ok ->
|
||||
{ok, WorkerPid} = sdlan_quic_conn:start_link(Conn),
|
||||
quicer:controlling_process(Conn, WorkerPid),
|
||||
loop_accept(L);
|
||||
{error, _} ->
|
||||
quicer:close_connection(Conn),
|
||||
loop_accept(L)
|
||||
end;
|
||||
{error, Reason} ->
|
||||
logger:debug("[sdlan_quic_server] accept failed: ~p", [Reason]),
|
||||
loop_accept(L)
|
||||
end.
|
||||
@ -61,6 +61,14 @@ init([]) ->
|
||||
shutdown => 2000,
|
||||
type => supervisor,
|
||||
modules => ['sdlan_stun_sup']
|
||||
},
|
||||
#{
|
||||
id => sdlan_quic_server,
|
||||
start => {sdlan_quic_server, start_link, []},
|
||||
restart => permanent,
|
||||
shutdown => 2000,
|
||||
type => worker,
|
||||
modules => ['sdlan_quic_server']
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
@ -15,6 +15,11 @@
|
||||
{backlog, 10240}
|
||||
]},
|
||||
|
||||
{quic_server, [
|
||||
{port, 1365},
|
||||
{alpn, ["punchnet/1.0"]}
|
||||
]},
|
||||
|
||||
%% 网络带宽, 单位为: kb
|
||||
{band_width, 2048},
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user