简化广播逻辑

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 -> error ->
PacketBytes = byte_size(Packet), PacketBytes = byte_size(Packet),
%% 广 %% 广
maps:foreach(fun(Mac, #endpoint{hole = Hole}) -> broadcast(fun(#endpoint{hole = Hole}) ->
case {Mac =/= SrcMac, Hole} of case Hole of
{true, #hole{peer = {NatIp, NatPort}}} -> #hole{peer = {NatIp, NatPort}} ->
gen_udp:send(Sock, NatIp, NatPort, Packet); gen_udp:send(Sock, NatIp, NatPort, Packet);
_ -> _ ->
ok ok
end end
end, Endpoints), end, [SrcMac], Endpoints),
%% client和stun之间必须有心跳机制保持nat映射可用udp包肯定可以到达对端的nat %% client和stun之间必须有心跳机制保持nat映射可用udp包肯定可以到达对端的nat
lager:debug("[sdlan_network] broadcast data networkd_id: ~p, src_mac: ~p, dst_mac: ~p", 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, mac = Mac,
ip = Ip 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 -> false ->
ok ok
end, end,
@ -423,9 +431,22 @@ handle_info({timeout, _, flow_report_ticker}, State = #state{network_id = Networ
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 = UsedMap}) -> handle_info({'EXIT', _Pid, shutdown}, State = #state{network_id = NetworkId, endpoints = Endpoints}) ->
lager:warning("[sdlan_network] network: ~p, get shutdown message", [NetworkId]), 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}; {stop, shutdown, State};
%% Channel进程退出, hole里面的数据也需要清理 %% Channel进程退出, hole里面的数据也需要清理
handle_info({'DOWN', _MRef, process, ChannelPid, Reason}, State = #state{network_id = NetworkId, endpoints = Endpoints}) -> 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()). State :: #state{}) -> term()).
terminate(Reason, #state{network_id = NetworkId, endpoints = Endpoints}) -> terminate(Reason, #state{network_id = NetworkId, endpoints = Endpoints}) ->
lager:debug("[sdlan_network] network: ~p, will terminate with reason: ~p", [NetworkId, Reason]), lager:debug("[sdlan_network] network: ~p, will terminate with reason: ~p", [NetworkId, Reason]),
broadcast_shutdown(Endpoints),
%% NetworkShutdownEvent = sdlan_pb:encode_msg(#sdl_network_shutdown_event {
maps:foreach(fun(_, #endpoint{channel_pid = ChannelPid, monitor_ref = MRef}) -> message = <<"Network shutdown">>
}),
broadcast(fun(#endpoint{channel_pid = ChannelPid, monitor_ref = MRef}) ->
is_reference(MRef) andalso demonitor(MRef), is_reference(MRef) andalso demonitor(MRef),
is_process_alive(ChannelPid) andalso sdlan_channel:stop(ChannelPid, normal) case is_pid(ChannelPid) andalso is_process_alive(ChannelPid) of
end, Endpoints), true ->
sdlan_channel:send_event(ChannelPid, ?PACKET_EVENT_NETWORK_SHUTDOWN, NetworkShutdownEvent),
sdlan_channel:stop(ChannelPid, normal);
false ->
ok
end
end, Endpoints),
ok. ok.
%% @private %% @private
@ -502,30 +531,20 @@ maybe_close_channel(#endpoint{channel_pid = ChannelPid0, monitor_ref = MRef0}) -
maybe_close_channel(_) -> maybe_close_channel(_) ->
ok. ok.
-spec broadcast(EventType :: integer(), Event :: binary(), ExcludeMac :: binary(), UsedMap :: map()) -> no_return(). -spec broadcast(Fun :: binary(), Endpoints :: map()) -> no_return().
broadcast(EventType, Event, ExcludeMac, UsedMap) when is_map(UsedMap), is_binary(ExcludeMac), is_integer(EventType), is_binary(Event) -> broadcast(Fun, Endpoints) when is_function(Fun, 1), is_map(Endpoints) ->
maps:foreach(fun(Mac, #endpoint{channel_pid = ChannelPid}) -> broadcast(Fun, [], Endpoints).
case is_process_alive(ChannelPid) andalso ExcludeMac /= Mac of
true ->
sdlan_channel:send_event(ChannelPid, EventType, Event);
false ->
ok
end
end, UsedMap).
broadcast_shutdown(UsedMap) when is_map(UsedMap) -> -spec broadcast(Fun :: binary(), ExcludeMacs :: [binary()], Endpoints :: map()) -> no_return().
maps:foreach(fun(_, #endpoint{channel_pid = ChannelPid}) -> broadcast(Fun, ExcludeMacs, Endpoints) when is_function(Fun, 1), is_map(Endpoints), is_list(ExcludeMacs) ->
case is_process_alive(ChannelPid) of maps:foreach(fun(Mac, Endpoint) ->
case lists:member(Mac, ExcludeMacs) of
true -> true ->
NetworkShutdownEvent = sdlan_pb:encode_msg(#sdl_network_shutdown_event { ok;
message = <<"Network shutdown">>
}),
sdlan_channel:send_event(ChannelPid, ?PACKET_EVENT_NETWORK_SHUTDOWN, NetworkShutdownEvent),
sdlan_channel:stop(ChannelPid, normal);
false -> false ->
ok Fun(Endpoint)
end end
end, UsedMap). 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()}.