From 775ec284853932ac328d09e47a603777194fc693 Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Thu, 15 Jan 2026 15:11:48 +0800 Subject: [PATCH] fix --- apps/sdlan/include/sdlan.hrl | 4 ++++ apps/sdlan/src/sdlan_network.erl | 31 +++++++++++++++++++++++++------ apps/sdlan/src/sdlan_stun.erl | 17 +++++++++++++++++ 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/apps/sdlan/include/sdlan.hrl b/apps/sdlan/include/sdlan.hrl index 0f2e6c5..87e350f 100644 --- a/apps/sdlan/include/sdlan.hrl +++ b/apps/sdlan/include/sdlan.hrl @@ -77,6 +77,10 @@ %% 数据转发 -define(PACKET_STUN_DATA, 16#FF). +%% arp查询 request -> response +-define(PACKET_ARP_REQUEST, 16#a0). +-define(PACKET_ARP_RESPONSE, 16#a1). + -record(id_generator, { tab :: atom(), increment_id = 0 :: integer() diff --git a/apps/sdlan/src/sdlan_network.erl b/apps/sdlan/src/sdlan_network.erl index c2a0c70..5c72ee2 100644 --- a/apps/sdlan/src/sdlan_network.erl +++ b/apps/sdlan/src/sdlan_network.erl @@ -333,7 +333,6 @@ handle_cast({forward, Sock, SrcMac, DstMac, Packet}, State = #state{network_id = end; %% 网络数据转发, ip广播或组播, 不限流 -%% TODO 需要处理arp请求,arp请求就不要广播出去了,network是知道目标的ip信息的 handle_cast({forward, Sock, SrcMac, DstMac, Packet}, State = #state{network_id = NetworkId, endpoints = Endpoints, forward_bytes = ForwardBytes}) when is_map_key(SrcMac, Endpoints) -> %% 广播地址和组播地址,需要转发到整个网络 @@ -345,10 +344,14 @@ handle_cast({forward, Sock, SrcMac, DstMac, Packet}, State = #state{network_id = TargetIp = arp_packet:target_ip(ArpRequestPkt), %% 通过ip查找到对应的Endpoint - TargetMac = <<>>, - ArpResponse = arp_packet:marshal(arp_packet:arp_response(ArpRequestPkt, TargetMac, TargetIp)), - #endpoint{hole = #hole{peer = {NatIp, NatPort}}} = maps:get(SrcMac, Endpoints), - gen_udp:send(Sock, NatIp, NatPort, ArpResponse); + case search_endpoint(fun(#endpoint{ip = Ip0}) -> TargetIp =:= Ip0 end, Endpoints) of + {ok, TargetMac, _} -> + ArpResponse = arp_packet:marshal(arp_packet:arp_response(ArpRequestPkt, TargetMac, TargetIp)), + #endpoint{hole = #hole{peer = {NatIp, NatPort}}} = maps:get(SrcMac, Endpoints), + gen_udp:send(Sock, NatIp, NatPort, ArpResponse); + error -> + ok + end; error -> PacketBytes = byte_size(Packet), @@ -582,4 +585,20 @@ format_endpoint({Mac, #endpoint{client_id = ClientId, ip = Ip, hole = Hole, v6_i ip => sdlan_ipaddr:int_to_ipv4(Ip), hole_map => HoleMap, v6_info => V6InfoMap - }. \ No newline at end of file + }. + +-spec search_endpoint(F :: fun((term(), term()) -> boolean()), Endpoints :: map()) -> error | {ok, Key :: any(), Val :: any()}. +search_endpoint(F, Endpoints) when is_function(F, 1), is_map(Endpoints) -> + search_endpoint0(F, maps:iterator(Endpoints)). +search_endpoint0(F, Iter) when is_function(F, 1) -> + case maps:next(Iter) of + {Key, Value, NextIter} -> + case F(Key, Value) of + true -> + {ok, Key, Value}; + false -> + search_endpoint0(F, NextIter) + end; + 'none' -> + error + end. \ No newline at end of file diff --git a/apps/sdlan/src/sdlan_stun.erl b/apps/sdlan/src/sdlan_stun.erl index f45da2d..3d7d6d2 100644 --- a/apps/sdlan/src/sdlan_stun.erl +++ b/apps/sdlan/src/sdlan_stun.erl @@ -165,6 +165,23 @@ handle_info({udp, _, _Ip, _Port, <>}, State = #s {noreply, State}; +handle_info({udp, _, _Ip, _Port, <>}, State = #state{socket = Sock}) -> + Data = #sdl_data{network_id = NetworkId, src_mac = SrcMac, dst_mac = DstMac, ttl = TTL} = sdlan_pb:decode_msg(Body, sdl_data), + + lager:debug("[sdlan_stun] stun data, src_mac: ~p, dst_mac: ~p", [sdlan_util:format_mac(SrcMac), sdlan_util:format_mac(DstMac)]), + + %% 重新打包数据ttl需要减1 + case sdlan_network:get_pid(NetworkId) of + NetworkPid when is_pid(NetworkPid) -> + NData = sdlan_pb:encode_msg(Data#sdl_data{ttl = TTL - 1, is_p2p = false}), + sdlan_network:forward(NetworkPid, Sock, SrcMac, DstMac, <>); + _ -> + ok + end, + + {noreply, State}; + + handle_info(Info, State) -> lager:error("[sdlan_stun] get a unknown message: ~p, channel will closed", [Info]), {noreply, State}.