fix register

This commit is contained in:
anlicheng 2026-01-25 21:07:34 +08:00
parent f5a07e41f7
commit a4f2ed8428
3 changed files with 79 additions and 108 deletions

View File

@ -23,7 +23,7 @@
%% API %% API
-export([start_link/2]). -export([start_link/2]).
-export([get_name/1, get_pid/1, lookup_pid/1, assign_ip_addr/4, peer_info/3, unregister/3, debug_info/1, get_network_id/1, get_used_map/1, arp_query/2]). -export([get_name/1, get_pid/1, lookup_pid/1, attach/6, peer_info/3, unregister/3, debug_info/1, get_network_id/1, get_used_map/1, arp_query/2]).
-export([forward/5, update_hole/6, disable_client/2, dropout_client/2]). -export([forward/5, update_hole/6, disable_client/2, dropout_client/2]).
-export([test_event/1]). -export([test_event/1]).
@ -39,8 +39,8 @@
-record(endpoint, { -record(endpoint, {
client_id :: binary(), client_id :: binary(),
ip :: integer(), ip :: integer(),
monitor_ref :: reference(), hostname :: binary(),
hole :: undefined | #hole{}, hole :: #hole{},
%% ip和ip_v6的映射关系, #{ip_addr :: integer() => {}} %% ip和ip_v6的映射关系, #{ip_addr :: integer() => {}}
v6_info :: undefined | #sdl_v6_info{} v6_info :: undefined | #sdl_v6_info{}
}). }).
@ -91,11 +91,10 @@ lookup_pid(Id) when is_integer(Id) ->
get_name(Id) when is_integer(Id) -> 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(), ChannelPid :: pid(), ClientId :: binary(), Mac :: binary()) -> -spec attach(Pid :: pid(), Peer :: {Ip :: inet:ip4_address(), Port :: integer()}, ClientId :: binary(), Mac :: binary(), Ip :: inet:ip4_address(), HostName :: binary()) ->
{ok, Domain :: binary(), NetAddr :: integer(), MaskLen :: integer(), AesKey :: binary()} | {error, Reason :: any()}. {ok, Domain :: binary(), MaskLen :: integer(), AesKey :: binary()} | {error, Reason :: any()}.
attach(Pid, Peer, ClientId, Mac, Ip, HostName) when is_pid(Pid), is_binary(ClientId), is_binary(Mac) ->
attach(Pid, ChannelPid, ClientId, Mac, Ip, HostName) when is_pid(Pid), is_pid(ChannelPid), is_binary(ClientId), is_binary(Mac) -> gen_server:call(Pid, {attach, Peer, ClientId, Mac, Ip, HostName}).
gen_server:call(Pid, {attach, ChannelPid, ClientId, Mac, Ip, HostName}).
-spec get_network_id(Pid :: pid()) -> {ok, NetworkId :: integer()}. -spec get_network_id(Pid :: pid()) -> {ok, NetworkId :: integer()}.
get_network_id(Pid) when is_pid(Pid) -> get_network_id(Pid) when is_pid(Pid) ->
@ -158,7 +157,6 @@ start_link(Name, Id) when is_atom(Name), is_integer(Id) ->
{ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} | {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
{stop, Reason :: term()} | ignore). {stop, Reason :: term()} | ignore).
init([Id]) when is_integer(Id) -> init([Id]) when is_integer(Id) ->
erlang:process_flag(trap_exit, true),
case sdlan_api:get_network(Id) of case sdlan_api:get_network(Id) of
{ok, #{<<"ipaddr">> := Null}} when Null == <<"null">>; Null == <<"NULL">> -> {ok, #{<<"ipaddr">> := Null}} when Null == <<"null">>; Null == <<"NULL">> ->
ignore; ignore;
@ -175,7 +173,8 @@ init([Id]) when is_integer(Id) ->
erlang:start_timer(?FLOW_REPORT_INTERVAL, self(), flow_report_ticker), erlang:start_timer(?FLOW_REPORT_INTERVAL, self(), flow_report_ticker),
sdlan_domain_regedit:insert(Domain), sdlan_domain_regedit:insert(Domain),
{ok, #state{network_id = Id, name = Name, domain = Domain, ipaddr = IpAddr, owner_id = OwnerId, mask_len = MaskLen, aes_key = AesKey, throttle_key = ThrottleKey}}; {ok, #state{network_id = Id, name = Name, domain = Domain, ipaddr = IpAddr, owner_id = OwnerId,
mask_len = MaskLen, aes_key = AesKey, throttle_key = ThrottleKey}};
{error, Reason} -> {error, Reason} ->
logger:warning("[sdlan_network] load network: ~p, get error: ~p", [Id, Reason]), logger:warning("[sdlan_network] load network: ~p, get error: ~p", [Id, Reason]),
ignore ignore
@ -191,21 +190,17 @@ init([Id]) when is_integer(Id) ->
{noreply, NewState :: #state{}, timeout() | hibernate} | {noreply, NewState :: #state{}, timeout() | hibernate} |
{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地址, TODO hole %% ip地址
handle_call({attach, ClientId, Mac, Ip, HostName}, _From, handle_call({attach, Peer, ClientId, Mac, Ip, Hostname}, _From,
State = #state{network_id = NetworkId, domain = Domain, endpoints = Endpoints, mask_len = MaskLen, aes_key = AesKey}) -> State = #state{network_id = NetworkId, domain = Domain, endpoints = Endpoints, mask_len = MaskLen, aes_key = AesKey}) ->
%% ip地址的时候mac地址为唯一基准 %% ip地址的时候mac地址为唯一基准
logger:debug("[sdlan_network] alloc_ip, network_id: ~p, client_id: ~p, mac: ~p, net_addr: ~p", logger:debug("[sdlan_network] alloc_ip, network_id: ~p, client_id: ~p, mac: ~p, ip_addr: ~p",
[NetworkId, ClientId, sdlan_util:format_mac(Mac), sdlan_ipaddr:int_to_ipv4(Ip)]), [NetworkId, ClientId, sdlan_util:format_mac(Mac), sdlan_ipaddr:int_to_ipv4(Ip)]),
%% channel
maybe_close_channel(maps:get(Mac, Endpoints, undefined)),
%% ->ip的映射关系 %% ->ip的映射关系
sdlan_hostname_regedit:insert(HostName, Domain, Ip), sdlan_hostname_regedit:insert(Hostname, Domain, Ip),
NEndpoints = maps:put(Mac, #endpoint{client_id = ClientId, ip = Ip, hostname = Hostname, hole = #hole{peer = Peer, nat_type = 0}}, Endpoints),
NEndpoints = maps:put(Mac, #endpoint{client_id = ClientId, ip = Ip}, Endpoints), {reply, {ok, Domain, MaskLen, AesKey}, State#state{endpoints = NEndpoints}};
{reply, {ok, Domain, Ip, MaskLen, AesKey}, State#state{endpoints = NEndpoints}};
handle_call(get_used_map, _From, State = #state{endpoints = Endpoints}) -> handle_call(get_used_map, _From, State = #state{endpoints = Endpoints}) ->
UsedInfos = maps:map(fun(_, #endpoint{hole = Hole, v6_info = V6Info}) -> UsedInfos = maps:map(fun(_, #endpoint{hole = Hole, v6_info = V6Info}) ->
@ -257,20 +252,20 @@ handle_call({arp_query, TargetIp}, _From, State = #state{endpoints = Endpoints})
%% nat_peer信息 %% nat_peer信息
handle_call({peer_info, SrcMac, DstMac}, _From, State = #state{endpoints = Endpoints}) -> handle_call({peer_info, SrcMac, DstMac}, _From, State = #state{endpoints = Endpoints}) ->
case maps:find(DstMac, Endpoints) of case maps:find(DstMac, Endpoints) of
{ok, #endpoint{channel_pid = DstChannelPid, hole = #hole{peer = DstNatPeer, nat_type = DstNatType}, v6_info = DstV6Info}} -> {ok, #endpoint{hole = #hole{peer = DstNatPeer, nat_type = DstNatType}, v6_info = DstV6Info}} ->
%% sendRegister事件(2024-06-25 ) %% sendRegister事件(2024-06-25 )
case maps:get(SrcMac, Endpoints, undefined) of maybe
#endpoint{hole = #hole{peer = {SrcNatIp, SrcNatPort}, nat_type = NatType}, v6_info = SrcV6Info} -> {ok, #endpoint{hole = #hole{peer = {SrcNatIp, SrcNatPort}, nat_type = NatType}, v6_info = SrcV6Info}} ?= maps:find(SrcMac, Endpoints),
Event = sdlan_pb:encode_msg(#sdl_send_register_event { Event = sdlan_pb:encode_msg(#sdl_send_register_event {
dst_mac = SrcMac, dst_mac = SrcMac,
nat_ip = sdlan_ipaddr:ipv4_to_int(SrcNatIp), nat_ip = sdlan_ipaddr:ipv4_to_int(SrcNatIp),
nat_type = NatType, nat_type = NatType,
nat_port = SrcNatPort, nat_port = SrcNatPort,
v6_info = SrcV6Info v6_info = SrcV6Info
}), }),
sdlan_channel:send_event(DstChannelPid, ?PACKET_EVENT_SEND_REGISTER, Event);
_ -> EventPacket = <<?PACKET_EVENT, ?PACKET_EVENT_SEND_REGISTER, Event/binary>>,
ok sdlan_stun_pool:send_packets([{DstNatPeer, EventPacket}])
end, end,
{reply, {ok, {DstNatPeer, DstNatType}, DstV6Info}, State}; {reply, {ok, {DstNatPeer, DstNatType}, DstV6Info}, State};
_ -> _ ->
@ -377,13 +372,10 @@ handle_cast({update_hole, ClientId, Mac, Peer, NatType, V6Info}, State = #state{
mac = Mac, mac = Mac,
ip = Ip ip = Ip
}), }),
broadcast(fun(#endpoint{channel_pid = ChannelPid}) -> EventPacket = <<?PACKET_EVENT, ?PACKET_EVENT_NAT_CHANGED, NatChangedEvent>>,
case is_process_alive(ChannelPid) of
true -> broadcast(fun(#endpoint{hole = #hole{peer = Peer}}) ->
sdlan_channel:send_event(ChannelPid, ?PACKET_EVENT_NAT_CHANGED, NatChangedEvent); sdlan_stun_pool:send_packet(Peer, EventPacket)
false ->
ok
end
end, [Mac], Endpoints); end, [Mac], Endpoints);
false -> false ->
ok ok
@ -404,30 +396,7 @@ handle_cast({update_hole, ClientId, Mac, Peer, NatType, V6Info}, State = #state{
handle_info({timeout, _, flow_report_ticker}, State = #state{network_id = NetworkId, forward_bytes = ForwardBytes}) -> handle_info({timeout, _, flow_report_ticker}, State = #state{network_id = NetworkId, forward_bytes = ForwardBytes}) ->
erlang:start_timer(?FLOW_REPORT_INTERVAL, self(), flow_report_ticker), erlang:start_timer(?FLOW_REPORT_INTERVAL, self(), flow_report_ticker),
catch sdlan_api:network_forward_report(NetworkId, ForwardBytes), catch sdlan_api:network_forward_report(NetworkId, ForwardBytes),
{noreply, State#state{forward_bytes = 0}}; {noreply, State#state{forward_bytes = 0}}.
handle_info({'EXIT', _Pid, shutdown}, State = #state{network_id = NetworkId, endpoints = Endpoints}) ->
logger:warning("[sdlan_network] network: ~p, get shutdown message", [NetworkId]),
NetworkShutdownEvent = sdlan_pb:encode_msg(#sdl_network_shutdown_event {
message = <<"Network shutdown">>
}),
broadcast(fun(#endpoint{channel_pid = ChannelPid}) ->
case is_pid(ChannelPid) andalso is_process_alive(ChannelPid) of
true ->
sdlan_channel:send_event(ChannelPid, ?PACKET_EVENT_NETWORK_SHUTDOWN, NetworkShutdownEvent),
sdlan_channel:stop(ChannelPid, normal);
false ->
ok
end
end, Endpoints),
{stop, shutdown, State};
%% Channel进程退出, hole里面的数据也需要清理
handle_info({'DOWN', _MRef, process, ChannelPid, Reason}, State = #state{network_id = NetworkId, endpoints = Endpoints}) ->
logger:notice("[sdlan_network] network_id: ~p, channel_pid: ~p, close with reason: ~p", [NetworkId, ChannelPid, Reason]),
NUsedMap = maps:filter(fun(_, #endpoint{channel_pid = ChannelPid0}) -> ChannelPid =/= ChannelPid0 end, Endpoints),
{noreply, State#state{endpoints = NUsedMap}}.
%% @private %% @private
%% @doc This function is called by a gen_server when it is about to %% @doc This function is called by a gen_server when it is about to
@ -442,15 +411,9 @@ terminate(Reason, #state{network_id = NetworkId, endpoints = Endpoints}) ->
NetworkShutdownEvent = sdlan_pb:encode_msg(#sdl_network_shutdown_event { NetworkShutdownEvent = sdlan_pb:encode_msg(#sdl_network_shutdown_event {
message = <<"Network shutdown">> message = <<"Network shutdown">>
}), }),
broadcast(fun(#endpoint{channel_pid = ChannelPid, monitor_ref = MRef}) -> EventPacket = <<?PACKET_EVENT, ?PACKET_EVENT_NETWORK_SHUTDOWN, NetworkShutdownEvent>>,
is_reference(MRef) andalso demonitor(MRef), broadcast(fun(#endpoint{hole = #hole{peer = Peer}}) ->
case is_pid(ChannelPid) andalso is_process_alive(ChannelPid) of sdlan_stun_pool:send_packet(Peer, EventPacket)
true ->
sdlan_channel:send_event(ChannelPid, ?PACKET_EVENT_NETWORK_SHUTDOWN, NetworkShutdownEvent),
sdlan_channel:stop(ChannelPid, normal);
false ->
ok
end
end, Endpoints), end, Endpoints),
ok. ok.
@ -480,18 +443,6 @@ limiting_check(ThrottleKey) ->
end end
end. end.
-spec maybe_close_channel(undefined | #endpoint{}) -> no_return().
maybe_close_channel(#endpoint{channel_pid = ChannelPid0, monitor_ref = MRef0}) ->
case is_pid(ChannelPid0) andalso is_process_alive(ChannelPid0) of
true ->
is_reference(MRef0) andalso demonitor(MRef0),
sdlan_channel:stop(ChannelPid0, channel_rebind);
false ->
ok
end;
maybe_close_channel(_) ->
ok.
-spec broadcast(Fun :: binary(), Endpoints :: map()) -> no_return(). -spec broadcast(Fun :: binary(), Endpoints :: map()) -> no_return().
broadcast(Fun, Endpoints) when is_function(Fun, 1), is_map(Endpoints) -> broadcast(Fun, Endpoints) when is_function(Fun, 1), is_map(Endpoints) ->
broadcast(Fun, [], Endpoints). broadcast(Fun, [], Endpoints).
@ -507,6 +458,17 @@ broadcast(Fun, ExcludeMacs, Endpoints) when is_function(Fun, 1), is_map(Endpoint
end end
end, Endpoints). end, Endpoints).
-spec broadcast_peers(Fun :: binary(), ExcludeMacs :: [binary()], Endpoints :: map()) -> no_return().
broadcast_peers(Fun, ExcludeMacs, Endpoints) when is_function(Fun, 1), is_map(Endpoints), is_list(ExcludeMacs) ->
maps:filtermap(fun(Mac, Endpoint) ->
case lists:member(Mac, ExcludeMacs) of
true ->
ok;
false ->
Fun(Endpoint)
end
end, Endpoints).
%% IpAddr: <<"192.168.172/24">> %% IpAddr: <<"192.168.172/24">>
-spec parse_ipaddr(IpAddr0 :: binary()) -> {IpAddr :: binary(), MaskLen :: integer()}. -spec parse_ipaddr(IpAddr0 :: binary()) -> {IpAddr :: binary(), MaskLen :: integer()}.
parse_ipaddr(IpAddr0) when is_binary(IpAddr0) -> parse_ipaddr(IpAddr0) when is_binary(IpAddr0) ->

View File

@ -25,15 +25,15 @@
-define(NAK_HOSTNAME_USED, 6). -define(NAK_HOSTNAME_USED, 6).
%% API %% API
-export([start_link/4, do_work/4]). -export([start_link/4, do_register/4]).
-spec start_link(Sock :: inet:socket(), Ip :: inet:ip4_address(), Port :: integer(), Packet :: binary()) -> {ok, pid()}. -spec start_link(Sock :: inet:socket(), Ip :: inet:ip4_address(), Port :: integer(), Packet :: binary()) -> {ok, pid()}.
start_link(Sock, Ip, Port, Packet) -> start_link(Sock, Ip, Port, Packet) ->
{ok, erlang:spawn_link(?MODULE, do_work, [Sock, Ip, Port, Packet])}. {ok, erlang:spawn_link(?MODULE, do_register, [Sock, Ip, Port, Packet])}.
do_work(Sock, Ip, Port, <<PacketId:32, Body/binary>>) -> do_register(Sock, SrcIp, SrcPort, <<PacketId:32, Body/binary>>) ->
#sdl_register_super{ #sdl_register_super{
version = Version, version = _Version,
client_id = ClientId, client_id = ClientId,
network_id = NetworkId, network_id = NetworkId,
mac = Mac, mac = Mac,
@ -45,7 +45,9 @@ do_work(Sock, Ip, Port, <<PacketId:32, Body/binary>>) ->
} = sdlan_pb:decode_msg(Body, sdl_register_super), } = sdlan_pb:decode_msg(Body, sdl_register_super),
%% %%
logger:debug("[sdlan_channel] client_id: ~p, ip: ~p, mac: ~p, host_name: ~p, access_token: ~p, network_id: ~p", [ClientId, Ip, Mac, HostName, AccessToken, NetworkId]), logger:debug("[sdlan_channel] client_id: ~p, ip: ~p, mac: ~p, host_name: ~p, access_token: ~p, network_id: ~p",
[ClientId, Ip, Mac, HostName, AccessToken, NetworkId]),
true = (Mac =/= <<>> andalso PubKey =/= <<>> andalso ClientId =/= <<>>), true = (Mac =/= <<>> andalso PubKey =/= <<>> andalso ClientId =/= <<>>),
%% 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)),
@ -65,7 +67,7 @@ do_work(Sock, Ip, Port, <<PacketId:32, Body/binary>>) ->
%% 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) ->
try sdlan_network:attach(NetworkPid, self(), ClientId, Mac, Ip, HostName) of case sdlan_network:attach(NetworkPid, {SrcIp, SrcPort}, ClientId, Mac, Ip, HostName) of
{ok, AesKey, SessionToken} -> {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),
@ -77,33 +79,31 @@ do_work(Sock, Ip, Port, <<PacketId:32, Body/binary>>) ->
%% %%
Reply = <<?PACKET_REGISTER_SUPER_ACK, PacketId:32, RegisterSuperAck/binary>>, Reply = <<?PACKET_REGISTER_SUPER_ACK, PacketId:32, RegisterSuperAck/binary>>,
gen_udp:send(Sock, Ip, Port, Reply), gen_udp:send(Sock, SrcIp, SrcPort, 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_channel] client_id: ~p, set none online result is: ~p", [ClientId, Result]); logger:debug("[sdlan_channel] client_id: ~p, set none online result is: ~p", [ClientId, Result]);
{error, no_ip} -> {error, no_ip} ->
logger:warning("[sdlan_channel] client_id: ~p, register get error: no_ip", [ClientId, Token]), logger:warning("[sdlan_channel] client_id: ~p, register get error: no_ip", [ClientId]),
gen_udp:send(Sock, Ip, Port, register_nak_reply(PacketId, ?NAK_NO_IP, <<"No Ip address">>)); gen_udp:send(Sock, SrcIp, SrcPort, register_nak_reply(PacketId, ?NAK_NO_IP, <<"No Ip address">>));
{error, host_name_used} -> {error, host_name_used} ->
logger:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: host_name_used", [ClientId, Token]), logger:warning("[sdlan_channel] client_id: ~p, register get error: host_name_used", [ClientId]),
gen_udp:send(Sock, Ip, Port, register_nak_reply(PacketId, ?NAK_HOSTNAME_USED, <<"Host Name Used">>)); gen_udp:send(Sock, SrcIp, SrcPort, register_nak_reply(PacketId, ?NAK_HOSTNAME_USED, <<"Host Name Used">>));
{error, client_disabled} -> {error, client_disabled} ->
logger:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: client_disabled", [ClientId, Token]), logger:warning("[sdlan_channel] client_id: ~p, register get error: client_disabled", [ClientId]),
gen_udp:send(Sock, Ip, Port, register_nak_reply(PacketId, ?NAK_NODE_DISABLE, <<"Client Connection Disable">>)) gen_udp:send(Sock, SrcIp, SrcPort, register_nak_reply(PacketId, ?NAK_NODE_DISABLE, <<"Client Connection Disable">>))
catch _:Error:Stack ->
logger:warning("[sdlan_channel] get error: ~p, stack: ~p", [Error, Stack])
end; end;
undefined -> undefined ->
logger:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: network not found", [ClientId, Token]), logger:warning("[sdlan_channel] client_id: ~p, register get error: network not found", [ClientId]),
gen_udp:send(Sock, Ip, Port, register_nak_reply(PacketId, ?NAK_INTERNAL_FAULT, <<"Internal Error">>)) gen_udp:send(Sock, SrcIp, SrcPort, register_nak_reply(PacketId, ?NAK_INTERNAL_FAULT, <<"Internal Error">>))
end; end;
{ok, #{<<"error">> := #{<<"code">> := Code, <<"message">> := Message}}} -> {ok, #{<<"error">> := #{<<"code">> := Code, <<"message">> := Message}}} ->
logger:warning("[sdlan_channel] network_id: ~p, client_id: ~p, register get error: ~ts, error_code: ~p", [NetworkId, ClientId, Message, Code]), logger:warning("[sdlan_channel] network_id: ~p, client_id: ~p, register get error: ~ts, error_code: ~p", [NetworkId, ClientId, Message, Code]),
gen_udp:send(Sock, Ip, Port, register_nak_reply(PacketId, Code, Message)); gen_udp:send(Sock, SrcIp, SrcPort, register_nak_reply(PacketId, Code, Message));
{error, Reason} -> {error, Reason} ->
logger:warning("[sdlan_channel] network_id: ~p, client_id: ~p, register get error: ~p", [NetworkId, ClientId, Reason]), logger:warning("[sdlan_channel] network_id: ~p, client_id: ~p, register get error: ~p", [NetworkId, ClientId, Reason]),
gen_udp:send(Sock, Ip, Port, register_nak_reply(PacketId, ?NAK_NETWORK_FAULT, <<"Network Error">>)) gen_udp:send(Sock, SrcIp, SrcPort, register_nak_reply(PacketId, ?NAK_NETWORK_FAULT, <<"Network Error">>))
end, end,
exit(normal). exit(normal).
@ -113,7 +113,8 @@ register_nak_reply(PacketId, ErrorCode, ErrorMsg) when is_integer(PacketId), is_
error_code = ErrorCode, error_code = ErrorCode,
error_message = ErrorMsg error_message = ErrorMsg
}), }),
<<PacketId:32, ?PACKET_REGISTER_SUPER_NAK, RegisterNakReply/binary>>. <<?PACKET_REGISTER_SUPER_NAK, PacketId:32, RegisterNakReply/binary>>.
-spec rsa_encode(PlainText :: binary(), RsaPubKey :: public_key:rsa_public_key()) -> binary().
rsa_encode(PlainText, RsaPubKey) when is_binary(PlainText) -> rsa_encode(PlainText, RsaPubKey) when is_binary(PlainText) ->
iolist_to_binary(sdlan_cipher:rsa_encrypt(PlainText, RsaPubKey)). iolist_to_binary(sdlan_cipher:rsa_encrypt(PlainText, RsaPubKey)).

View File

@ -16,7 +16,7 @@
-behaviour(gen_server). -behaviour(gen_server).
%% API %% API
-export([start_link/0, send_packets/1]). -export([start_link/0, send_packets/1, send_packet/2]).
%% gen_server callbacks %% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
@ -33,6 +33,9 @@
%%% API %%% API
%%%=================================================================== %%%===================================================================
send_packet(Peer, Packet) ->
gen_server:cast(?SERVER, {send_packet, Peer, Packet}).
send_packets(Packets) when is_list(Packets) -> send_packets(Packets) when is_list(Packets) ->
gen_server:cast(?SERVER, {send_packets, Packets}). gen_server:cast(?SERVER, {send_packets, Packets}).
@ -94,11 +97,16 @@ handle_call(_Request, _From, State = #state{}) ->
{stop, Reason :: term(), NewState :: #state{}}). {stop, Reason :: term(), NewState :: #state{}}).
%% node下的转发 %% node下的转发
handle_cast({send_packet, {Ip, Port}, Packet}, State = #state{workers = Workers, idx = Idx, num = Num}) ->
{Sock, _} = element(Idx, Workers),
gen_udp:send(Sock, Ip, Port, Packet),
NewIdx = (Idx rem Num) + 1,
{noreply, State#state{idx = NewIdx}};
handle_cast({send_packets, Packets}, State = #state{workers = Workers, idx = Idx, num = Num}) -> handle_cast({send_packets, Packets}, State = #state{workers = Workers, idx = Idx, num = Num}) ->
{Sock, _} = element(Idx, Workers), {Sock, _} = element(Idx, Workers),
lists:foreach(fun({Ip, Port, Data}) -> gen_udp:send(Sock, Ip, Port, Data) end, Packets), lists:foreach(fun({{Ip, Port}, Data}) -> gen_udp:send(Sock, Ip, Port, Data) end, Packets),
NewIdx = (Idx rem Num) + 1, NewIdx = (Idx rem Num) + 1,
{noreply, State#state{idx = NewIdx}}. {noreply, State#state{idx = NewIdx}}.
%% @private %% @private