diff --git a/apps/sdlan/src/mnesia/client_model.erl b/apps/sdlan/src/mnesia/client_model.erl index 26738cf..9187616 100644 --- a/apps/sdlan/src/mnesia/client_model.erl +++ b/apps/sdlan/src/mnesia/client_model.erl @@ -13,7 +13,7 @@ %% API -export([create_table/1, get_table_name/1]). --export([get_clients/1, delete_clients/1, delete_client/2, disable_client/2, alloc_ip/5]). +-export([get_clients/1, get_client/2, delete_clients/1, delete_client/2, disable_client/2, alloc_ip/5]). -export([debug/1]). create_table(Tab) when is_atom(Tab) -> @@ -28,6 +28,16 @@ create_table(Tab) when is_atom(Tab) -> get_table_name(NetworkId) when is_integer(NetworkId) -> list_to_atom("client_" ++ integer_to_list(NetworkId)). +-spec get_client(NetworkId :: integer(), ClientId :: binary()) -> error | {ok, Client :: #client{}} . +get_client(NetworkId, ClientId) when is_integer(NetworkId), is_binary(ClientId) -> + Tab = get_table_name(NetworkId), + case mnesia:dirty_read(Tab, ClientId) of + [] -> + error; + [Client|_] -> + {ok, Client} + end. + -spec get_clients(NetworkId :: integer()) -> [Client :: #client{}]. get_clients(NetworkId) when is_integer(NetworkId) -> Tab = get_table_name(NetworkId), diff --git a/apps/sdlan/src/sdlan_channel.erl b/apps/sdlan/src/sdlan_channel.erl index 2052a6f..a5fd7c6 100644 --- a/apps/sdlan/src/sdlan_channel.erl +++ b/apps/sdlan/src/sdlan_channel.erl @@ -138,7 +138,7 @@ handle_info({tcp, Sock, <>}, S %% 建立到network的对应关系 case sdlan_network:get_pid(NetworkId) of NetworkPid when is_pid(NetworkPid) -> - try sdlan_network:assign_ip_addr(NetworkPid, self(), ClientId, Mac, NetAddr0) of + try sdlan_network:assign_ip_addr(NetworkPid, self(), ClientId, Mac, NetAddr0, HostName) of {ok, Domain, NetAddr, NetBitLen, AesKey} -> RsaPubKey = sdlan_cipher:rsa_pem_decode(PubKey), EncodedAesKey = rsa_encode(AesKey, RsaPubKey), diff --git a/apps/sdlan/src/sdlan_network.erl b/apps/sdlan/src/sdlan_network.erl index 0513d0c..e605028 100644 --- a/apps/sdlan/src/sdlan_network.erl +++ b/apps/sdlan/src/sdlan_network.erl @@ -21,7 +21,7 @@ %% API -export([start_link/2]). --export([get_name/1, get_pid/1, assign_ip_addr/5, peer_info/3, unregister/3, debug_info/1, get_network_id/1, get_used_map/1]). +-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([test_event/1]). @@ -33,11 +33,9 @@ nat_type :: integer() }). -%% ip的使用信息 +%% ip的使用信息, 记录主机的动态信息 -record(host, { client_id :: binary(), - mac :: binary(), - ip :: integer(), channel_pid :: undefined | pid(), monitor_ref :: undefined | reference(), hole :: undefined | #hole{}, @@ -90,10 +88,10 @@ get_name(Id) when is_integer(Id) -> 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()) -> +-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) when is_pid(Pid), is_pid(ChannelPid), is_binary(ClientId), is_binary(Mac), is_integer(NetAddr) -> - gen_server:call(Pid, {assign_ip_addr, ChannelPid, ClientId, Mac, NetAddr}). +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) -> + gen_server:call(Pid, {assign_ip_addr, ChannelPid, ClientId, Mac, NetAddr, HostName}). -spec get_network_id(Pid :: pid()) -> {ok, NetworkId :: integer()}. get_network_id(Pid) when is_pid(Pid) -> @@ -221,7 +219,7 @@ handle_call(reload, _From, State = #state{network_id = Id, ipaddr = OldIpAddr, m end; %% 给客户端分配ip地址 -handle_call({assign_ip_addr, ChannelPid, ClientId, Mac, NetAddr0}, _From, +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}) -> %% 分配ip地址的时候,以mac地址为唯一基准 @@ -235,7 +233,7 @@ handle_call({assign_ip_addr, ChannelPid, ClientId, Mac, NetAddr0}, _From, %% 建立到新的channel之间的关系 MRef = monitor(process, ChannelPid), - NUsedMap = maps:put(Mac, #host{client_id = ClientId, mac = Mac, ip = Ip, channel_pid = ChannelPid, monitor_ref = MRef}, UsedMap), + NUsedMap = maps:put(Mac, #host{client_id = ClientId, channel_pid = ChannelPid, monitor_ref = MRef}, UsedMap), {reply, {ok, Domain, Ip, MaskLen, AesKey}, State#state{used_map = NUsedMap}}; {error, Reason} -> @@ -338,7 +336,14 @@ handle_call(debug_info, _From, State = #state{network_id = NetworkId, ipaddr = I <<"mask_len">> => MaskLen, <<"owner_id">> => OwnerId, <<"ips">> => lists:map(fun sdlan_ipaddr:int_to_ipv4/1, Ips), - <<"used_ips">> => lists:map(fun({_, Host}) -> format_host(Host) end, maps:to_list(UsedMap)) + <<"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)) }, {reply, Reply, State}. @@ -435,12 +440,12 @@ handle_cast({unregister, _ClientId, Mac}, State = #state{network_id = NetworkId, end; %% 需要判断,client是属于当前网络的 -handle_cast({update_hole, _ClientId, Mac, Peer, NatType, V6Info}, State = #state{used_map = UsedMap}) -> - case maps:find(Mac, UsedMap) of - {ok, Host0 = #host{hole = OldHole, ip = Ip}} -> +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 -> 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 { + NatChangedEvent = sdlan_pb:encode_msg(#sdl_nat_changed_event{ mac = Mac, ip = Ip }), @@ -451,7 +456,7 @@ handle_cast({update_hole, _ClientId, Mac, Peer, NatType, V6Info}, State = #state Host = Host0#host{hole = #hole{peer = Peer, nat_type = NatType}, v6_info = V6Info}, {noreply, State#state{used_map = maps:put(Mac, Host, UsedMap)}}; - error -> + _ -> {noreply, State} end. @@ -561,8 +566,8 @@ parse_ipaddr(IpAddr0) when is_binary(IpAddr0) -> {IpAddr0, 24} end. --spec format_host(Host :: #host{}) -> map(). -format_host(#host{client_id = ClientId, mac = Mac, ip = Ip, hole = Hole, v6_info = V6Info}) -> +-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) -> HoleMap = case Hole of undefined -> #{};