fix events
This commit is contained in:
parent
eb11c05ba5
commit
eb35558fe7
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
%% 定义事件信息
|
%% 定义事件信息
|
||||||
-define(PACKET_EVENT_KNOWN_IP, 16#01).
|
-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_NAT_CHANGED, 16#03).
|
||||||
-define(PACKET_EVENT_SEND_REGISTER, 16#04).
|
-define(PACKET_EVENT_SEND_REGISTER, 16#04).
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,8 @@
|
|||||||
|
|
||||||
-behaviour(gen_server).
|
-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"
|
%% broadcast, "FF-FF-FF-FF-FF-FF"
|
||||||
-define(BROADCAST_MAC, <<16#FF,16#FF,16#FF,16#FF,16#FF,16#FF>>).
|
-define(BROADCAST_MAC, <<16#FF,16#FF,16#FF,16#FF,16#FF,16#FF>>).
|
||||||
@ -43,7 +44,9 @@
|
|||||||
hostname :: binary(),
|
hostname :: binary(),
|
||||||
hole :: #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{},
|
||||||
|
|
||||||
|
last_seen :: integer() %% monotonic_time(second)
|
||||||
}).
|
}).
|
||||||
|
|
||||||
-record(state, {
|
-record(state, {
|
||||||
@ -161,6 +164,10 @@ 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),
|
||||||
|
|
||||||
|
%% endpoint定时扫描器
|
||||||
|
erlang:start_timer(?ENDPOINT_GC_INTERVAL, self(), endpoint_gc),
|
||||||
|
|
||||||
sdlan_domain_regedit:insert(Domain),
|
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}};
|
{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)]),
|
[NetworkId, ClientId, sdlan_util:format_mac(Mac), sdlan_ipaddr:int_to_ipv4(Ip)]),
|
||||||
%% 添加域名->ip的映射关系
|
%% 添加域名->ip的映射关系
|
||||||
sdlan_hostname_regedit:insert(Hostname, Domain, 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)}};
|
{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)}};
|
{noreply, State#state{endpoints = maps:remove(Mac, Endpoints)}};
|
||||||
|
|
||||||
%% 需要判断,client是属于当前网络的
|
%% 需要判断,client是属于当前网络的
|
||||||
|
%% TODO 被拒绝的endpoint需要通知其重新验证
|
||||||
handle_cast({update_hole, ClientId, Mac, Peer, NatType, V6Info}, State = #state{endpoints = Endpoints}) ->
|
handle_cast({update_hole, ClientId, Mac, Peer, NatType, V6Info}, State = #state{endpoints = Endpoints}) ->
|
||||||
case maps:find(Mac, Endpoints) of
|
case maps:find(Mac, Endpoints) of
|
||||||
{ok, Endpoint0 = #endpoint{ip = Ip, client_id = ClientId0, hole = OldHole}} when ClientId =:= ClientId0 ->
|
{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),
|
EndpointPeers = endpoint_peers([Mac], Endpoints),
|
||||||
sdlan_stun_pool:send_packets(EndpointPeers, EventPacket)
|
sdlan_stun_pool:send_packets(EndpointPeers, EventPacket)
|
||||||
end,
|
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}
|
{noreply, State}
|
||||||
end.
|
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}) ->
|
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({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
|
%% @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
|
||||||
|
|||||||
@ -64,6 +64,12 @@ message SDLNatChangedEvent {
|
|||||||
uint32 ip = 3;
|
uint32 ip = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 被清理掉的Endpoints
|
||||||
|
message SDLDropMacsEvent {
|
||||||
|
uint32 network_id = 1;
|
||||||
|
repeated bytes mac = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message SDLSendRegisterEvent {
|
message SDLSendRegisterEvent {
|
||||||
uint32 network_id = 1;
|
uint32 network_id = 1;
|
||||||
bytes dst_mac = 2;
|
bytes dst_mac = 2;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user