fix events

This commit is contained in:
anlicheng 2026-01-26 12:17:58 +08:00
parent eb11c05ba5
commit eb35558fe7
3 changed files with 64 additions and 6 deletions

View File

@ -33,7 +33,7 @@
%%
-define(PACKET_EVENT_KNOWN_IP, 16#01).
-define(PACKET_EVENT_DROP_IP, 16#02).
-define(PACKET_EVENT_DROP_IPS, 16#02).
-define(PACKET_EVENT_NAT_CHANGED, 16#03).
-define(PACKET_EVENT_SEND_REGISTER, 16#04).

View File

@ -16,7 +16,8 @@
-behaviour(gen_server).
-define(FLOW_REPORT_INTERVAL, 60 * 1000).
-define(FLOW_REPORT_INTERVAL, 60_000).
-define(ENDPOINT_GC_INTERVAL, 30_000).
%% broadcast, "FF-FF-FF-FF-FF-FF"
-define(BROADCAST_MAC, <<16#FF,16#FF,16#FF,16#FF,16#FF,16#FF>>).
@ -43,7 +44,9 @@
hostname :: binary(),
hole :: #hole{},
%% ip和ip_v6的映射关系, #{ip_addr :: integer() => {}}
v6_info :: undefined | #sdl_v6_info{}
v6_info :: undefined | #sdl_v6_info{},
last_seen :: integer() %% monotonic_time(second)
}).
-record(state, {
@ -161,6 +164,10 @@ init([Id]) when is_integer(Id) ->
%%
erlang:start_timer(?FLOW_REPORT_INTERVAL, self(), flow_report_ticker),
%% endpoint定时扫描器
erlang:start_timer(?ENDPOINT_GC_INTERVAL, self(), endpoint_gc),
sdlan_domain_regedit:insert(Domain),
{ok, #state{network_id = Id, name = Name, domain = Domain, ipaddr = IpAddr, mask_len = MaskLen, aes_key = AesKey, throttle_key = ThrottleKey}};
@ -187,7 +194,23 @@ handle_call({attach, Peer, ClientId, Mac, Ip, Hostname}, _From,
[NetworkId, ClientId, sdlan_util:format_mac(Mac), sdlan_ipaddr:int_to_ipv4(Ip)]),
%% ->ip的映射关系
sdlan_hostname_regedit:insert(Hostname, Domain, Ip),
Endpoint = #endpoint{client_id = ClientId, mac = Mac, ip = Ip, hostname = Hostname, hole = #hole{peer = Peer, nat_type = 0}},
%% mac对应的Endpoint存在ip变了arp
maybe
{ok, #endpoint{ip = OldIp}} ?= maps:find(Mac, Endpoints),
true ?= OldIp =/= Ip,
NatChangedEvent = sdlan_pb:encode_msg(#sdl_nat_changed_event{
mac = Mac,
ip = Ip
}),
EventPacket = <<?PACKET_EVENT, ?PACKET_EVENT_NAT_CHANGED, NatChangedEvent/binary>>,
EndpointPeers = endpoint_peers([Mac], Endpoints),
sdlan_stun_pool:send_packets(EndpointPeers, EventPacket)
end,
Endpoint = #endpoint{client_id = ClientId, mac = Mac, ip = Ip, hostname = Hostname,
hole = #hole{peer = Peer, nat_type = 0}, last_seen = erlang:monotonic_time(second)},
{reply, {ok, Domain, MaskLen, AesKey}, State#state{endpoints = maps:put(Mac, Endpoint, Endpoints)}};
@ -313,6 +336,7 @@ handle_cast({unregister, _ClientId, Mac}, State = #state{network_id = NetworkId,
{noreply, State#state{endpoints = maps:remove(Mac, Endpoints)}};
%% client是属于当前网络的
%% TODO endpoint需要通知其重新验证
handle_cast({update_hole, ClientId, Mac, Peer, NatType, V6Info}, State = #state{endpoints = Endpoints}) ->
case maps:find(Mac, Endpoints) of
{ok, Endpoint0 = #endpoint{ip = Ip, client_id = ClientId0, hole = OldHole}} when ClientId =:= ClientId0 ->
@ -328,7 +352,7 @@ handle_cast({update_hole, ClientId, Mac, Peer, NatType, V6Info}, State = #state{
EndpointPeers = endpoint_peers([Mac], Endpoints),
sdlan_stun_pool:send_packets(EndpointPeers, EventPacket)
end,
{noreply, State#state{endpoints = maps:put(Mac, Endpoint0#endpoint{hole = NHole, v6_info = V6Info}, Endpoints)}};
{noreply, State#state{endpoints = maps:put(Mac, Endpoint0#endpoint{hole = NHole, v6_info = V6Info, last_seen = erlang:monotonic_time(second)}, Endpoints)}};
_ ->
{noreply, State}
end.
@ -342,7 +366,35 @@ 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}) ->
erlang:start_timer(?FLOW_REPORT_INTERVAL, self(), flow_report_ticker),
catch sdlan_api:network_forward_report(NetworkId, ForwardBytes),
{noreply, State#state{forward_bytes = 0}}.
{noreply, State#state{forward_bytes = 0}};
handle_info({timeout, _, endpoint_gc}, State = #state{endpoints = Endpoints}) ->
erlang:start_timer(?ENDPOINT_GC_INTERVAL, self(), endpoint_gc),
Now = erlang:monotonic_time(second),
{AliveEndpoints, ExpiredEndpoints} = maps:fold(fun(Mac, Ep = #endpoint{last_seen = Last}, {Alive, Expired}) ->
case Now - Last =< ?ENDPOINT_GC_INTERVAL of
true ->
{maps:put(Mac, Ep, Alive), Expired};
false ->
{Alive, maps:put(Mac, Ep, Expired)}
end
end,
{#{}, #{}}, Endpoints),
ExpiredIps = lists:map(fun(#endpoint{ip = Ip0}) -> Ip0 end, maps:values(ExpiredEndpoints)),
%% Endpoints
NatChangedEvent = sdlan_pb:encode_msg(#sdl_nat_changed_event{
mac = Mac,
ip = Ip
}),
EventPacket = <<?PACKET_EVENT, ?PACKET_EVENT_NAT_CHANGED, NatChangedEvent/binary>>,
EndpointPeers = endpoint_peers([Mac], Endpoints),
sdlan_stun_pool:send_packets(EndpointPeers, EventPacket),
{noreply, State#state{endpoints = AliveEndpoints}}.
%% @private
%% @doc This function is called by a gen_server when it is about to

View File

@ -64,6 +64,12 @@ message SDLNatChangedEvent {
uint32 ip = 3;
}
// Endpoints
message SDLDropMacsEvent {
uint32 network_id = 1;
repeated bytes mac = 2;
}
message SDLSendRegisterEvent {
uint32 network_id = 1;
bytes dst_mac = 2;