fix sdlan_network
This commit is contained in:
parent
07bdfb5f31
commit
f6e1cd7c5e
@ -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
|
||||||
|
|||||||
@ -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).
|
||||||
|
|||||||
@ -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) ->
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user