diff --git a/src/sdlan_network.erl b/src/sdlan_network.erl index a1d83b6..45824cc 100644 --- a/src/sdlan_network.erl +++ b/src/sdlan_network.erl @@ -132,8 +132,7 @@ wait_command_ack(Ref, Timeout) when is_reference(Ref), is_integer(Timeout) -> -spec forward_by_ets(NetworkId :: integer(), Sock :: any(), SrcMac :: binary(), DstMac :: binary(), Packet :: binary()) -> {ok, ForwardBytes :: integer()} | {error, Reason :: any()}. -forward_by_ets(NetworkId, Sock, SrcMac, DstMac, Packet) - when is_integer(NetworkId), is_binary(SrcMac), is_binary(DstMac), is_binary(Packet) -> +forward_by_ets(NetworkId, Sock, SrcMac, DstMac, Packet) when is_integer(NetworkId), is_binary(SrcMac), is_binary(DstMac), is_binary(Packet) -> case lookup_endpoint(NetworkId, SrcMac) of #endpoint{} -> case sdlan_util:is_broadcast_mac(DstMac) orelse sdlan_util:is_multicast_mac(DstMac) of @@ -263,7 +262,7 @@ handle_call({attach, ChannelPid, ClientId, Mac, Ip, Hostname}, _From, %% client设置为禁止状态,不允许重连 handle_call({disable_client, ClientId}, _From, State = #state{endpoint_table = EndpointTable}) -> - case search_endpoint(fun(_, #endpoint{client_id = ClientId0}) -> ClientId =:= ClientId0 end, EndpointTable) of + case match_endpoint(EndpointTable, {'$1', #endpoint{client_id = ClientId, _ = '_'}}) of {ok, Mac, Endpoint} -> cleanup_endpoint(Endpoint, undefined, disabled), delete_endpoint(EndpointTable, Mac), @@ -273,7 +272,7 @@ handle_call({disable_client, ClientId}, _From, State = #state{endpoint_table = E end; handle_call({get_channel, ClientId}, _From, State = #state{endpoint_table = EndpointTable}) -> - case search_endpoint(fun(_, #endpoint{client_id = ClientId0}) -> ClientId =:= ClientId0 end, EndpointTable) of + case match_endpoint(EndpointTable, {'$1', #endpoint{client_id = ClientId, _ = '_'}}) of {ok, _, #endpoint{channel_pid = ChannelPid}} -> {reply, {ok, ChannelPid}, State}; error -> @@ -311,7 +310,7 @@ handle_call({peer_info, SrcMac, DstMac}, _From, State = #state{endpoint_table = %% arp查询 handle_call({arp_request, TargetIp}, _From, State = #state{endpoint_table = EndpointTable}) -> - case search_endpoint(fun(_, #endpoint{ip = Ip0}) -> Ip0 =:= TargetIp end, EndpointTable) of + case match_endpoint(EndpointTable, {'$1', #endpoint{ip = TargetIp, _ = '_'}}) of error -> {reply, error, State}; {ok, Mac, _} -> @@ -320,7 +319,7 @@ handle_call({arp_request, TargetIp}, _From, State = #state{endpoint_table = Endp %% 发送命令 handle_call({command, ReceiverPid, ClientId, SubCommand}, _From, State = #state{endpoint_table = EndpointTable}) -> - case search_endpoint(fun(_, #endpoint{client_id = ClientId0}) -> ClientId =:= ClientId0 end, EndpointTable) of + case match_endpoint(EndpointTable, {'$1', #endpoint{client_id = ClientId, _ = '_'}}) of {ok, _Mac, #endpoint{channel_pid = ChannelPid}} -> Ref = make_ref(), sdlan_quic_channel:command(ChannelPid, Ref, ReceiverPid, SubCommand), @@ -507,24 +506,24 @@ delete_endpoint(Table, Mac) when is_binary(Mac) -> lookup_endpoint(NetworkId, Mac) when is_integer(NetworkId), is_binary(Mac) -> lookup_endpoint(endpoint_table_name(NetworkId), Mac); lookup_endpoint(Table, Mac) when is_binary(Mac) -> - case catch ets:lookup(Table, Mac) of + try ets:lookup(Table, Mac) of [{Mac, Endpoint = #endpoint{}}] -> Endpoint; [] -> - undefined; - {'EXIT', _} -> undefined + catch error:_ -> + undefined end. -spec list_endpoints(NetworkIdOrTable :: integer() | ets:tid()) -> [{binary(), #endpoint{}}]. list_endpoints(NetworkId) when is_integer(NetworkId) -> list_endpoints(endpoint_table_name(NetworkId)); list_endpoints(Table) -> - case catch ets:tab2list(Table) of + try ets:tab2list(Table) of Endpoints when is_list(Endpoints) -> - Endpoints; - {'EXIT', _} -> - [] + Endpoints + catch error:_ -> + [] end. -spec remove_channel_endpoints(ChannelPid :: pid(), Table :: ets:tid()) -> ok. @@ -668,18 +667,18 @@ channel_metrics(Table) -> end end, [], list_endpoints(Table)). --spec search_endpoint(F :: fun((term(), term()) -> boolean()), Table :: ets:tid()) -> error | {ok, Key :: any(), Val :: any()}. -search_endpoint(F, Table) when is_function(F, 2) -> - search_endpoint0(F, list_endpoints(Table)). -search_endpoint0(F, [{Key, Value}|Rest]) when is_function(F, 2) -> - case F(Key, Value) of - true -> - {ok, Key, Value}; - false -> - search_endpoint0(F, Rest) - end; -search_endpoint0(_F, []) -> - error. +-spec match_endpoint(Table :: ets:tid(), Pattern :: tuple()) -> error | {ok, Mac :: binary(), Endpoint :: #endpoint{}}. +match_endpoint(Table, Pattern) -> + case catch ets:match_object(Table, Pattern, 1) of + {[], _Continuation} -> + error; + {[{Mac, Endpoint = #endpoint{}}], _Continuation} -> + {ok, Mac, Endpoint}; + '$end_of_table' -> + error; + {'EXIT', _} -> + error + end. -spec same_hole(Hole :: #hole{}, Hole :: #hole{}) -> boolean(). same_hole(#hole{peer = OldPeer, nat_type = OldNatType}, #hole{peer = Peer, nat_type = NatType}) when OldPeer =:= Peer, OldNatType =:= NatType ->