This commit is contained in:
anlicheng 2026-05-03 15:54:13 +08:00
parent 58eeced341
commit 58e59fec82
30 changed files with 120 additions and 29 deletions

View File

@ -12,6 +12,7 @@
-define(SERVER, ?MODULE).
-spec start_link() -> supervisor:startlink_ret().
start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
@ -23,7 +24,9 @@ start_link() ->
%% restart => restart(), % optional
%% shutdown => shutdown(), % optional
%% type => worker(), % optional
%% modules => modules()} % optional
-spec init(Args :: term()) ->
{ok, {SupFlags :: supervisor:sup_flags(), [ChildSpec :: supervisor:child_spec()]}}
| ignore.
init([]) ->
SupFlags = #{strategy => one_for_one, intensity => 1000, period => 3600},
Port = 15353,

View File

@ -112,6 +112,7 @@ ip_checksum(#ipv4{hl = HL, tos = ToS, len = Len,
CheckSum
end.
-spec test() -> term().
test() ->
%Bin = <<69,0,0,77,48,179,0,0,64,17,28,168,100,123,0,2,100,100,100,100,252,230,0,53,0,57,6,92,152,24,1,0,0,1,0,0,0,0,0,0,2,100,98,7,95,100,110,115,45,115,100,4,95,117,100,112,8,112,117,110,99,104,110,101,116,2,116,115,3,110,101,116,0,0,12,0,1>>,
Bin = <<69,0,0,93,0,0,0,0,64,6,77,86,100,100,100,100,100,123,0,2,0,53,196,102,0,73,39,7,215,192,129,128,0,1,0,1,0,0,0,0,2,108,98,7,95,100,110,115,45,115,100,4,95,117,100,112,8,112,117,110,99,104,110,101,116,2,116,115,3,110,101,116,0,0,12,0,1,192,12,0,12,0,1,0,0,1,44,0,4,192,168,1,101>>,

View File

@ -17,6 +17,8 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
-spec handle_request(Method :: string(), Path :: string(), GetParams :: map(), PostParams :: map()) ->
{ok, StatusCode :: non_neg_integer(), Body :: iodata()}.
handle_request("POST", "/test/auth_token", _, PostParams) ->
logger:debug("[test_handler] get post params: ~p", [PostParams]),
[Id | _] = network_bo:get_all_networks(),

View File

@ -17,6 +17,8 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
-spec handle_request(Method :: string(), Path :: string(), GetParams :: map(), PostParams :: map()) ->
{ok, StatusCode :: non_neg_integer(), Body :: iodata()}.
handle_request("POST", "/binlog", _, PostParams) ->
logger:debug("[binlog_handler] get post params: ~p", [PostParams]),
{ok, 200, sdlan_util:json_data(<<"ok">>)};

View File

@ -12,6 +12,7 @@
%% API
-export([init/2]).
-spec init(Req :: cowboy_req:req(), Opts :: [module()]) -> {ok, cowboy_req:req(), [module()]}.
init(Req0, Opts = [Mod|_]) ->
Method = binary_to_list(cowboy_req:method(Req0)),
Path = binary_to_list(cowboy_req:path(Req0)),

View File

@ -13,6 +13,8 @@
%% API
-export([handle_request/4]).
-spec handle_request(Method :: string(), Path :: string(), GetParams :: map(), PostParams :: map()) ->
{ok, StatusCode :: non_neg_integer(), Body :: iodata()}.
handle_request("POST", "/network/create", _, #{<<"id">> := NetworkId}) when NetworkId > 0 ->
case sdlan_network_sup:ensure_network_started(NetworkId) of
{ok, Pid} when is_pid(Pid) ->

View File

@ -12,6 +12,8 @@
%% API
-export([handle_request/4]).
-spec handle_request(Method :: string(), Path :: string(), GetParams :: map(), PostParams :: map()) ->
{ok, StatusCode :: non_neg_integer(), Body :: iodata()}.
handle_request("POST", "/node/disable", _, #{<<"network_id">> := NetworkId, <<"client_id">> := ClientId}) when NetworkId > 0 ->
case sdlan_network:get_pid(NetworkId) of
undefined ->

View File

@ -13,6 +13,7 @@
-export([start/0]).
%% http服务
-spec start() -> ok.
start() ->
{ok, Props} = application:get_env(sdlan, http_server),
Acceptors = proplists:get_value(acceptors, Props, 50),

View File

@ -17,6 +17,8 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
-spec handle_request(Method :: string(), Path :: string(), GetParams :: map(), PostParams :: map()) ->
{ok, StatusCode :: non_neg_integer(), Body :: iodata()}.
handle_request("POST", "/test/auth_access_token", _, _PostParams) ->
{ok, 200, sdlan_util:json_data(<<"ok">>)};

View File

@ -12,9 +12,13 @@
-define(SERVER, ?MODULE).
-spec start_link() -> supervisor:startlink_ret().
start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
-spec init(Args :: term()) ->
{ok, {SupFlags :: supervisor:sup_flags(), [ChildSpec :: supervisor:child_spec()]}}
| ignore.
init([]) ->
SupFlags = #{strategy => one_for_one, intensity => 1000, period => 3600},
{ok, Props} = application:get_env(sdlan, ipv6_assist),

View File

@ -4,6 +4,7 @@
-export([init/0]).
-export([get_policies/1, insert/1, delete/1, update/2]).
-spec init() -> ets:tab().
init() ->
ets:new(identity_policy, [named_table, bag, public, {keypos, 2}, {read_concurrency, true}]).
@ -12,16 +13,19 @@ get_policies(IdentityId) when is_integer(IdentityId) ->
Records = ets:lookup(identity_policy, IdentityId),
lists:map(fun(#identity_policy{policy_id = PolicyId}) -> PolicyId end, Records).
-spec insert(map() | #identity_policy{}) -> true.
insert(#{<<"identity_id">> := IdentityId, <<"policy_id">> := PolicyId}) ->
insert(#identity_policy{identity_id = IdentityId, policy_id = PolicyId});
insert(IdentityPolicy=#identity_policy{}) ->
true = ets:insert(identity_policy, IdentityPolicy).
-spec delete(map() | #identity_policy{}) -> true.
delete(#{<<"identity_id">> := IdentityId, <<"policy_id">> := PolicyId}) ->
ets:delete_object(identity_policy, #identity_policy{identity_id = IdentityId, policy_id = PolicyId});
delete(IdentityPolicy = #identity_policy{}) ->
true = ets:delete_object(identity_policy, IdentityPolicy).
-spec update(NewData :: map(), OldData :: map()) -> true.
update(NewData=#{<<"identity_id">> := IdentityId, <<"policy_id">> := PolicyId}, OldData) ->
%%
#{<<"identity_id">> := OldIdentityId, <<"policy_id">> := OldPolicyId} = maps:merge(NewData, OldData),

View File

@ -29,9 +29,11 @@
%% esockd callback
%%--------------------------------------------------------------------
-spec start(Socket :: inet:socket()) -> pid().
start(Socket) ->
spawn(?MODULE, loop, [#state{socket = Socket, command = #command{}}]).
-spec loop(State :: #state{}) -> no_return().
loop(State=#state{socket = Socket, command = Command = #command{data = Data}}) ->
inet:setopts(Socket, [{active, once}]),
receive

View File

@ -16,9 +16,11 @@
%% esockd callback
%%--------------------------------------------------------------------
-spec start_link(Port :: inet:port_number()) -> {ok, pid()}.
start_link(Port) when is_integer(Port) ->
{ok, spawn_link(?MODULE, init, [Port])}.
-spec init(Port :: inet:port_number()) -> no_return().
init(Port) ->
{ok, LSocket} = gen_tcp:listen(Port, [
binary,

View File

@ -4,6 +4,7 @@
-export([init/0]).
-export([insert/1, get_rules/2, delete/1, update/2]).
-spec init() -> ets:tab().
init() ->
ets:new(rule_table, [named_table, ordered_set, public, {keypos, 2}, {read_concurrency, true}]),
ets:new(rule_index, [named_table, bag, public, {read_concurrency, true}]).
@ -25,6 +26,7 @@ get_rules(SrcPolicyIds, DstPolicyIds) when is_list(SrcPolicyIds), is_list(DstPol
{ok, sets:to_list(S)}.
-spec insert(Data :: map()) -> true.
insert(#{<<"rule_id">> := RuleId, <<"network_id">> := NetworkId,
<<"src_policy_id">> := SrcPolicyId, <<"dst_policy_id">> := DstPolicyId, <<"proto">> := Proto,
<<"port">> := Port, <<"action">> := Action, <<"created_at">> := CreatedAt}) ->
@ -41,6 +43,7 @@ insert(#{<<"rule_id">> := RuleId, <<"network_id">> := NetworkId,
ets:insert(rule_table, Rule),
ets:insert(rule_index, {SrcPolicyId, DstPolicyId, RuleId}).
-spec update(NewData :: map(), OldData :: map()) -> true.
update(NewData = #{<<"rule_id">> := RuleId, <<"network_id">> := NetworkId,
<<"src_policy_id">> := SrcPolicyId, <<"dst_policy_id">> := DstPolicyId, <<"proto">> := Proto,
<<"port">> := Port, <<"action">> := Action, <<"created_at">> := CreatedAt}, OldData) ->
@ -63,6 +66,7 @@ update(NewData = #{<<"rule_id">> := RuleId, <<"network_id">> := NetworkId,
%%
ets:insert(rule_index, {SrcPolicyId, DstPolicyId, RuleId}).
-spec delete(Data :: map()) -> true.
delete(#{<<"rule_id">> := RuleId, <<"src_policy_id">> := SrcPolicyId, <<"dst_policy_id">> := DstPolicyId}) ->
ets:delete(rule_table, RuleId),
ets:delete_object(rule_index, {SrcPolicyId, DstPolicyId, RuleId}).

View File

@ -18,17 +18,19 @@
%%%===================================================================
%%
-spec test_rules(SrcIdentityId :: integer(), DstIdentityId :: integer()) -> binary().
test_rules(SrcIdentityId, DstIdentityId) when is_integer(SrcIdentityId), is_integer(DstIdentityId) ->
sdlan_session:test_rules(SrcIdentityId, DstIdentityId).
-spec send_event(Pid :: pid(), Event :: binary()) -> no_return().
-spec send_event(Pid :: pid(), Event :: binary()) -> ok.
send_event(Pid, ProtobufEvent) when is_pid(Pid), is_binary(ProtobufEvent) ->
sdlan_quic_transport:send_event(Pid, ProtobufEvent).
-spec command(Pid :: pid(), Ref :: reference(), ReceiverPid :: pid(), {Tag :: atom(), SubCommand :: any()}) -> no_return().
-spec command(Pid :: pid(), Ref :: reference(), ReceiverPid :: pid(), {Tag :: atom(), SubCommand :: any()}) -> ok.
command(Pid, Ref, ReceiverPid, SubCommand) when is_pid(Pid), is_pid(ReceiverPid) ->
sdlan_quic_transport:command(Pid, Ref, ReceiverPid, SubCommand).
-spec accept_stream(Pid :: pid()) -> ok.
accept_stream(Pid) when is_pid(Pid) ->
sdlan_quic_transport:accept_stream(Pid).
@ -36,9 +38,11 @@ accept_stream(Pid) when is_pid(Pid) ->
stop(Pid, Reason) when is_pid(Pid) ->
sdlan_quic_transport:stop(Pid, Reason).
-spec debug_info(Pid :: pid()) -> map().
debug_info(Pid) when is_pid(Pid) ->
sdlan_quic_transport:debug_info(Pid).
%% @doc Creates a transport process. Kept for existing supervisor specs.
-spec start_link(Conn :: quicer:connection_handle(), Limits :: proplists:proplist()) -> gen_statem:start_ret().
start_link(Conn, Limits) when is_list(Limits) ->
sdlan_quic_transport:start_link(Conn, Limits).

View File

@ -12,9 +12,11 @@
%% API
-export([start_link/0, init/0]).
-spec start_link() -> {ok, pid()}.
start_link() ->
{ok, spawn_link(?MODULE, init, [])}.
-spec init() -> ok.
init() ->
process_flag(trap_exit, true),
{ok, Props} = application:get_env(sdlan, quic_server),

View File

@ -43,14 +43,15 @@
%%% API
%%%===================================================================
-spec send_event(Pid :: pid(), Event :: binary()) -> no_return().
-spec send_event(Pid :: pid(), Event :: binary()) -> ok.
send_event(Pid, ProtobufEvent) when is_pid(Pid), is_binary(ProtobufEvent) ->
gen_statem:cast(Pid, {send_event, ProtobufEvent}).
-spec command(Pid :: pid(), Ref :: reference(), ReceiverPid :: pid(), {Tag :: atom(), SubCommand :: any()}) -> no_return().
-spec command(Pid :: pid(), Ref :: reference(), ReceiverPid :: pid(), {Tag :: atom(), SubCommand :: any()}) -> ok.
command(Pid, Ref, ReceiverPid, SubCommand) when is_pid(Pid), is_pid(ReceiverPid) ->
gen_statem:cast(Pid, {command, Ref, ReceiverPid, SubCommand}).
-spec accept_stream(Pid :: pid()) -> ok.
accept_stream(Pid) when is_pid(Pid) ->
gen_statem:cast(Pid, accept_stream).
@ -58,12 +59,14 @@ accept_stream(Pid) when is_pid(Pid) ->
stop(Pid, Reason) when is_pid(Pid) ->
gen_statem:stop(Pid, Reason, 2000).
-spec debug_info(Pid :: pid()) -> map().
debug_info(Pid) when is_pid(Pid) ->
gen_statem:call(Pid, debug_info).
%% @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.
-spec start_link(Conn :: quicer:connection_handle(), Limits :: proplists:proplist()) -> gen_statem:start_ret().
start_link(Conn, Limits) when is_list(Limits) ->
gen_statem:start_link(?MODULE, [Conn, Limits], []).
@ -75,6 +78,7 @@ start_link(Conn, Limits) when is_list(Limits) ->
%% @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.
-spec init(Args :: term()) -> gen_statem:init_result(atom(), #state{}).
init([Conn, Limits]) ->
MaxPacketSize = proplists:get_value(max_packet_size, Limits, 16384),
HeartbeatSec = proplists:get_value(heartbeat_sec, Limits, 15),
@ -91,6 +95,7 @@ init([Conn, Limits]) ->
%% @private
%% @doc This function is called by a gen_statem when it needs to find out
%% the callback mode of the callback module.
-spec callback_mode() -> gen_statem:callback_mode_result().
callback_mode() ->
handle_event_function.
@ -99,6 +104,8 @@ callback_mode() ->
%% gen_statem receives an event from call/2, cast/2, or as a normal
%% process message, this function is called.
-spec handle_event(EventType :: gen_statem:event_type(), EventContent :: term(),
StateName :: atom(), State :: #state{}) -> gen_statem:event_handler_result(atom(), #state{}).
handle_event(cast, accept_stream, initializing, State = #state{conn = Conn, stream_active_n = StreamActiveN}) ->
logger:debug("[sdlan_quic_transport] call do_init of conn: ~p", [Conn]),
case quicer:async_accept_stream(Conn, #{active => StreamActiveN}) of
@ -219,6 +226,7 @@ handle_event(EventType, Info, StateName, State) ->
%% 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.
-spec terminate(Reason :: term(), StateName :: atom(), State :: #state{}) -> ok.
terminate(Reason, _StateName, _State = #state{conn = Conn, stream = Stream, session = Session, close_reason = CloseReason}) ->
Stream /= undefined andalso quicer:close_stream(Stream, 1000),
quicer:close_connection(Conn),
@ -228,6 +236,8 @@ terminate(Reason, _StateName, _State = #state{conn = Conn, stream = Stream, sess
%% @private
%% @doc Convert process state when code is changed
-spec code_change(OldVsn :: term(), StateName :: atom(), State :: #state{}, Extra :: term()) ->
{ok, atom(), #state{}}.
code_change(_OldVsn, StateName, State = #state{}, _Extra) ->
{ok, StateName, State}.
@ -248,7 +258,7 @@ decode_frames0(<<Len:16, Frame:Len/binary, Rest/binary>>, MaxPacketSize, Frames)
decode_frames0(Rest, _MaxPacketSize, Frames) ->
{ok, Rest, lists:reverse(Frames)}.
-spec quic_send(Stream :: quicer:stream_handle(), Data :: iodata()) -> no_return().
-spec quic_send(Stream :: quicer:stream_handle(), Data :: iodata()) -> ok.
quic_send(_Stream, []) ->
ok;
quic_send(Stream, Data) ->

View File

@ -9,6 +9,8 @@
-export([start/2, stop/1]).
-spec start(StartType :: application:start_type(), StartArgs :: term()) ->
{ok, pid()} | {ok, pid(), term()} | {error, term()}.
start(_StartType, _StartArgs) ->
io:setopts([{encoding, unicode}]),
%%
@ -38,6 +40,7 @@ start(_StartType, _StartArgs) ->
sdlan_sup:start_link().
-spec stop(State :: term()) -> ok.
stop(_State) ->
ok.

View File

@ -14,6 +14,7 @@
-export([aes_encrypt/3, aes_decrypt/3]).
-export([test/0, test_chacha20/0]).
-spec test() -> ok.
test() ->
Key = <<"abcdabcdabcdabcd">>,
X = aes_encrypt(Key, Key, <<"hello world">>),
@ -41,6 +42,7 @@ aes_decrypt(Key, IVec, CipherText) when is_binary(Key), is_binary(IVec), is_bina
crypto:crypto_one_time(aes_128_ofb, Key, IVec, CipherText, [{encrypt, false}, {padding, pkcs_padding}]).
-spec test_chacha20() -> ok.
test_chacha20() ->
Key = crypto:strong_rand_bytes(32),
Nonce = crypto:strong_rand_bytes(12),

View File

@ -14,6 +14,7 @@
-define(TABLE, sdlan_domain_regedit).
-spec init() -> ets:tab().
init() ->
ets:new(?TABLE, [named_table, ordered_set, public, {read_concurrency, true}, {write_concurrency, true}]).

View File

@ -14,6 +14,7 @@
-define(TABLE, sdlan_hostname_regedit).
-spec init() -> ets:tab().
init() ->
ets:new(?TABLE, [named_table, set, public, {read_concurrency, true}, {write_concurrency, true}]).

View File

@ -38,6 +38,10 @@ start_link() ->
%% this function is called by the new process to find out about
%% restart strategy, maximum restart frequency and child
%% specifications.
-spec init(Args :: term()) ->
{ok, {SupFlags :: supervisor:sup_flags(), [ChildSpec :: supervisor:child_spec()]}}
| ignore
| {stop, Reason :: term()}.
init([]) ->
SupFlags = #{strategy => one_for_one, intensity => 1000, period => 3600},
case sdlan_api:get_all_networks() of
@ -96,7 +100,7 @@ get_all_networks() ->
lists:map(fun({_Id, ChildPid, _Type, _Modules}) -> ChildPid end, supervisor:which_children(?MODULE)).
%%
-spec reallocate_bind_width() -> no_return().
-spec reallocate_bind_width() -> term().
reallocate_bind_width() ->
ChildPids = lists:map(fun({_Id, ChildPid, _Type, _Modules}) -> ChildPid end, supervisor:which_children(?MODULE)),
set_network_bind(length(ChildPids)).

View File

@ -63,6 +63,7 @@ new(HeartbeatSec) ->
#session{heartbeat_sec = HeartbeatSec}.
%%
-spec test_rules(SrcIdentityId :: integer(), DstIdentityId :: integer()) -> binary().
test_rules(SrcIdentityId, DstIdentityId) when is_integer(SrcIdentityId), is_integer(DstIdentityId) ->
{ok, Rules} = get_rules(SrcIdentityId, DstIdentityId),
logger:debug("[sdlan_session] test_rules policy_request src_identity_id: ~p, dst_identity_id: ~p, rules: ~p", [SrcIdentityId, DstIdentityId, Rules]),

View File

@ -12,6 +12,7 @@
-define(SERVER, ?MODULE).
-spec start_link() -> supervisor:startlink_ret().
start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
@ -23,7 +24,9 @@ start_link() ->
%% restart => restart(), % optional
%% shutdown => shutdown(), % optional
%% type => worker(), % optional
%% modules => modules()} % optional
-spec init(Args :: term()) ->
{ok, {SupFlags :: supervisor:sup_flags(), [ChildSpec :: supervisor:child_spec()]}}
| ignore.
init([]) ->
SupFlags = #{strategy => one_for_one, intensity => 1000, period => 3600},
Specs = [

View File

@ -13,6 +13,7 @@
-define(SERVER, ?MODULE).
-spec start_link() -> supervisor:startlink_ret().
start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
@ -24,7 +25,9 @@ start_link() ->
%% restart => restart(), % optional
%% shutdown => shutdown(), % optional
%% type => worker(), % optional
%% modules => modules()} % optional
-spec init(Args :: term()) ->
{ok, {SupFlags :: supervisor:sup_flags(), [ChildSpec :: supervisor:child_spec()]}}
| ignore.
init([]) ->
SupFlags = #{strategy => one_for_one, intensity => 1000, period => 3600},

View File

@ -39,6 +39,7 @@
%% @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.
-spec start_link() -> gen_statem:start_ret().
start_link() ->
gen_statem:start_link({local, ?MODULE}, ?MODULE, [], []).
@ -50,12 +51,14 @@ start_link() ->
%% @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.
-spec init(Args :: term()) -> gen_statem:init_result(atom(), #state{}).
init([]) ->
{ok, initializing, #state{}, [{next_event, internal, do_sync}]}.
%% @private
%% @doc This function is called by a gen_statem when it needs to find out
%% the callback mode of the callback module.
-spec callback_mode() -> gen_statem:callback_mode_result().
callback_mode() ->
handle_event_function.
@ -64,6 +67,8 @@ callback_mode() ->
%% gen_statem receives an event from call/2, cast/2, or as a normal
%% process message, this function is called.
-spec handle_event(EventType :: gen_statem:event_type(), EventContent :: term(),
StateName :: atom(), State :: #state{}) -> gen_statem:event_handler_result(atom(), #state{}).
handle_event(internal, do_sync, initializing, State=#state{}) ->
sync_identity_policy(),
sync_rule(),
@ -74,12 +79,15 @@ handle_event(internal, do_sync, initializing, State=#state{}) ->
%% 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.
-spec terminate(Reason :: term(), StateName :: atom(), State :: #state{}) -> ok.
terminate(Reason, _StateName, _State) ->
logger:debug("[sdlan_sync_mysql] terminate with reason: ~p", [Reason]),
ok.
%% @private
%% @doc Convert process state when code is changed
-spec code_change(OldVsn :: term(), StateName :: atom(), State :: #state{}, Extra :: term()) ->
{ok, atom(), #state{}}.
code_change(_OldVsn, StateName, State = #state{}, _Extra) ->
{ok, StateName, State}.

View File

@ -37,6 +37,7 @@ mac_str_to_bin(MacBin) when is_binary(MacBin) ->
binary:decode_hex(HexBin2).
%%
-spec rand_byte(Num :: pos_integer()) -> binary().
rand_byte(Num) when is_integer(Num), Num > 0 ->
rand_byte0(Num, <<>>).
rand_byte0(0, Acc) ->
@ -65,12 +66,15 @@ hex0(14) -> $e;
hex0(15) -> $f;
hex0(I) -> $0 + I.
-spec json_data(Data :: term()) -> iodata().
json_data(Data) ->
jiffy:encode(#{<<"result">> => Data}, [force_utf8]).
-spec json_error(ErrCode :: integer(), ErrMessage :: binary()) -> iodata().
json_error(ErrCode, ErrMessage) when is_integer(ErrCode), is_binary(ErrMessage) ->
jiffy:encode(#{<<"error">> => #{<<"code">> => ErrCode, <<"message">> => ErrMessage}}, [force_utf8]).
-spec assert_call(Condition :: boolean(), F :: fun(() -> T)) -> T | ok.
assert_call(true, F) ->
F();
assert_call(false, _) ->
@ -85,6 +89,7 @@ is_multicast_mac(Mac) when is_binary(Mac) ->
binary:part(Mac, 0, 3) =:= <<16#01,16#00,16#5E>>.
-spec format_ip(Ip :: term()) -> term().
format_ip(Ip) when is_integer(Ip) ->
int_to_ipv4(Ip);
format_ip(Ip) ->
@ -163,5 +168,6 @@ hmac(Key, Data) when is_binary(Key), is_binary(Data) ->
%% PHP hash_hmac
lists:flatten([io_lib:format("~2.16.0b", [B]) || B <- binary:bin_to_list(Digest)]).
-spec term_to_binary(Term :: term()) -> binary().
term_to_binary(Term) ->
iolist_to_binary(io_lib:format("~p", [Term])).

View File

@ -13,6 +13,7 @@
-export([start/0]).
%% ssl服务
-spec start() -> ok.
start() ->
{ok, Props} = application:get_env(sdlan, ssl_server),
Acceptors = proplists:get_value(acceptors, Props, 50),

View File

@ -36,6 +36,8 @@
%%% Ranch protocol callback
%%%===================================================================
-spec start_link(Ref :: ranch:ref(), Socket :: inet:socket(), Transport :: module(),
Limits :: proplists:proplist()) -> gen_statem:start_ret().
start_link(Ref, Socket, Transport, Limits) ->
gen_statem:start_link(?MODULE, [Ref, Socket, Transport, Limits], []).
@ -43,6 +45,7 @@ start_link(Ref, Socket, Transport, Limits) ->
%%% gen_statem callbacks
%%%===================================================================
-spec init(Args :: term()) -> gen_statem:init_result(atom(), #state{}).
init([Ref, Socket, Transport, Limits]) ->
MaxPacketSize = proplists:get_value(max_packet_size, Limits, 16384),
HeartbeatSec = proplists:get_value(heartbeat_sec, Limits, 15),
@ -56,9 +59,12 @@ init([Ref, Socket, Transport, Limits]) ->
session = Session
}}.
-spec callback_mode() -> gen_statem:callback_mode_result().
callback_mode() ->
handle_event_function.
-spec handle_event(EventType :: gen_statem:event_type(), EventContent :: term(),
StateName :: atom(), State :: #state{}) -> gen_statem:event_handler_result(atom(), #state{}).
handle_event(info, {handshake, Ref, Transport, Socket, Timeout}, handshaking,
State = #state{ref = Ref, transport = Transport, max_packet_size = MaxPacketSize, heartbeat_sec = HeartbeatSec}) ->
case Transport:handshake(Socket, [], Timeout) of
@ -123,12 +129,15 @@ handle_event(EventType, Info, StateName, State) ->
logger:notice("[sdlan_ssl_transport] state: ~p, state_name: ~p, event_type: ~p, info: ~p", [State, StateName, EventType, Info]),
keep_state_and_data.
-spec terminate(Reason :: term(), StateName :: atom(), State :: #state{}) -> ok.
terminate(Reason, _StateName, #state{socket = Socket, transport = Transport, session = Session, close_reason = CloseReason}) ->
Socket =/= undefined andalso catch Transport:close(Socket),
logger:notice("[sdlan_ssl_transport] terminate closed with reason: ~p, close_reason: ~p", [Reason, CloseReason]),
sdlan_session:close(Session),
ok.
-spec code_change(OldVsn :: term(), StateName :: atom(), State :: #state{}, Extra :: term()) ->
{ok, atom(), #state{}}.
code_change(_OldVsn, StateName, State = #state{}, _Extra) ->
{ok, StateName, State}.

View File

@ -12,6 +12,7 @@
%% API
-export([test/0]).
-spec test() -> ok.
test() ->
Opts = [
binary,