Compare commits

...

2 Commits

Author SHA1 Message Date
9403259513 解决静态分析错误的问题 2026-01-26 23:46:35 +08:00
160fb4d92b fix 2026-01-26 23:16:06 +08:00
7 changed files with 65 additions and 115 deletions

View File

@ -1,34 +0,0 @@
%%%-------------------------------------------------------------------
%%% @author licheng5
%%% @copyright (C) 2020, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 26. 4 2020 3:36
%%%-------------------------------------------------------------------
-module(api_handler).
-author("licheng5").
%% API
-export([handle_request/4]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% helper methods
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
handle_request("POST", "/test/auth_token", _, PostParams) ->
logger:debug("[test_handler] get post params: ~p", [PostParams]),
[Id | _] = network_bo:get_all_networks(),
Data = #{
<<"network_id">> => Id
},
{ok, 200, sdlan_util:json_data(Data)};
handle_request(_, Path, _, _) ->
Path1 = list_to_binary(Path),
{ok, 200, sdlan_util:json_error(-1, <<"url: ", Path1/binary, " not found">>)}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% helper methods
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View File

@ -12,7 +12,7 @@
%% API %% API
-export([handle_request/4]). -export([handle_request/4]).
handle_request("POST", "/network/create", _, #{<<"id">> := NetworkId}) when NetworkId > 0 -> handle_request("POST", "/network/start", _, #{<<"id">> := NetworkId}) when NetworkId > 0 ->
case sdlan_network_sup:ensured_network_started(NetworkId) of case sdlan_network_sup:ensured_network_started(NetworkId) of
{ok, Pid} when is_pid(Pid) -> {ok, Pid} when is_pid(Pid) ->
{ok, 200, sdlan_util:json_data(<<"success">>)}; {ok, 200, sdlan_util:json_data(<<"success">>)};
@ -21,28 +21,7 @@ handle_request("POST", "/network/create", _, #{<<"id">> := NetworkId}) when Netw
{ok, 200, sdlan_util:json_error(-1, <<"error">>)} {ok, 200, sdlan_util:json_error(-1, <<"error">>)}
end; end;
handle_request("POST", "/network/reload", _, #{<<"id">> := NetworkId}) when NetworkId > 0 -> handle_request("POST", "/network/stop", _, #{<<"id">> := NetworkId}) when NetworkId > 0 ->
case sdlan_network:get_pid(NetworkId) of
undefined ->
case sdlan_network_sup:start_network(NetworkId) of
{ok, Pid} when is_pid(Pid) ->
sdlan_network_sup:reallocate_bind_width(),
{ok, 200, sdlan_util:json_data(<<"success">>)};
{error, Reason} ->
logger:debug("[network_handler] start network: ~p, get error: ~p", [NetworkId, Reason]),
{ok, 200, sdlan_util:json_error(-1, <<"error">>)}
end;
NetworkPid when is_pid(NetworkPid) ->
case sdlan_network:reload(NetworkPid) of
ok ->
{ok, 200, sdlan_util:json_data(<<"success">>)};
{error, Reason} ->
logger:debug("[network_handler] reload network: ~p, get error: ~p", [NetworkId, Reason]),
{ok, 200, sdlan_util:json_error(-1, <<"error">>)}
end
end;
handle_request("POST", "/network/delete", _, #{<<"id">> := NetworkId}) when NetworkId > 0 ->
case sdlan_network:get_pid(NetworkId) of case sdlan_network:get_pid(NetworkId) of
undefined -> undefined ->
{ok, 200, sdlan_util:json_data(<<"success">>)}; {ok, 200, sdlan_util:json_data(<<"success">>)};

View File

@ -62,7 +62,7 @@
%% , AES-256 %% , AES-256
aes_key :: binary(), aes_key :: binary(),
%% 使ip, #{mac => #endpoint{}} %% 使ip, #{mac => #endpoint{}}
endpoints = #{} endpoints = #{} :: map()
}). }).
%%%=================================================================== %%%===================================================================
@ -91,7 +91,7 @@ get_name(Id) when is_integer(Id) ->
list_to_atom("sdlan_network:" ++ integer_to_list(Id)). list_to_atom("sdlan_network:" ++ integer_to_list(Id)).
-spec attach(Pid :: pid(), Peer :: {Ip :: inet:ip4_address(), Port :: integer()}, ClientId :: binary(), Mac :: binary(), Ip :: integer(), HostName :: binary()) -> -spec attach(Pid :: pid(), Peer :: {Ip :: inet:ip4_address(), Port :: integer()}, ClientId :: binary(), Mac :: binary(), Ip :: integer(), HostName :: binary()) ->
{ok, Domain :: binary(), MaskLen :: integer(), AesKey :: binary()} | {error, Reason :: any()}. {ok, AesKey :: binary(), SessionToken :: binary()}.
attach(Pid, Peer, ClientId, Mac, Ip, HostName) when is_pid(Pid), is_binary(ClientId), is_binary(Mac), is_integer(Ip) -> attach(Pid, Peer, ClientId, Mac, Ip, HostName) when is_pid(Pid), is_binary(ClientId), is_binary(Mac), is_integer(Ip) ->
gen_server:call(Pid, {attach, Peer, ClientId, Mac, Ip, HostName}). gen_server:call(Pid, {attach, Peer, ClientId, Mac, Ip, HostName}).
@ -228,7 +228,7 @@ handle_call(get_network_id, _From, State = #state{network_id = NetworkId}) ->
%% arp查询 %% arp查询
handle_call({arp_query, TargetIp}, _From, State = #state{endpoints = Endpoints}) -> handle_call({arp_query, TargetIp}, _From, State = #state{endpoints = Endpoints}) ->
case search_endpoint(fun(#endpoint{ip = Ip0}) -> TargetIp =:= Ip0 end, Endpoints) of case search_endpoint(fun(_, #endpoint{ip = Ip0}) -> TargetIp =:= Ip0 end, Endpoints) of
{ok, TargetMac, _} -> {ok, TargetMac, _} ->
{reply, {ok, TargetMac}, State}; {reply, {ok, TargetMac}, State};
error -> error ->
@ -256,6 +256,9 @@ handle_call(debug_info, _From, State = #state{network_id = NetworkId, ipaddr = I
handle_cast({peer_info, Sock, {ClientIp, ClientPort}, #sdl_query_info{pkt_id = PktId, src_mac = SrcMac, dst_mac = DstMac}}, handle_cast({peer_info, Sock, {ClientIp, ClientPort}, #sdl_query_info{pkt_id = PktId, src_mac = SrcMac, dst_mac = DstMac}},
State = #state{network_id = NetworkId, endpoints = Endpoints}) -> State = #state{network_id = NetworkId, endpoints = Endpoints}) ->
logger:debug("[sdlan_network] network_id: ~p, query_info, src_mac: ~p, dst_mac: ~p",
[NetworkId, sdlan_util:format_mac(SrcMac), sdlan_util:format_mac(DstMac)]),
case maps:find(DstMac, Endpoints) of case maps:find(DstMac, Endpoints) of
{ok, #endpoint{hole = #hole{peer = DstNatPeer = {{Ip0, Ip1, Ip2, Ip3}, DstNatPort}, nat_type = DstNatType}, v6_info = DstV6Info}} -> {ok, #endpoint{hole = #hole{peer = DstNatPeer = {{Ip0, Ip1, Ip2, Ip3}, DstNatPort}, nat_type = DstNatType}, v6_info = DstV6Info}} ->
%% sendRegister事件(2024-06-25 ) %% sendRegister事件(2024-06-25 )
@ -354,7 +357,7 @@ handle_cast({stun_request, Sock, Peer = {ClientIp, ClientPort}, #sdl_stun_reques
case maps:find(Mac, Endpoints) of case maps:find(Mac, Endpoints) of
%% ClientId =:= ClientId0, SessionToken =:= SessionToken0 %% ClientId =:= ClientId0, SessionToken =:= SessionToken0
{ok, Endpoint0 = #endpoint{ip = Ip, client_id = ClientId, hole = OldHole, session_token = ST}} when 1 == 2 -> {ok, Endpoint0 = #endpoint{ip = Ip, client_id = ClientId, hole = OldHole, session_token = ST}} ->
NHole = #hole{peer = Peer, nat_type = NatType}, NHole = #hole{peer = Peer, nat_type = NatType},
maybe maybe
%% hole changed -> notify peers %% hole changed -> notify peers
@ -429,7 +432,7 @@ handle_info({timeout, _, endpoint_gc}, State = #state{network_id = NetworkId, en
%% necessary cleaning up. When it returns, the gen_server terminates %% necessary cleaning up. When it returns, the gen_server terminates
%% with Reason. The return value is ignored. %% with Reason. The return value is ignored.
-spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()), -spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
State :: #state{}) -> term()). State :: #state{}) -> no_return()).
terminate(Reason, #state{network_id = NetworkId, endpoints = Endpoints}) -> terminate(Reason, #state{network_id = NetworkId, endpoints = Endpoints}) ->
logger:debug("[sdlan_network] network: ~p, will terminate with reason: ~p", [NetworkId, Reason]), logger:debug("[sdlan_network] network: ~p, will terminate with reason: ~p", [NetworkId, Reason]),
@ -482,7 +485,7 @@ limiting_check(ThrottleKey) ->
end end
end. end.
-spec broadcast(Fun :: binary(), ExcludeMacs :: [binary()], Endpoints :: map()) -> no_return(). -spec broadcast(Fun :: fun((#endpoint{}) -> no_return()), ExcludeMacs :: [binary()], Endpoints :: map()) -> no_return().
broadcast(Fun, ExcludeMacs, Endpoints) when is_function(Fun, 1), is_map(Endpoints), is_list(ExcludeMacs) -> broadcast(Fun, ExcludeMacs, Endpoints) when is_function(Fun, 1), is_map(Endpoints), is_list(ExcludeMacs) ->
maps:foreach(fun(Mac, Endpoint) -> maps:foreach(fun(Mac, Endpoint) ->
case lists:member(Mac, ExcludeMacs) of case lists:member(Mac, ExcludeMacs) of
@ -505,17 +508,12 @@ parse_ipaddr(IpAddr0) when is_binary(IpAddr0) ->
end. end.
-spec format_endpoint({Mac :: binary(), Host :: #endpoint{}}) -> map(). -spec format_endpoint({Mac :: binary(), Host :: #endpoint{}}) -> map().
format_endpoint({Mac, #endpoint{client_id = ClientId, ip = Ip, hole = Hole, v6_info = V6Info}}) -> format_endpoint({Mac, #endpoint{client_id = ClientId, ip = Ip, hole = #hole{peer = {NatIp, NatPort}, nat_type = NatType}, v6_info = V6Info}}) ->
HoleMap = case Hole of HoleMap = #{
undefined -> nat_ip => NatIp,
#{}; nat_port => NatPort,
#hole{peer = {NatIp, NatPort}, nat_type = NatType} -> nat_type => NatType
#{ },
nat_ip => NatIp,
nat_port => NatPort,
nat_type => NatType
}
end,
V6InfoMap = case V6Info of V6InfoMap = case V6Info of
undefined -> undefined ->
@ -533,9 +531,9 @@ format_endpoint({Mac, #endpoint{client_id = ClientId, ip = Ip, hole = Hole, v6_i
}. }.
-spec search_endpoint(F :: fun((term(), term()) -> boolean()), Endpoints :: map()) -> error | {ok, Key :: any(), Val :: any()}. -spec search_endpoint(F :: fun((term(), term()) -> boolean()), Endpoints :: map()) -> error | {ok, Key :: any(), Val :: any()}.
search_endpoint(F, Endpoints) when is_function(F, 1), is_map(Endpoints) -> search_endpoint(F, Endpoints) when is_function(F, 2), is_map(Endpoints) ->
search_endpoint0(F, maps:iterator(Endpoints)). search_endpoint0(F, maps:iterator(Endpoints)).
search_endpoint0(F, Iter) when is_function(F, 1) -> search_endpoint0(F, Iter) when is_function(F, 2) ->
case maps:next(Iter) of case maps:next(Iter) of
{Key, Value, NextIter} -> {Key, Value, NextIter} ->
case F(Key, Value) of case F(Key, Value) of

View File

@ -39,56 +39,43 @@ do_register(Sock, ClientIp, ClientPort, #sdl_register_super{
%% Mac地址不能是广播地址 %% Mac地址不能是广播地址
true = not (sdlan_util:is_multicast_mac(Mac) orelse sdlan_util:is_broadcast_mac(Mac)), true = not (sdlan_util:is_multicast_mac(Mac) orelse sdlan_util:is_broadcast_mac(Mac)),
MacBinStr = sdlan_util:format_mac(Mac),
IpAddr = sdlan_ipaddr:int_to_ipv4(Ip),
Params = #{ Params = #{
<<"network_id">> => NetworkId, <<"network_id">> => NetworkId,
<<"client_id">> => ClientId, <<"client_id">> => ClientId,
<<"mac">> => Mac, <<"mac">> => MacBinStr,
<<"ip">> => Ip, <<"ip">> => IpAddr,
<<"mask_len">> => MaskLen, <<"mask_len">> => MaskLen,
<<"hostname">> => HostName, <<"hostname">> => HostName,
<<"access_token">> => AccessToken <<"access_token">> => AccessToken
}, },
%% %%
logger:debug("[sdlan_register_worker] xyz client_id: ~p, ip: ~p, mac: ~p, host_name: ~p, access_token: ~p, network_id: ~p", logger:debug("[sdlan_register_worker] client_id: ~p, ip: ~p, mac: ~p, host_name: ~p, access_token: ~p, network_id: ~p",
[ClientId, Ip, Mac, HostName, AccessToken, NetworkId]), [ClientId, Ip, Mac, HostName, AccessToken, NetworkId]),
%% TODO case sdlan_api:auth_access_token(Params) of
%AuthResult = sdlan_api:auth_access_token(Params),
AuthResult = {ok, #{<<"result">> => <<"ok">>}},
case AuthResult of
{ok, #{<<"result">> := <<"ok">>}} -> {ok, #{<<"result">> := <<"ok">>}} ->
%% network的对应关系 %% network的对应关系
case sdlan_network:get_pid(NetworkId) of case sdlan_network:get_pid(NetworkId) of
NetworkPid when is_pid(NetworkPid) -> NetworkPid when is_pid(NetworkPid) ->
case sdlan_network:attach(NetworkPid, {ClientIp, ClientPort}, ClientId, Mac, Ip, HostName) of {ok, AesKey, SessionToken} = sdlan_network:attach(NetworkPid, {ClientIp, ClientPort}, ClientId, Mac, Ip, HostName),
{ok, AesKey, SessionToken} -> RsaPubKey = sdlan_cipher:rsa_pem_decode(PubKey),
RsaPubKey = sdlan_cipher:rsa_pem_decode(PubKey), EncodedAesKey = rsa_encode(AesKey, RsaPubKey),
EncodedAesKey = rsa_encode(AesKey, RsaPubKey),
RegisterSuperAck = sdlan_pb:encode_msg(#sdl_register_super_ack { RegisterSuperAck = sdlan_pb:encode_msg(#sdl_register_super_ack {
pkt_id = PktId, pkt_id = PktId,
aes_key = EncodedAesKey, aes_key = EncodedAesKey,
session_token = SessionToken session_token = SessionToken
}), }),
%% %%
Reply = <<?PACKET_REGISTER_SUPER_ACK, RegisterSuperAck/binary>>, Reply = <<?PACKET_REGISTER_SUPER_ACK, RegisterSuperAck/binary>>,
gen_udp:send(Sock, ClientIp, ClientPort, Reply), gen_udp:send(Sock, ClientIp, ClientPort, Reply),
%% 线 %% 线
Result = sdlan_api:node_online(ClientId, NetworkId, sdlan_ipaddr:int_to_ipv4(Ip)), Result = sdlan_api:node_online(ClientId, NetworkId, sdlan_ipaddr:int_to_ipv4(Ip)),
logger:debug("[sdlan_register_worker] client_id: ~p, set none online result is: ~p", [ClientId, Result]); logger:debug("[sdlan_register_worker] client_id: ~p, set none online result is: ~p", [ClientId, Result]);
{error, no_ip} ->
logger:warning("[sdlan_register_worker] client_id: ~p, register get error: no_ip", [ClientId]),
gen_udp:send(Sock, ClientIp, ClientPort, register_nak_reply(PktId, ?NAK_NO_IP, <<"No Ip address">>));
{error, host_name_used} ->
logger:warning("[sdlan_register_worker] client_id: ~p, register get error: host_name_used", [ClientId]),
gen_udp:send(Sock, ClientIp, ClientPort, register_nak_reply(PktId, ?NAK_HOSTNAME_USED, <<"Host Name Used">>));
{error, client_disabled} ->
logger:warning("[sdlan_register_worker] client_id: ~p, register get error: client_disabled", [ClientId]),
gen_udp:send(Sock, ClientIp, ClientPort, register_nak_reply(PktId, ?NAK_NODE_DISABLE, <<"Client Connection Disable">>))
end;
undefined -> undefined ->
logger:warning("[sdlan_register_worker] client_id: ~p, register get error: network not found", [ClientId]), logger:warning("[sdlan_register_worker] client_id: ~p, register get error: network not found", [ClientId]),
gen_udp:send(Sock, ClientIp, ClientPort, register_nak_reply(PktId, ?NAK_INTERNAL_FAULT, <<"Internal Error">>)) gen_udp:send(Sock, ClientIp, ClientPort, register_nak_reply(PktId, ?NAK_INTERNAL_FAULT, <<"Internal Error">>))

View File

@ -40,9 +40,7 @@ start_link() ->
%% restart strategy, maximum restart frequency and child %% restart strategy, maximum restart frequency and child
%% specifications. %% specifications.
-spec(init(Args :: term()) -> -spec(init(Args :: term()) ->
{ok, {SupFlags :: {RestartStrategy :: supervisor:strategy(), {ok, {SupFlags :: supervisor:sup_flags(), [ChildSpec :: supervisor:child_spec()]}}
MaxR :: non_neg_integer(), MaxT :: non_neg_integer()},
[ChildSpec :: supervisor:child_spec()]}}
| ignore | {error, Reason :: term()}). | ignore | {error, Reason :: term()}).
init([]) -> init([]) ->
SupFlags = #{strategy => simple_one_for_one, intensity => 1000, period => 3600}, SupFlags = #{strategy => simple_one_for_one, intensity => 1000, period => 3600},

View File

@ -86,13 +86,14 @@ handle_call(_Request, _From, State = #state{}) ->
{noreply, NewState :: #state{}} | {noreply, NewState :: #state{}} |
{noreply, NewState :: #state{}, timeout() | hibernate} | {noreply, NewState :: #state{}, timeout() | hibernate} |
{stop, Reason :: term(), NewState :: #state{}}). {stop, Reason :: term(), NewState :: #state{}}).
%% node下的转发 %% node下的转发
handle_cast({send_packets, Peers, Packet}, State = #state{workers = Workers, idx = Idx, num = Num}) -> handle_cast({send_packets, Peers, Packet}, State = #state{workers = Workers, idx = Idx, num = Num}) ->
WorkerPid = element(Idx, Workers), WorkerPid = element(Idx, Workers),
sdlan_stun:send_packets(WorkerPid, Peers, Packet), sdlan_stun:send_packets(WorkerPid, Peers, Packet),
NewIdx = (Idx rem Num) + 1, NewIdx = (Idx rem Num) + 1,
{noreply, State#state{idx = NewIdx}}. {noreply, State#state{idx = NewIdx}};
handle_cast(_Request, State) ->
{noreply, State}.
%% @private %% @private
%% @doc Handling all non call/cast messages %% @doc Handling all non call/cast messages

View File

@ -155,7 +155,18 @@ handle_info({udp, _Socket, _ServerIp, _ServerPort, <<?PACKET_EVENT, ?PACKET_EVEN
logger:debug("[stun_client] get a refresh_auth_event: ~p", [Event]), logger:debug("[stun_client] get a refresh_auth_event: ~p", [Event]),
{stop, refresh_auth, State}; {stop, refresh_auth, State};
handle_info({timeout, _, stun_request_ticker}, State = #state{tun_socket = TunSocket, client_id = ClientId, mac = Mac, ip = Ip, session_token = SessionToken}) -> handle_info({udp, _Socket, _ServerIp, _ServerPort, <<?PACKET_PEER_INFO, Data/binary>>}, State) ->
PeerInfo = #sdl_peer_info{} = sdlan_pb:decode_msg(Data, sdl_peer_info),
logger:debug("[stun_client] get peer info: ~p", [PeerInfo]),
{noreply, State};
handle_info({udp, _Socket, _ServerIp, _ServerPort, <<?PACKET_EVENT, EventType:8, Event/binary>>}, State) ->
logger:debug("[stun_client] get event_type: ~p, event: ~p", [EventType, Event]),
{noreply, State};
handle_info({timeout, _, stun_request_ticker},
State = #state{tun_socket = TunSocket, network_id = NetworkId, client_id = ClientId, mac = Mac, ip = Ip, session_token = SessionToken}) ->
Packet = sdlan_pb:encode_msg(#sdl_stun_request{ Packet = sdlan_pb:encode_msg(#sdl_stun_request{
client_id = ClientId, client_id = ClientId,
network_id = 8, network_id = 8,
@ -169,6 +180,16 @@ handle_info({timeout, _, stun_request_ticker}, State = #state{tun_socket = TunSo
gen_udp:send(TunSocket, ?SUPER_HOST, ?SUPER_PORT, <<?PACKET_STUN_REQUEST, Packet/binary>>), gen_udp:send(TunSocket, ?SUPER_HOST, ?SUPER_PORT, <<?PACKET_STUN_REQUEST, Packet/binary>>),
erlang:start_timer(5000, self(), stun_request_ticker), erlang:start_timer(5000, self(), stun_request_ticker),
QueryPacket = sdlan_pb:encode_msg(#sdl_query_info{
pkt_id = 10,
network_id = NetworkId,
src_mac = Mac,
dst_mac = Mac,
session_token = SessionToken
}),
gen_udp:send(TunSocket, ?SUPER_HOST, ?SUPER_PORT, <<?PACKET_QUERY_INFO, QueryPacket/binary>>),
logger:debug("[stun_client] will send query packet: ~p", [QueryPacket]),
{noreply, State}. {noreply, State}.
%% @private %% @private