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,
|
shutdown => 2000,
|
||||||
type => supervisor,
|
type => supervisor,
|
||||||
modules => ['sdlan_stun_sup']
|
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}
|
{backlog, 10240}
|
||||||
]},
|
]},
|
||||||
|
|
||||||
|
{quic_server, [
|
||||||
|
{port, 1365},
|
||||||
|
{alpn, ["punchnet/1.0"]}
|
||||||
|
]},
|
||||||
|
|
||||||
%% 网络带宽, 单位为: kb
|
%% 网络带宽, 单位为: kb
|
||||||
{band_width, 2048},
|
{band_width, 2048},
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user