diff --git a/apps/sdlan/src/sdlan_api.erl b/apps/sdlan/src/sdlan_api.erl index c0d60ad..98207fa 100644 --- a/apps/sdlan/src/sdlan_api.erl +++ b/apps/sdlan/src/sdlan_api.erl @@ -15,7 +15,7 @@ -export([get_all_networks/0, get_network/1]). -export([auth_token/3, node_online/3, node_offline/2, flow_report/5, network_forward_report/2, auth_network_code/3]). --export([assign_ip_address/5]). +-export([assign_ip_address/3]). -spec get_all_networks() -> {ok, [NetworkId :: integer()]} | {error, Reason :: any()}. get_all_networks() -> @@ -78,19 +78,25 @@ auth_network_code(ClientId, NetworkCode, Version) when is_binary(ClientId), is_b end. %% 请求ip地址的分配 -assign_ip_address(NetworkId, ClientId, Mac, RetainIp, HostName) when is_integer(NetworkId), is_binary(ClientId), is_binary(Mac), is_integer(RetainIp), is_binary(HostName) -> +-spec assign_ip_address(NetworkId :: integer(), ClientId :: binary(), Mac :: binary()) -> {ok, map()} | {error, Reason :: any()}. +assign_ip_address(NetworkId, ClientId, Mac) when is_integer(NetworkId), is_binary(ClientId), is_binary(Mac) -> Params = #{ <<"network_id">> => NetworkId, <<"client_id">> => ClientId, - <<"mac">> => Mac, - <<"retain_ip">> => RetainIp, - <<"host_name">> => HostName + <<"mac">> => Mac }, case catch do_post("assign_ip_address", Params) of {ok, Resp} -> case catch jiffy:decode(Resp, [return_maps]) of - Result when is_map(Result) -> - {ok, Result}; + Json when is_map(Json) -> + case Json of + #{<<"result">> := Result} -> + {ok, Result}; + #{<<"error">> := #{<<"message">> := Message}} -> + {error, Message}; + _ -> + {error, <<"invalid response">>} + end; {error, Reason} -> {error, Reason} end; diff --git a/apps/sdlan/src/sdlan_network.erl b/apps/sdlan/src/sdlan_network.erl index 5672296..2f9fd01 100644 --- a/apps/sdlan/src/sdlan_network.erl +++ b/apps/sdlan/src/sdlan_network.erl @@ -22,7 +22,7 @@ %% API -export([start_link/2]). -export([get_name/1, get_pid/1, assign_ip_addr/6, peer_info/3, unregister/3, debug_info/1, get_network_id/1, get_used_map/1]). --export([forward/5, update_hole/6, disable_client/2, get_channel/2, dropout_client/2, reload/1]). +-export([forward/5, update_hole/6, disable_client/2, get_channel/2, dropout_client/2]). -export([test_event/1]). %% gen_server callbacks @@ -33,9 +33,10 @@ nat_type :: integer() }). -%% ip的使用信息, 记录主机的动态信息 --record(host, { +%% ip的使用信息, 记录Node的运行时状态信息 +-record(endpoint, { client_id :: binary(), + ip :: integer(), channel_pid :: undefined | pid(), monitor_ref :: undefined | reference(), hole :: undefined | #hole{}, @@ -60,11 +61,7 @@ %% 同一个网络下公用的密钥, 采用AES-256加密算法;随机生成 aes_key :: binary(), - %% ip分配器 - %% 记录当前网络下的全部ip地址 - ips = [] :: [Ip :: integer()], - - %% 记录已经使用了的ip, #{mac :: integer() => Host :: #host{}} + %% 记录已经使用了的ip, #{mac :: integer() => #endpoint{}} used_map = #{} }). @@ -84,10 +81,6 @@ get_pid(Id) when is_integer(Id) -> get_name(Id) when is_integer(Id) -> list_to_atom("sdlan_network:" ++ integer_to_list(Id)). --spec reload(Pid :: pid()) -> ok | {error, Reason :: any()}. -reload(Pid) when is_pid(Pid) -> - gen_server:call(Pid, reload). - -spec assign_ip_addr(Pid :: pid(), ChannelPid :: pid(), ClientId :: binary(), Mac :: binary(), NetAddr :: integer(), HostName :: binary()) -> {ok, Domain :: binary(), NetAddr :: integer(), MaskLen :: integer(), AesKey :: binary()} | {error, Reason :: any()}. assign_ip_addr(Pid, ChannelPid, ClientId, Mac, NetAddr, HostName) when is_pid(Pid), is_pid(ChannelPid), is_binary(ClientId), is_binary(Mac), is_integer(NetAddr) -> @@ -160,8 +153,8 @@ init([Id]) when is_integer(Id) -> ignore; {ok, #{<<"id">> := Id, <<"name">> := Name, <<"domain">> := Domain, <<"ipaddr">> := IpAddr0, <<"owner_id">> := OwnerId}} -> {IpAddr, MaskLen} = parse_ipaddr(IpAddr0), - Ips = sdlan_ipaddr:ips(IpAddr, MaskLen), AesKey = sdlan_util:rand_byte(32), + %% 限流key ThrottleKey = list_to_atom("network_throttle:" ++ integer_to_list(Id)), %% 绑定到资源协调器 @@ -169,15 +162,9 @@ init([Id]) when is_integer(Id) -> %% 每分钟汇报一次转发的流量 erlang:start_timer(?FLOW_REPORT_INTERVAL, self(), flow_report_ticker), - - %% 创建数据库表 - create_mnesia_table(Id), - - lager:debug("[sdlan_network] network: ~p, ips: ~p", [Id, lists:map(fun sdlan_ipaddr:int_to_ipv4/1, Ips)]), - sdlan_domain_regedit:insert(Domain), - {ok, #state{network_id = Id, name = Name, domain = Domain, ipaddr = IpAddr, owner_id = OwnerId, mask_len = MaskLen, ips = Ips, aes_key = AesKey, throttle_key = ThrottleKey}}; + {ok, #state{network_id = Id, name = Name, domain = Domain, ipaddr = IpAddr, owner_id = OwnerId, mask_len = MaskLen, aes_key = AesKey, throttle_key = ThrottleKey}}; {error, Reason} -> lager:warning("[sdlan_network] load network: ~p, get error: ~p", [Id, Reason]), ignore @@ -193,58 +180,23 @@ init([Id]) when is_integer(Id) -> {noreply, NewState :: #state{}, timeout() | hibernate} | {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} | {stop, Reason :: term(), NewState :: #state{}}). -%% 重新加载网络信息 -handle_call(reload, _From, State = #state{network_id = Id, ipaddr = OldIpAddr, mask_len = OldMarkLen, used_map = UsedMap}) -> - case sdlan_api:get_network(Id) of - {ok, #{<<"name">> := Name, <<"ipaddr">> := IpAddr0, <<"owner_id">> := OwnerId}} -> - {IpAddr, MaskLen} = parse_ipaddr(IpAddr0), - case OldIpAddr =:= IpAddr andalso OldMarkLen =:= MaskLen of - true -> - {reply, ok, State#state{name = Name, owner_id = OwnerId}}; - false -> - lager:debug("[sdlan_networkd] network_id: ~p, reload will close all channels", [Id]), - Ips = sdlan_ipaddr:ips(IpAddr, MaskLen), - %% 整个网络下的设备都需要重新连接 - maps:foreach(fun(_, #host{channel_pid = ChannelPid, monitor_ref = MRef}) -> - is_reference(MRef) andalso demonitor(MRef), - is_process_alive(ChannelPid) andalso sdlan_channel:stop(ChannelPid, normal) - end, UsedMap), - %% 清理掉数据库中的数据 - ok = client_model:delete_clients(Id), - - {reply, ok, State#state{name = Name, ipaddr = IpAddr, - owner_id = OwnerId, mask_len = MaskLen, ips = Ips, used_map = maps:new()}} - end; - {error, Reason} -> - lager:warning("[sdlan_network] reload network: ~p, get error: ~p", [Id, Reason]), - {reply, {error, Reason}, State} - end; - %% 给客户端分配ip地址 -handle_call({assign_ip_addr, ChannelPid, ClientId, Mac, NetAddr0, HostName}, _From, - State = #state{network_id = NetworkId, domain = Domain, ips = Ips, used_map = UsedMap, mask_len = MaskLen, aes_key = AesKey}) -> +handle_call({assign_ip_addr, ChannelPid, ClientId, Mac}, _From, + State = #state{network_id = NetworkId, domain = Domain, used_map = UsedMap, mask_len = MaskLen, aes_key = AesKey}) -> - %% 分配ip地址的时候,以mac地址为唯一基准 - lager:debug("[sdlan_network] alloc_ip, network_id: ~p, ips: ~p, client_id: ~p, mac: ~p, net_addr: ~p", - [NetworkId, Ips, ClientId, sdlan_util:format_mac(Mac), sdlan_ipaddr:int_to_ipv4(NetAddr0)]), - - case client_model:alloc_ip(NetworkId, Ips, ClientId, Mac, NetAddr0, HostName) of - {ok, Ip} -> + case sdlan_api:assign_ip_address(NetworkId, ClientId, Mac) of + {ok, #{<<"ip">> := Ip, <<"host_name">> := HostName}} -> + %% 分配ip地址的时候,以mac地址为唯一基准 + lager:debug("[sdlan_network] alloc_ip, network_id: ~p, client_id: ~p, mac: ~p, net_addr: ~p", + [NetworkId, ClientId, sdlan_util:format_mac(Mac), sdlan_ipaddr:int_to_ipv4(Ip)]), %% 关闭之前的channel maybe_close_channel(maps:get(Mac, UsedMap, undefined)), - %% 添加域名->ip的映射关系 - case HostName =/= <<>> of - true -> - FullHostname = <>, - sdlan_hostname_regedit:insert(FullHostname, Ip); - false -> - ok - end, + sdlan_hostname_regedit:insert(HostName, Domain, Ip), %% 建立到新的channel之间的关系 MRef = monitor(process, ChannelPid), - NUsedMap = maps:put(Mac, #host{client_id = ClientId, channel_pid = ChannelPid, monitor_ref = MRef}, UsedMap), + NUsedMap = maps:put(Mac, #endpoint{client_id = ClientId, ip = Ip, channel_pid = ChannelPid, monitor_ref = MRef}, UsedMap), {reply, {ok, Domain, Ip, MaskLen, AesKey}, State#state{used_map = NUsedMap}}; {error, Reason} -> @@ -252,7 +204,7 @@ handle_call({assign_ip_addr, ChannelPid, ClientId, Mac, NetAddr0, HostName}, _Fr end; handle_call(get_used_map, _From, State = #state{used_map = UsedMap}) -> - UsedInfos = maps:map(fun(_, #host{hole = Hole, v6_info = V6Info}) -> + UsedInfos = maps:map(fun(_, #endpoint{hole = Hole, v6_info = V6Info}) -> HoleMap = case Hole of #hole{peer = {NatIp, NatPort}} -> #{ @@ -279,40 +231,31 @@ handle_call(get_used_map, _From, State = #state{used_map = UsedMap}) -> %% client设置为禁止状态,不允许重连 handle_call({disable_client, ClientId}, _From, State = #state{network_id = NetworkId, used_map = UsedMap}) -> - case lists:search(fun({_, #host{client_id = ClientId0}}) -> ClientId =:= ClientId0 end, maps:to_list(UsedMap)) of - {value, {Mac, #host{channel_pid = ChannelPid, monitor_ref = MRef}}} -> + case lists:search(fun({_, #endpoint{client_id = ClientId0}}) -> ClientId =:= ClientId0 end, maps:to_list(UsedMap)) of + {value, {Mac, #endpoint{channel_pid = ChannelPid, monitor_ref = MRef}}} -> is_reference(MRef) andalso demonitor(MRef), sdlan_channel:stop(ChannelPid, disable), NUsedMap = maps:remove(Mac, UsedMap), - %% 将客户端设置为禁止状态 - client_model:disable_client(NetworkId, ClientId), - {reply, ok, State#state{used_map = NUsedMap}}; false -> {reply, error, State} end; handle_call({get_channel, ClientId}, _From, State = #state{used_map = UsedMap}) -> - case lists:search(fun({_, #host{client_id = ClientId0}}) -> ClientId =:= ClientId0 end, maps:to_list(UsedMap)) of - {value, {_Ip, #host{channel_pid = ChannelPid}}} -> + case lists:search(fun({_, #endpoint{client_id = ClientId0}}) -> ClientId =:= ClientId0 end, maps:to_list(UsedMap)) of + {value, {_Ip, #endpoint{channel_pid = ChannelPid}}} -> {reply, {ok, ChannelPid}, State}; false -> {reply, error, State} end; %% 区别在于是否关闭掉channel, 这里是在网络迁移中的功能; drop的时候需要从当前网络中移除 -handle_call({dropout_client, ClientId}, _From, State = #state{network_id = NetworkId, used_map = UsedMap}) -> - case lists:search(fun({_, #host{client_id = ClientId0}}) -> ClientId =:= ClientId0 end, maps:to_list(UsedMap)) of - {value, {Mac, #host{channel_pid = ChannelPid, monitor_ref = MRef}}} -> +handle_call({dropout_client, ClientId}, _From, State = #state{used_map = UsedMap}) -> + case lists:search(fun({_, #endpoint{client_id = ClientId0}}) -> ClientId =:= ClientId0 end, maps:to_list(UsedMap)) of + {value, {Mac, #endpoint{channel_pid = ChannelPid, monitor_ref = MRef}}} -> is_reference(MRef) andalso demonitor(MRef), NUsedMap = maps:remove(Mac, UsedMap), - %% 从数据库删除 - case client_model:delete_client(NetworkId, ClientId) of - {ok, #client{host_name = HostName}} -> - {reply, {ok, ChannelPid, HostName}, State#state{used_map = NUsedMap}}; - {error, _} -> - {reply, error, State} - end; + {reply, {ok, ChannelPid}, State#state{used_map = NUsedMap}}; false -> {reply, error, State} end; @@ -323,10 +266,10 @@ handle_call(get_network_id, _From, State = #state{network_id = NetworkId}) -> %% 网络存在的nat_peer信息 handle_call({peer_info, SrcMac, DstMac}, _From, State = #state{used_map = UsedMap}) -> case maps:find(DstMac, UsedMap) of - {ok, #host{channel_pid = DstChannelPid, hole = #hole{peer = DstNatPeer, nat_type = DstNatType}, v6_info = DstV6Info}} -> + {ok, #endpoint{channel_pid = DstChannelPid, hole = #hole{peer = DstNatPeer, nat_type = DstNatType}, v6_info = DstV6Info}} -> %% 让目标服务器发送sendRegister事件(2024-06-25 新增,提高打洞的成功率) case maps:get(SrcMac, UsedMap, undefined) of - #host{hole = #hole{peer = {SrcNatIp, SrcNatPort}, nat_type = NatType}, v6_info = SrcV6Info} -> + #endpoint{hole = #hole{peer = {SrcNatIp, SrcNatPort}, nat_type = NatType}, v6_info = SrcV6Info} -> Event = sdlan_pb:encode_msg(#sdl_send_register_event { dst_mac = SrcMac, nat_ip = sdlan_ipaddr:ipv4_to_int(SrcNatIp), @@ -343,21 +286,13 @@ handle_call({peer_info, SrcMac, DstMac}, _From, State = #state{used_map = UsedMa {reply, error, State} end; -handle_call(debug_info, _From, State = #state{network_id = NetworkId, ipaddr = IpAddr, mask_len = MaskLen, owner_id = OwnerId, ips = Ips, used_map = UsedMap}) -> +handle_call(debug_info, _From, State = #state{network_id = NetworkId, ipaddr = IpAddr, mask_len = MaskLen, owner_id = OwnerId, used_map = UsedMap}) -> Reply = #{ <<"network_id">> => NetworkId, <<"ipaddr">> => IpAddr, <<"mask_len">> => MaskLen, <<"owner_id">> => OwnerId, - <<"ips">> => lists:map(fun sdlan_ipaddr:int_to_ipv4/1, Ips), - <<"used_ips">> => lists:map(fun({_, Host = #host{client_id = ClientId}}) -> - case client_model:get_client(NetworkId, ClientId) of - error -> - #{}; - {ok, #client{mac = Mac, ip = Ip}} -> - format_host(Host, Ip, Mac) - end - end, maps:to_list(UsedMap)) + <<"used_ips">> => lists:map(fun format_endpoint/1, maps:to_list(UsedMap)) }, {reply, Reply, State}. @@ -373,29 +308,19 @@ handle_cast({forward, Sock, SrcMac, DstMac, Packet}, State = #state{network_id = PacketBytes = byte_size(Packet), case maps:find(DstMac, UsedMap) of - {ok, #host{hole = #hole{peer = Peer = {Ip, Port}}}} -> - case throttle:check(sdlan_network, ThrottleKey) of - {ok, _RestCount, _LeftToReset} -> + {ok, #endpoint{hole = #hole{peer = Peer = {Ip, Port}}}} -> + case limiting_check(ThrottleKey) of + pass -> %% client和stun之间必须有心跳机制保持nat映射可用,并且通过服务转发的udp包肯定可以到达对端的nat lager:debug("[sdlan_network] forward data networkd_id: ~p, src_mac: ~p, dst_mac: ~p, hole: ~p", [NetworkId, sdlan_util:format_mac(SrcMac), sdlan_util:format_mac(DstMac), Peer]), gen_udp:send(Sock, Ip, Port, Packet), {noreply, State#state{forward_bytes = ForwardBytes + PacketBytes}}; - {limit_exceeded, 0, _LeftToReset} -> - %% 尝试获取其他网络是否有让渡的资源 - case sdlan_network_coordinator:checkout() of - ok -> - lager:debug("[sdlan_network] use release forward data networkd_id: ~p, src_mac: ~p, dst_mac: ~p, hole: ~p", - [NetworkId, sdlan_util:format_mac(SrcMac), sdlan_util:format_mac(DstMac), Peer]), - - gen_udp:send(Sock, Ip, Port, Packet), - {noreply, State#state{forward_bytes = ForwardBytes + PacketBytes}}; - error -> - lager:notice("[sdlan_network] networkd_id: ~p, src_mac: ~p, dst_mac: ~p, rate limited, discard", - [NetworkId, sdlan_util:format_mac(SrcMac), sdlan_util:format_mac(DstMac)]), - {noreply, State} - end + denied -> + lager:notice("[sdlan_network] networkd_id: ~p, src_mac: ~p, dst_mac: ~p, rate limited, discard", + [NetworkId, sdlan_util:format_mac(SrcMac), sdlan_util:format_mac(DstMac)]), + {noreply, State} end; {ok, _} -> lager:debug("[sdlan_network] networkd_id: ~p, src_mac: ~p, dst_mac: ~p, hole not found", @@ -408,6 +333,7 @@ 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, used_map = UsedMap, forward_bytes = ForwardBytes}) when is_map_key(SrcMac, UsedMap) -> %% 广播地址和组播地址,需要转发到整个网络 @@ -415,10 +341,9 @@ handle_cast({forward, Sock, SrcMac, DstMac, Packet}, State = #state{network_id = true -> PacketBytes = byte_size(Packet), %% 消息广播 - maps:foreach(fun(Mac, #host{hole = Hole}) -> + maps:foreach(fun(Mac, #endpoint{hole = Hole}) -> case {Mac =/= SrcMac, Hole} of {true, #hole{peer = {NatIp, NatPort}}} -> - lager:debug("[sdlan_network] call me here"), gen_udp:send(Sock, NatIp, NatPort, Packet); _ -> ok @@ -447,16 +372,16 @@ handle_cast({unregister, _ClientId, Mac}, State = #state{network_id = NetworkId, case maps:take(Mac, UsedMap) of error -> {noreply, State}; - {#host{channel_pid = ChannelPid, monitor_ref = MRef}, NUsedMap} -> + {#endpoint{channel_pid = ChannelPid, monitor_ref = MRef}, NUsedMap} -> is_reference(MRef) andalso demonitor(MRef), sdlan_channel:stop(ChannelPid, normal), {noreply, State#state{used_map = NUsedMap}} end; %% 需要判断,client是属于当前网络的 -handle_cast({update_hole, ClientId, Mac, Peer, NatType, V6Info}, State = #state{network_id = NetworkId, used_map = UsedMap}) -> - case {maps:find(Mac, UsedMap), client_model:get_client(NetworkId, ClientId)} of - {{ok, Host0 = #host{client_id = ClientId0, hole = OldHole}}, {ok, #client{ip = Ip}}} when ClientId =:= ClientId0 -> +handle_cast({update_hole, ClientId, Mac, Peer, NatType, V6Info}, State = #state{used_map = UsedMap}) -> + case maps:find(Mac, UsedMap) of + {ok, Endpoint0 = #endpoint{client_id = ClientId0, ip = Ip, hole = OldHole}} when ClientId =:= ClientId0 -> case OldHole =:= undefined orelse (OldHole#hole.peer =/= Peer orelse OldHole#hole.nat_type =/= NatType) of true -> NatChangedEvent = sdlan_pb:encode_msg(#sdl_nat_changed_event{ @@ -467,9 +392,9 @@ handle_cast({update_hole, ClientId, Mac, Peer, NatType, V6Info}, State = #state{ false -> ok end, - Host = Host0#host{hole = #hole{peer = Peer, nat_type = NatType}, v6_info = V6Info}, + Endpoint = Endpoint0#endpoint{hole = #hole{peer = Peer, nat_type = NatType}, v6_info = V6Info}, - {noreply, State#state{used_map = maps:put(Mac, Host, UsedMap)}}; + {noreply, State#state{used_map = maps:put(Mac, Endpoint, UsedMap)}}; _ -> {noreply, State} end. @@ -492,7 +417,7 @@ handle_info({'EXIT', _Pid, shutdown}, State = #state{network_id = NetworkId, use %% Channel进程退出, hole里面的数据也需要清理 handle_info({'DOWN', _MRef, process, ChannelPid, Reason}, State = #state{network_id = NetworkId, used_map = UsedMap}) -> lager:notice("[sdlan_network] network_id: ~p, channel_pid: ~p, close with reason: ~p", [NetworkId, ChannelPid, Reason]), - NUsedMap = maps:filter(fun(_, #host{channel_pid = ChannelPid0}) -> ChannelPid =/= ChannelPid0 end, UsedMap), + NUsedMap = maps:filter(fun(_, #endpoint{channel_pid = ChannelPid0}) -> ChannelPid =/= ChannelPid0 end, UsedMap), {noreply, State#state{used_map = NUsedMap}}. %% @private @@ -505,6 +430,11 @@ handle_info({'DOWN', _MRef, process, ChannelPid, Reason}, State = #state{network terminate(Reason, #state{network_id = NetworkId, used_map = UsedMap}) -> lager:debug("[sdlan_network] network: ~p, will terminate with reason: ~p", [NetworkId, Reason]), broadcast_shutdown(UsedMap), + %% 整个网络下的设备都需要重新连接 + maps:foreach(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, UsedMap), ok. %% @private @@ -519,21 +449,23 @@ code_change(_OldVsn, State = #state{}, _Extra) -> %%% Internal functions %%%=================================================================== -%% 创建数据库表 --spec create_mnesia_table(NetworkId :: integer()) -> no_return(). -create_mnesia_table(NetworkId) when is_integer(NetworkId) -> - Tab = client_model:get_table_name(NetworkId), - Tables = mnesia:system_info(tables), - case lists:member(Tab, Tables) of - true -> - ok; - false -> - Res = client_model:create_table(Tab), - lager:debug("[sdlan_network] create table result: ~p", [Res]) +-spec limiting_check(ThrottleKey :: any()) -> pass | denied. +limiting_check(ThrottleKey) -> + case throttle:check(sdlan_network, ThrottleKey) of + {ok, _RestCount, _LeftToReset} -> + pass; + {limit_exceeded, 0, _LeftToReset} -> + %% 尝试获取其他网络是否有让渡的资源 + case sdlan_network_coordinator:checkout() of + ok -> + pass; + error -> + denied + end end. --spec maybe_close_channel(undefined | #host{}) -> no_return(). -maybe_close_channel(#host{channel_pid = ChannelPid0, monitor_ref = MRef0}) -> +-spec maybe_close_channel(undefined | #endpoint{}) -> no_return(). +maybe_close_channel(#endpoint{channel_pid = ChannelPid0, monitor_ref = MRef0}) -> case is_pid(ChannelPid0) andalso is_process_alive(ChannelPid0) of true -> is_reference(MRef0) andalso demonitor(MRef0), @@ -546,7 +478,7 @@ maybe_close_channel(_) -> -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, #host{channel_pid = ChannelPid}) -> + 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); @@ -556,7 +488,7 @@ broadcast(EventType, Event, ExcludeMac, UsedMap) when is_map(UsedMap), is_binary end, UsedMap). broadcast_shutdown(UsedMap) when is_map(UsedMap) -> - maps:foreach(fun(_, #host{channel_pid = ChannelPid}) -> + maps:foreach(fun(_, #endpoint{channel_pid = ChannelPid}) -> case is_process_alive(ChannelPid) of true -> NetworkShutdownEvent = sdlan_pb:encode_msg(#sdl_network_shutdown_event { @@ -580,18 +512,18 @@ parse_ipaddr(IpAddr0) when is_binary(IpAddr0) -> {IpAddr0, 24} end. --spec format_host(Host :: #host{}, Ip :: integer(), Mac :: binary()) -> map(). -format_host(#host{client_id = ClientId, hole = Hole, v6_info = V6Info}, Ip, Mac) when is_integer(Ip), is_binary(Mac) -> +-spec format_endpoint({Mac :: binary(), Host :: #endpoint{}}) -> map(). +format_endpoint({Mac, #endpoint{client_id = ClientId, ip = Ip, hole = Hole, v6_info = V6Info}}) -> HoleMap = case Hole of - undefined -> - #{}; - #hole{peer = {NatIp, NatPort}, nat_type = NatType} -> - #{ - nat_ip => NatIp, - nat_port => NatPort, - nat_type => NatType - } - end, + undefined -> + #{}; + #hole{peer = {NatIp, NatPort}, nat_type = NatType} -> + #{ + nat_ip => NatIp, + nat_port => NatPort, + nat_type => NatType + } + end, V6InfoMap = case V6Info of undefined -> @@ -606,4 +538,4 @@ format_host(#host{client_id = ClientId, hole = Hole, v6_info = V6Info}, Ip, Mac) ip => sdlan_ipaddr:int_to_ipv4(Ip), hole_map => HoleMap, v6_info => V6InfoMap - }. + }. \ No newline at end of file