简化广播逻辑

This commit is contained in:
anlicheng 2026-01-15 11:48:41 +08:00
parent e2fd4f18cb
commit 1ae54ab276

View File

@ -353,14 +353,14 @@ handle_cast({forward, Sock, SrcMac, DstMac, Packet}, State = #state{network_id =
error ->
PacketBytes = byte_size(Packet),
%% 广
maps:foreach(fun(Mac, #endpoint{hole = Hole}) ->
case {Mac =/= SrcMac, Hole} of
{true, #hole{peer = {NatIp, NatPort}}} ->
broadcast(fun(#endpoint{hole = Hole}) ->
case Hole of
#hole{peer = {NatIp, NatPort}} ->
gen_udp:send(Sock, NatIp, NatPort, Packet);
_ ->
ok
end
end, Endpoints),
end, [SrcMac], Endpoints),
%% client和stun之间必须有心跳机制保持nat映射可用udp包肯定可以到达对端的nat
lager:debug("[sdlan_network] broadcast data networkd_id: ~p, src_mac: ~p, dst_mac: ~p",
@ -401,7 +401,15 @@ handle_cast({update_hole, ClientId, Mac, Peer, NatType, V6Info}, State = #state{
mac = Mac,
ip = Ip
}),
broadcast(?PACKET_EVENT_NAT_CHANGED, NatChangedEvent, Mac, Endpoints);
broadcast(fun(#endpoint{channel_pid = ChannelPid}) ->
case is_process_alive(ChannelPid) of
true ->
sdlan_channel:send_event(ChannelPid, ?PACKET_EVENT_NAT_CHANGED, NatChangedEvent);
false ->
ok
end
end, [Mac], Endpoints);
false ->
ok
end,
@ -423,9 +431,22 @@ handle_info({timeout, _, flow_report_ticker}, State = #state{network_id = Networ
catch sdlan_api:network_forward_report(NetworkId, ForwardBytes),
{noreply, State#state{forward_bytes = 0}};
handle_info({'EXIT', _Pid, shutdown}, State = #state{network_id = NetworkId, endpoints = UsedMap}) ->
handle_info({'EXIT', _Pid, shutdown}, State = #state{network_id = NetworkId, endpoints = Endpoints}) ->
lager:warning("[sdlan_network] network: ~p, get shutdown message", [NetworkId]),
broadcast_shutdown(UsedMap),
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}) ->
@ -442,12 +463,20 @@ handle_info({'DOWN', _MRef, process, ChannelPid, Reason}, State = #state{network
State :: #state{}) -> term()).
terminate(Reason, #state{network_id = NetworkId, endpoints = Endpoints}) ->
lager:debug("[sdlan_network] network: ~p, will terminate with reason: ~p", [NetworkId, Reason]),
broadcast_shutdown(Endpoints),
%%
maps:foreach(fun(_, #endpoint{channel_pid = ChannelPid, monitor_ref = MRef}) ->
NetworkShutdownEvent = sdlan_pb:encode_msg(#sdl_network_shutdown_event {
message = <<"Network shutdown">>
}),
broadcast(fun(#endpoint{channel_pid = ChannelPid, monitor_ref = MRef}) ->
is_reference(MRef) andalso demonitor(MRef),
is_process_alive(ChannelPid) andalso sdlan_channel:stop(ChannelPid, normal)
end, Endpoints),
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),
ok.
%% @private
@ -502,30 +531,20 @@ maybe_close_channel(#endpoint{channel_pid = ChannelPid0, monitor_ref = MRef0}) -
maybe_close_channel(_) ->
ok.
-spec broadcast(EventType :: integer(), Event :: binary(), ExcludeMac :: binary(), UsedMap :: map()) -> no_return().
broadcast(EventType, Event, ExcludeMac, UsedMap) when is_map(UsedMap), is_binary(ExcludeMac), is_integer(EventType), is_binary(Event) ->
maps:foreach(fun(Mac, #endpoint{channel_pid = ChannelPid}) ->
case is_process_alive(ChannelPid) andalso ExcludeMac /= Mac of
true ->
sdlan_channel:send_event(ChannelPid, EventType, Event);
false ->
ok
end
end, UsedMap).
-spec broadcast(Fun :: binary(), Endpoints :: map()) -> no_return().
broadcast(Fun, Endpoints) when is_function(Fun, 1), is_map(Endpoints) ->
broadcast(Fun, [], Endpoints).
broadcast_shutdown(UsedMap) when is_map(UsedMap) ->
maps:foreach(fun(_, #endpoint{channel_pid = ChannelPid}) ->
case is_process_alive(ChannelPid) of
-spec broadcast(Fun :: binary(), ExcludeMacs :: [binary()], Endpoints :: map()) -> no_return().
broadcast(Fun, ExcludeMacs, Endpoints) when is_function(Fun, 1), is_map(Endpoints), is_list(ExcludeMacs) ->
maps:foreach(fun(Mac, Endpoint) ->
case lists:member(Mac, ExcludeMacs) of
true ->
NetworkShutdownEvent = sdlan_pb:encode_msg(#sdl_network_shutdown_event {
message = <<"Network shutdown">>
}),
sdlan_channel:send_event(ChannelPid, ?PACKET_EVENT_NETWORK_SHUTDOWN, NetworkShutdownEvent),
sdlan_channel:stop(ChannelPid, normal);
ok;
false ->
ok
Fun(Endpoint)
end
end, UsedMap).
end, Endpoints).
%% IpAddr: <<"192.168.172/24">>
-spec parse_ipaddr(IpAddr0 :: binary()) -> {IpAddr :: binary(), MaskLen :: integer()}.