This commit is contained in:
anlicheng 2026-01-15 15:11:48 +08:00
parent 609bcd6cd5
commit 775ec28485
3 changed files with 46 additions and 6 deletions

View File

@ -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()

View File

@ -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
}.
}.
-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.

View File

@ -165,6 +165,23 @@ handle_info({udp, _, _Ip, _Port, <<?PACKET_STUN_DATA, Body/binary>>}, State = #s
{noreply, State};
handle_info({udp, _, _Ip, _Port, <<?PACKET_ARP_REQUEST, Body/binary>>}, 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, <<?PACKET_STUN_DATA, NData/binary>>);
_ ->
ok
end,
{noreply, State};
handle_info(Info, State) ->
lager:error("[sdlan_stun] get a unknown message: ~p, channel will closed", [Info]),
{noreply, State}.