fix sdlan_network

This commit is contained in:
anlicheng 2026-05-26 13:59:59 +08:00
parent 07bdfb5f31
commit f6e1cd7c5e
3 changed files with 44 additions and 22 deletions

View File

@ -19,7 +19,7 @@
%% API %% API
-export([start_link/2]). -export([start_link/2]).
-export([get_name/1, get_pid/1, lookup_pid/1, peer_info/3, unregister/3, debug_info/1, get_network_id/1, attach/6, arp_request/2]). -export([get_name/1, get_pid/1, lookup_pid/1, peer_info/3, unregister/3, debug_info/1, get_network_id/1, attach/7, arp_request/2]).
-export([forward_by_ets/5, update_hole/7, disable_client/2, get_channel/2, acl_changed/2]). -export([forward_by_ets/5, update_hole/7, disable_client/2, get_channel/2, acl_changed/2]).
-export([command/4, wait_command_ack/2]). -export([command/4, wait_command_ack/2]).
@ -35,6 +35,7 @@
-record(endpoint, { -record(endpoint, {
channel_pid :: undefined | pid(), channel_pid :: undefined | pid(),
channel_ref :: undefined | reference(), channel_ref :: undefined | reference(),
transport :: module(),
client_id :: binary(), client_id :: binary(),
mac :: binary(), mac :: binary(),
@ -90,10 +91,11 @@ get_name(Id) when is_integer(Id) ->
get_network_id(Pid) when is_pid(Pid) -> get_network_id(Pid) when is_pid(Pid) ->
gen_server:call(Pid, get_network_id). gen_server:call(Pid, get_network_id).
-spec attach(Pid :: pid(), ChannelPid :: pid(), ClientId :: binary(), Mac :: binary(), Ip :: integer(), Hostname :: binary()) -> -spec attach(Pid :: pid(), ChannelPid :: pid(), Transport :: module(), ClientId :: binary(), Mac :: binary(), Ip :: integer(), Hostname :: binary()) ->
{ok, Algorithm :: binary(), Key :: binary(), RegionId :: integer(), SessionToken :: binary()}. {ok, Algorithm :: binary(), Key :: binary(), RegionId :: integer(), SessionToken :: binary()}.
attach(Pid, ChannelPid, ClientId, Mac, Ip, Hostname) when is_pid(Pid), is_pid(ChannelPid), is_binary(ClientId), is_binary(Mac), is_integer(Ip), is_binary(Hostname) -> attach(Pid, ChannelPid, Transport, ClientId, Mac, Ip, Hostname)
gen_server:call(Pid, {attach, ChannelPid, ClientId, Mac, Ip, Hostname}). when is_pid(Pid), is_pid(ChannelPid), is_atom(Transport), is_binary(ClientId), is_binary(Mac), is_integer(Ip), is_binary(Hostname) ->
gen_server:call(Pid, {attach, ChannelPid, Transport, ClientId, Mac, Ip, Hostname}).
-spec unregister(Pid :: pid(), ClientId :: binary(), Mac :: binary()) -> ok. -spec unregister(Pid :: pid(), ClientId :: binary(), Mac :: binary()) -> ok.
unregister(Pid, ClientId, Mac) when is_pid(Pid), is_binary(ClientId), is_binary(Mac) -> unregister(Pid, ClientId, Mac) when is_pid(Pid), is_binary(ClientId), is_binary(Mac) ->
@ -209,7 +211,7 @@ init([{network, Id, Name, Domain, IpAddr, MaskLen, OwnerId, Algorithm0}]) ->
{stop, Reason :: term(), Reply :: term(), NewState :: #state{}} | {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
{stop, Reason :: term(), NewState :: #state{}}). {stop, Reason :: term(), NewState :: #state{}}).
%% ip地址 %% ip地址
handle_call({attach, ChannelPid, ClientId, Mac, Ip, Hostname}, _From, handle_call({attach, ChannelPid, Transport, ClientId, Mac, Ip, Hostname}, _From,
State = #state{network_id = NetworkId, domain = Domain, algorithm = Algorithm, key = Key, endpoint_table = EndpointTable}) -> State = #state{network_id = NetworkId, domain = Domain, algorithm = Algorithm, key = Key, endpoint_table = EndpointTable}) ->
%% ip地址的时候mac地址为唯一基准 %% ip地址的时候mac地址为唯一基准
logger:debug("[sdlan_network] alloc_ip, network_id: ~p, client_id: ~p, mac: ~p, ip_addr: ~p", logger:debug("[sdlan_network] alloc_ip, network_id: ~p, client_id: ~p, mac: ~p, ip_addr: ~p",
@ -225,6 +227,7 @@ handle_call({attach, ChannelPid, ClientId, Mac, Ip, Hostname}, _From,
Endpoint = #endpoint{ Endpoint = #endpoint{
channel_pid = ChannelPid, channel_pid = ChannelPid,
channel_ref = ChannelRef, channel_ref = ChannelRef,
transport = Transport,
client_id = ClientId, client_id = ClientId,
mac = Mac, mac = Mac,
ip = Ip, ip = Ip,
@ -270,7 +273,7 @@ handle_call(get_network_id, _From, State = #state{network_id = NetworkId}) ->
%% nat_peer信息 %% nat_peer信息
handle_call({peer_info, SrcMac, DstMac}, _From, State = #state{endpoint_table = EndpointTable}) -> handle_call({peer_info, SrcMac, DstMac}, _From, State = #state{endpoint_table = EndpointTable}) ->
case lookup_endpoint(EndpointTable, DstMac) of case lookup_endpoint(EndpointTable, DstMac) of
#endpoint{channel_pid = DstChannelPid, hole = #hole{peer = DstNatPeer, nat_type = DstNatType}, v6_info = DstV6Info} -> #endpoint{channel_pid = DstChannelPid, transport = Transport, hole = #hole{peer = DstNatPeer, nat_type = DstNatType}, v6_info = DstV6Info} ->
%% sendRegister事件(2024-06-25 ) %% sendRegister事件(2024-06-25 )
maybe maybe
#endpoint{hole = #hole{peer = {SrcNatIp, SrcNatPort}, nat_type = SrcNatType}, v6_info = SrcV6Info} ?= lookup_endpoint(EndpointTable, SrcMac), #endpoint{hole = #hole{peer = {SrcNatIp, SrcNatPort}, nat_type = SrcNatType}, v6_info = SrcV6Info} ?= lookup_endpoint(EndpointTable, SrcMac),
@ -286,7 +289,7 @@ handle_call({peer_info, SrcMac, DstMac}, _From, State = #state{endpoint_table =
}), }),
logger:debug("Event: send_register, for peer_info"), logger:debug("Event: send_register, for peer_info"),
sdlan_quic_transport:send_event(DstChannelPid, RegisterEvent) Transport:send_event(DstChannelPid, RegisterEvent)
end, end,
{reply, {ok, {DstNatPeer, DstNatType}, DstV6Info}, State}; {reply, {ok, {DstNatPeer, DstNatType}, DstV6Info}, State};
_ -> _ ->
@ -311,9 +314,9 @@ handle_call({command, ReceiverPid, ClientId, SubCommand}, _From, State = #state{
Object Object
end), end),
case select_endpoint(EndpointTable, MatchSpec) of case select_endpoint(EndpointTable, MatchSpec) of
{ok, _Mac, #endpoint{channel_pid = ChannelPid}} -> {ok, _Mac, #endpoint{channel_pid = ChannelPid, transport = Transport}} ->
Ref = make_ref(), Ref = make_ref(),
sdlan_quic_transport:command(ChannelPid, Ref, ReceiverPid, SubCommand), Transport:command(ChannelPid, Ref, ReceiverPid, SubCommand),
{reply, {ok, Ref}, State}; {reply, {ok, Ref}, State};
error -> error ->
{reply, {error, <<"目标Node不在线"/utf8>>}, State} {reply, {error, <<"目标Node不在线"/utf8>>}, State}
@ -325,9 +328,9 @@ handle_call({acl_changed, ReceiverPid, ClientId, SubCommand}, _From, State = #st
Object Object
end), end),
case select_endpoint(EndpointTable, MatchSpec) of case select_endpoint(EndpointTable, MatchSpec) of
{ok, _Mac, #endpoint{channel_pid = ChannelPid}} -> {ok, _Mac, #endpoint{channel_pid = ChannelPid, transport = Transport}} ->
Ref = make_ref(), Ref = make_ref(),
sdlan_quic_transport:command(ChannelPid, Ref, ReceiverPid, SubCommand), Transport:command(ChannelPid, Ref, ReceiverPid, SubCommand),
{reply, {ok, Ref}, State}; {reply, {ok, Ref}, State};
error -> error ->
{reply, {error, <<"目标Node不在线"/utf8>>}, State} {reply, {error, <<"目标Node不在线"/utf8>>}, State}
@ -380,8 +383,8 @@ handle_cast({update_hole, SessionToken, ClientId, Mac, Peer, NatType, V6Info}, S
}), }),
logger:debug("[sdlan_network] Event: nat_changed, update_hole, client_id: ~p(~p), hole changed", [ClientId, Ip]), logger:debug("[sdlan_network] Event: nat_changed, update_hole, client_id: ~p(~p), hole changed", [ClientId, Ip]),
broadcast(fun(#endpoint{channel_pid = ChannelPid}) -> broadcast(fun(#endpoint{channel_pid = ChannelPid, transport = Transport}) ->
sdlan_quic_transport:send_event(ChannelPid, NatChangedEvent) Transport:send_event(ChannelPid, NatChangedEvent)
end, [Mac], EndpointTable) end, [Mac], EndpointTable)
end, end,
NEndpoint = Endpoint0#endpoint{hole = NHole, v6_info = V6Info, last_seen = erlang:monotonic_time(second)}, NEndpoint = Endpoint0#endpoint{hole = NHole, v6_info = V6Info, last_seen = erlang:monotonic_time(second)},
@ -417,7 +420,7 @@ handle_info(Info, State) ->
-spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()), -spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
State :: #state{}) -> ok). State :: #state{}) -> ok).
terminate(Reason, #state{network_id = NetworkId, endpoint_table = EndpointTable}) -> terminate(Reason, #state{network_id = NetworkId, endpoint_table = EndpointTable}) ->
broadcast(fun(#endpoint{channel_pid = ChannelPid}) -> broadcast(fun(#endpoint{channel_pid = ChannelPid, transport = Transport}) ->
case is_pid(ChannelPid) andalso is_process_alive(ChannelPid) of case is_pid(ChannelPid) andalso is_process_alive(ChannelPid) of
true -> true ->
NetworkShutdownEvent = sdlan_pb:encode_msg(#'SDLEvent'{ NetworkShutdownEvent = sdlan_pb:encode_msg(#'SDLEvent'{
@ -428,8 +431,8 @@ terminate(Reason, #state{network_id = NetworkId, endpoint_table = EndpointTable}
logger:debug("[sdlan_network] Event: shutdown"), logger:debug("[sdlan_network] Event: shutdown"),
sdlan_quic_transport:send_event(ChannelPid, NetworkShutdownEvent), Transport:send_event(ChannelPid, NetworkShutdownEvent),
sdlan_quic_transport:stop(ChannelPid, normal); Transport:stop(ChannelPid, normal);
false -> false ->
ok ok
end end
@ -589,8 +592,8 @@ maybe_nat_changed(ChannelPid, Mac, Ip, EndpointTable) ->
}), }),
logger:debug("Event: nat_changed, for attach"), logger:debug("Event: nat_changed, for attach"),
broadcast(fun(#endpoint{channel_pid = ChannelPid0}) -> broadcast(fun(#endpoint{channel_pid = ChannelPid0, transport = Transport}) ->
sdlan_quic_transport:send_event(ChannelPid0, Event) Transport:send_event(ChannelPid0, Event)
end, [Mac], EndpointTable) end, [Mac], EndpointTable)
end, end,
%% attach需要清理之前的绑定信息使IP未变化channel %% attach需要清理之前的绑定信息使IP未变化channel
@ -598,11 +601,11 @@ maybe_nat_changed(ChannelPid, Mac, Ip, EndpointTable) ->
cleanup_endpoint(undefined, _KeepChannelPid, _Reason) -> cleanup_endpoint(undefined, _KeepChannelPid, _Reason) ->
ok; ok;
cleanup_endpoint(#endpoint{channel_ref = ChannelRef, channel_pid = ChannelPid}, KeepChannelPid, Reason) -> cleanup_endpoint(#endpoint{channel_ref = ChannelRef, channel_pid = ChannelPid, transport = Transport}, KeepChannelPid, Reason) ->
is_reference(ChannelRef) andalso erlang:demonitor(ChannelRef, [flush]), is_reference(ChannelRef) andalso erlang:demonitor(ChannelRef, [flush]),
case should_stop_channel(ChannelPid, KeepChannelPid) of case should_stop_channel(ChannelPid, KeepChannelPid) of
true -> true ->
catch sdlan_quic_transport:stop(ChannelPid, Reason), catch Transport:stop(ChannelPid, Reason),
ok; ok;
false -> false ->
ok ok

View File

@ -121,7 +121,7 @@ handle_frame(<<?PACKET_REGISTER_SUPER, Body/binary>>, Session = #session{status
%% 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) ->
{ok, Algorithm, Key, RegionId, SessionToken} = sdlan_network:attach(NetworkPid, self(), ClientId, Mac, Ip, HostName), {ok, Algorithm, Key, RegionId, SessionToken} = sdlan_network:attach(NetworkPid, self(), Transport, ClientId, Mac, Ip, HostName),
RsaPubKey = sdlan_cipher:rsa_pem_decode(PubKey), RsaPubKey = sdlan_cipher:rsa_pem_decode(PubKey),
RegisterSuperAck = sdlan_pb:encode_msg(#'SDLRegisterSuperAck'{ RegisterSuperAck = sdlan_pb:encode_msg(#'SDLRegisterSuperAck'{
algorithm = Algorithm, algorithm = Algorithm,
@ -410,4 +410,4 @@ heartbeat_ms(_) ->
?PING_TICKER. ?PING_TICKER.
parse_ports(Ports0) when is_list(Ports0) -> parse_ports(Ports0) when is_list(Ports0) ->
lists:filter(fun(P0) -> is_integer(P0) andalso (P0 > 0 andalso P0 < 65535) end, Ports0). lists:filter(fun(P0) -> is_integer(P0) andalso (P0 > 0 andalso P0 < 65535) end, Ports0).

View File

@ -16,6 +16,9 @@
%% Ranch protocol callback %% Ranch protocol callback
-export([start_link/4]). -export([start_link/4]).
%% API
-export([send_event/2, command/4, stop/2, debug_info/1]).
%% gen_statem callbacks %% gen_statem callbacks
-export([init/1, handle_event/4, terminate/3, code_change/4, callback_mode/0]). -export([init/1, handle_event/4, terminate/3, code_change/4, callback_mode/0]).
@ -36,6 +39,22 @@
%%% Ranch protocol callback %%% Ranch protocol callback
%%%=================================================================== %%%===================================================================
-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()}) -> ok.
command(Pid, Ref, ReceiverPid, SubCommand) when is_pid(Pid), is_pid(ReceiverPid) ->
gen_statem:cast(Pid, {command, Ref, ReceiverPid, SubCommand}).
-spec stop(Pid :: pid(), Reason :: term()) -> ok.
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).
-spec start_link(Ref :: ranch:ref(), Socket :: inet:socket(), Transport :: module(), -spec start_link(Ref :: ranch:ref(), Socket :: inet:socket(), Transport :: module(),
Limits :: proplists:proplist()) -> gen_statem:start_ret(). Limits :: proplists:proplist()) -> gen_statem:start_ret().
start_link(Ref, Socket, Transport, Limits) -> start_link(Ref, Socket, Transport, Limits) ->