fix host name

This commit is contained in:
anlicheng 2025-12-13 20:33:40 +08:00
parent 067d425595
commit 99752ddd2e
5 changed files with 62 additions and 34 deletions

View File

@ -13,6 +13,7 @@
client_id :: binary(),
mac :: binary(),
ip :: integer(),
host_name :: binary(),
%%
status = normal :: normal | disabled
}).

View File

@ -45,8 +45,8 @@ handle_request("POST", "/node/move", _, #{<<"client_id">> := ClientId, <<"from_n
case {sdlan_network:get_pid(FromNetworkId), sdlan_network:get_pid(ToNetworkId)} of
{FromPid, ToPid} when is_pid(FromPid), is_pid(ToPid) ->
case sdlan_network:dropout_client(FromPid, ClientId) of
{ok, ChannelPid} ->
Ref = sdlan_channel:move_network(ChannelPid, self(), ToPid),
{ok, ChannelPid, HostName} ->
Ref = sdlan_channel:move_network(ChannelPid, self(), ToPid, HostName),
receive
{command_reply, Ref, {error, Reason}} ->
lager:warning("[node_handler] client_id: ~p, move network from: ~p, to: ~p, get error: ~p", [ClientId, FromPid, ToPid, Reason]),

View File

@ -13,7 +13,7 @@
%% API
-export([create_table/1, get_table_name/1]).
-export([get_clients/1, get_client/2, 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/6]).
-export([debug/1]).
create_table(Tab) when is_atom(Tab) ->
@ -58,12 +58,23 @@ delete_clients(NetworkId) when is_integer(NetworkId) ->
{error, Reason}
end.
-spec delete_client(NetworkId :: integer(), ClientId :: binary()) -> ok | {error, Reason :: any()}.
-spec delete_client(NetworkId :: integer(), ClientId :: binary()) -> {ok, Client :: #client{}} | {error, Reason :: any()}.
delete_client(NetworkId, ClientId) when is_integer(NetworkId), is_binary(ClientId) ->
Tab = get_table_name(NetworkId),
case mnesia:transaction(fun() -> mnesia:delete(Tab, ClientId, write) end) of
{'atomic', ok} ->
ok;
Fun = fun() ->
case mnesia:read(Tab, ClientId, write) of
[] ->
mnesia:abort(not_found);
[Record] ->
mnesia:delete(Tab, ClientId, write),
{ok, Record}
end
end,
case mnesia:transaction(Fun) of
{'atomic', {ok, Client}} ->
{ok, Client};
{'aborted', Reason} ->
{error, Reason}
end.
@ -88,16 +99,16 @@ disable_client(NetworkId, ClientId) when is_integer(NetworkId), is_binary(Client
end.
%% ip地址的时候mac地址为唯一基准
-spec alloc_ip(NetworkId :: integer(), Ips :: list(), ClientId :: binary(), Mac :: binary(), NetAddr0 :: integer()) ->
-spec alloc_ip(NetworkId :: integer(), Ips :: list(), ClientId :: binary(), Mac :: binary(), NetAddr0 :: integer(), HostName :: binary()) ->
{ok, Ip :: integer()} | {error, Reason :: any()}.
alloc_ip(NetworkId, Ips, ClientId, Mac, NetAddr0) when is_binary(ClientId), is_integer(NetAddr0), is_binary(Mac) ->
case mnesia:transaction(fun() -> alloc_ip0(NetworkId, Ips, ClientId, Mac, NetAddr0) end) of
alloc_ip(NetworkId, Ips, ClientId, Mac, NetAddr0, HostName) when is_binary(ClientId), is_integer(NetAddr0), is_binary(Mac), is_binary(HostName) ->
case mnesia:transaction(fun() -> alloc_ip0(NetworkId, Ips, ClientId, Mac, NetAddr0, HostName) end) of
{'atomic', Res} ->
{ok, Res};
{'aborted', Reason} ->
{error, Reason}
end.
alloc_ip0(NetworkId, Ips, ClientId, Mac, NetAddr0) ->
alloc_ip0(NetworkId, Ips, ClientId, Mac, NetAddr0, HostName) ->
Tab = get_table_name(NetworkId),
case mnesia:read(Tab, ClientId) of
@ -107,21 +118,28 @@ alloc_ip0(NetworkId, Ips, ClientId, Mac, NetAddr0) ->
[#client{status = disabled}] ->
mnesia:abort(client_disabled);
[] ->
UsedIps = mnesia:foldl(fun(#client{ip = Ip0}, Acc) -> [Ip0|Acc] end, [], Tab),
case lists:member(NetAddr0, Ips) andalso not lists:member(NetAddr0, UsedIps) of
{UsedIps, UsedHostNames} = mnesia:foldl(fun(#client{ip = Ip0, host_name = HostName0}, {IpAcc, HostNameAcc}) ->
{[Ip0|IpAcc], [HostName0|HostNameAcc]}
end, {[], []}, Tab),
case HostName =/= <<>> andalso lists:member(HostName, UsedHostNames) of
true ->
%% ip没有被占用
Client = #client{client_id = ClientId, mac = Mac, ip = NetAddr0},
ok = mnesia:write(Tab, Client, write),
NetAddr0;
mnesia:abort(host_name_used);
false ->
case Ips -- UsedIps of
[] ->
mnesia:abort(no_ip);
[Ip|_] ->
Client = #client{client_id = ClientId, mac = Mac, ip = Ip, status = normal},
case lists:member(NetAddr0, Ips) andalso not lists:member(NetAddr0, UsedIps) of
true ->
%% ip没有被占用
Client = #client{client_id = ClientId, mac = Mac, ip = NetAddr0, host_name = HostName, status = normal},
ok = mnesia:write(Tab, Client, write),
Ip
NetAddr0;
false ->
case Ips -- UsedIps of
[] ->
mnesia:abort(no_ip);
[Ip|_] ->
Client = #client{client_id = ClientId, mac = Mac, ip = Ip, host_name = HostName, status = normal},
ok = mnesia:write(Tab, Client, write),
Ip
end
end
end
end.

View File

@ -28,6 +28,8 @@
-define(NAK_NETWORK_FAULT, 4).
%%
-define(NAK_INTERNAL_FAULT, 5).
%% hostname被占用
-define(NAK_HOSTNAME_USED, 6).
%%
-define(UPGRADE_NONE, 0).
@ -36,7 +38,7 @@
%% API
-export([start_link/4]).
-export([publish_command/4, send_event/3, stop/2, move_network/3]).
-export([publish_command/4, send_event/3, stop/2, move_network/4]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
@ -75,10 +77,10 @@ publish_command(Pid, ReceiverPid, CommandType, Msg) when is_pid(Pid), is_pid(Rec
Ref.
%%
-spec move_network(Pid :: pid(), ReceiverPid :: pid(), NetworkPid :: pid()) -> Ref :: reference().
move_network(Pid, ReceiverPid, NetworkPid) when is_pid(Pid), is_pid(ReceiverPid), is_pid(NetworkPid) ->
-spec move_network(Pid :: pid(), ReceiverPid :: pid(), NetworkPid :: pid(), HostName :: binary()) -> Ref :: reference().
move_network(Pid, ReceiverPid, NetworkPid, HostName) when is_pid(Pid), is_pid(ReceiverPid), is_pid(NetworkPid), is_binary(HostName) ->
Ref = make_ref(),
Pid ! {move_network, ReceiverPid, Ref, NetworkPid},
Pid ! {move_network, ReceiverPid, Ref, NetworkPid, HostName},
Ref.
%%
@ -177,6 +179,10 @@ handle_info({tcp, Sock, <<PacketId:32, ?PACKET_REGISTER_SUPER, Body/binary>>}, S
lager:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: no_ip", [ClientId, Token]),
Transport:send(Sock, register_nak_reply(PacketId, ?NAK_NO_IP, <<"No Ip address">>)),
{stop, normal, State};
{error, host_name_used} ->
lager:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: host_name_used", [ClientId, Token]),
Transport:send(Sock, register_nak_reply(PacketId, ?NAK_HOSTNAME_USED, <<"Host Name Used">>)),
{stop, normal, State};
{error, client_disabled} ->
lager:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: client_disabled", [ClientId, Token]),
Transport:send(Sock, register_nak_reply(PacketId, ?NAK_NODE_DISABLE, <<"Client Connection Disable">>)),
@ -249,11 +255,11 @@ handle_info({timeout, _, ping_ticker}, State = #state{client_id = ClientId, ping
end;
%%
handle_info({move_network, ReceiverPid, Ref, NetworkPid},
handle_info({move_network, ReceiverPid, Ref, NetworkPid, HostName},
State = #state{transport = Transport, socket = Sock, client_id = ClientId, mac = Mac, pub_key = PubKey, packet_id = PacketId, inflight = Inflight, is_registered = true}) ->
%% network的对应关系
case sdlan_network:assign_ip_addr(NetworkPid, self(), ClientId, Mac, 0) of
case sdlan_network:assign_ip_addr(NetworkPid, self(), ClientId, Mac, 0, HostName) of
{ok, Domain, NetAddr, NetBitLen, AesKey} ->
RsaPubKey = sdlan_cipher:rsa_pem_decode(PubKey),
EncodedAesKey = rsa_encode(AesKey, RsaPubKey),

View File

@ -124,7 +124,7 @@ get_channel(Pid, ClientId) when is_pid(Pid), is_binary(ClientId) ->
gen_server:call(Pid, {get_channel, ClientId}).
%% client_idchannel不关闭; channel会被重新绑定到其他的network里面
-spec dropout_client(Pid :: pid(), ClientId :: binary()) -> {ok, ChannelPid :: pid()} | error.
-spec dropout_client(Pid :: pid(), ClientId :: binary()) -> {ok, ChannelPid :: pid(), HostName :: binary()} | error.
dropout_client(Pid, ClientId) when is_pid(Pid), is_binary(ClientId) ->
gen_server:call(Pid, {dropout_client, ClientId}).
@ -226,7 +226,7 @@ handle_call({assign_ip_addr, ChannelPid, ClientId, Mac, NetAddr0, HostName}, _Fr
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) of
case client_model:alloc_ip(NetworkId, Ips, ClientId, Mac, NetAddr0, HostName) of
{ok, Ip} ->
%% channel
maybe_close_channel(maps:get(Mac, UsedMap, undefined)),
@ -296,9 +296,12 @@ handle_call({dropout_client, ClientId}, _From, State = #state{network_id = Netwo
is_reference(MRef) andalso demonitor(MRef),
NUsedMap = maps:remove(Mac, UsedMap),
%%
client_model:delete_client(NetworkId, ClientId),
{reply, {ok, ChannelPid}, State#state{used_map = NUsedMap}};
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;
false ->
{reply, error, State}
end;