fix network

This commit is contained in:
anlicheng 2026-05-01 16:56:54 +08:00
parent c3c5873cc0
commit 4844e32b6c
2 changed files with 108 additions and 61 deletions

View File

@ -161,10 +161,11 @@ debug_info(Pid) when is_pid(Pid) ->
gen_server:call(Pid, debug_info). gen_server:call(Pid, debug_info).
%% @doc Spawns the server and registers the local name (unique) %% @doc Spawns the server and registers the local name (unique)
-spec(start_link(Name :: atom(), Id :: integer()) -> -spec(start_link(Name :: atom(), NetworkData :: tuple()) ->
{ok, Pid :: pid()} | ignore | {error, Reason :: term()}). {ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
start_link(Name, Id) when is_atom(Name), is_integer(Id) -> start_link(Name, NetworkData = {network, Id, _NetworkName, _Domain, _IpAddr, _MaskLen, _OwnerId, _Algorithm})
gen_server:start_link({local, Name}, ?MODULE, [Id], []). when is_atom(Name), is_integer(Id) ->
gen_server:start_link({local, Name}, ?MODULE, [NetworkData], []).
%%%=================================================================== %%%===================================================================
%%% gen_server callbacks %%% gen_server callbacks
@ -175,14 +176,8 @@ start_link(Name, Id) when is_atom(Name), is_integer(Id) ->
-spec(init(Args :: term()) -> -spec(init(Args :: term()) ->
{ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} | {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
{stop, Reason :: term()} | ignore). {stop, Reason :: term()} | ignore).
init([Id]) when is_integer(Id) -> init([{network, Id, Name, Domain, IpAddr, MaskLen, OwnerId, Algorithm0}]) ->
erlang:process_flag(trap_exit, true), erlang:process_flag(trap_exit, true),
case sdlan_api:get_network(Id) of
{ok, #{<<"ipaddr">> := Null}} when Null == <<"null">>; Null == <<"NULL">> ->
{stop, <<"ipaddrr is null">>};
{ok, NetworkInfo = #{<<"id">> := Id, <<"name">> := Name, <<"domain">> := Domain, <<"algorithm">> := Algorithm0, <<"ipaddr">> := IpAddr0, <<"owner_id">> := OwnerId}} ->
logger:debug("[sdlan_network] load network info: ~p", [NetworkInfo]),
{IpAddr, MaskLen} = parse_ipaddr(IpAddr0),
%% key %% key
ThrottleKey = list_to_atom("network_throttle:" ++ integer_to_list(Id)), ThrottleKey = list_to_atom("network_throttle:" ++ integer_to_list(Id)),
%% %%
@ -196,11 +191,7 @@ init([Id]) when is_integer(Id) ->
EndpointTable = new_endpoint_table(Id), EndpointTable = new_endpoint_table(Id),
{ok, #state{network_id = Id, name = Name, domain = Domain, ipaddr = IpAddr, algorithm = Algorithm, {ok, #state{network_id = Id, name = Name, domain = Domain, ipaddr = IpAddr, algorithm = Algorithm,
owner_id = OwnerId, mask_len = MaskLen, key = Key, throttle_key = ThrottleKey, endpoint_table = EndpointTable}}; owner_id = OwnerId, mask_len = MaskLen, key = Key, throttle_key = ThrottleKey, endpoint_table = EndpointTable}}.
{error, Reason} ->
logger:warning("[sdlan_network] load network: ~p, get error: ~p", [Id, Reason]),
{stop, Reason}
end.
%% @private %% @private
%% @doc Handling call messages %% @doc Handling call messages
@ -426,17 +417,6 @@ code_change(_OldVsn, State = #state{}, _Extra) ->
%%% Internal functions %%% Internal functions
%%%=================================================================== %%%===================================================================
%% IpAddr: <<"192.168.172/24">>
-spec parse_ipaddr(IpAddr0 :: binary()) -> {IpAddr :: binary(), MaskLen :: integer()}.
parse_ipaddr(IpAddr0) when is_binary(IpAddr0) ->
case binary:split(IpAddr0, <<"/">>) of
[IpAddr, MaskLen] ->
MaskLen1 = binary_to_integer(MaskLen),
{IpAddr, MaskLen1};
_ ->
{IpAddr0, 24}
end.
-spec limiting_check(ThrottleKey :: any()) -> pass | denied. -spec limiting_check(ThrottleKey :: any()) -> pass | denied.
limiting_check(ThrottleKey) -> limiting_check(ThrottleKey) ->
case throttle:check(sdlan_network, ThrottleKey) of case throttle:check(sdlan_network, ThrottleKey) of

View File

@ -40,11 +40,16 @@ start_link() ->
%% specifications. %% specifications.
init([]) -> init([]) ->
SupFlags = #{strategy => one_for_one, intensity => 1000, period => 3600}, SupFlags = #{strategy => one_for_one, intensity => 1000, period => 3600},
{ok, NetworkIds} = sdlan_api:get_all_networks(), case sdlan_api:get_all_networks() of
Specs = lists:map(fun child_spec/1, NetworkIds), {ok, NetworkIds} ->
Specs = lists:filtermap(fun load_child_spec/1, NetworkIds),
set_network_bind(length(Specs)), set_network_bind(length(Specs)),
{ok, {SupFlags, Specs}}. {ok, {SupFlags, Specs}};
{error, Reason} ->
logger:warning("[sdlan_network_sup] load all networks error: ~p", [Reason]),
{stop, {load_networks_failed, Reason}}
end.
%%%=================================================================== %%%===================================================================
%%% Internal functions %%% Internal functions
@ -54,15 +59,11 @@ init([]) ->
ensure_network_started(Id) when is_integer(Id) -> ensure_network_started(Id) when is_integer(Id) ->
case sdlan_network:get_pid(Id) of case sdlan_network:get_pid(Id) of
undefined -> undefined ->
case supervisor:start_child(?MODULE, child_spec(Id)) of case child_spec(Id) of
{ok, Pid} when is_pid(Pid) -> {ok, Spec} ->
{ok, Pid}; start_child(Spec);
{ok, undefined} -> {error, Reason} ->
{error, ignored}; {error, Reason}
{error, {'already_started', Pid}} when is_pid(Pid) ->
{ok, Pid};
{error, Error} ->
{error, Error}
end; end;
Pid when is_pid(Pid) -> Pid when is_pid(Pid) ->
{ok, Pid} {ok, Pid}
@ -70,9 +71,20 @@ ensure_network_started(Id) when is_integer(Id) ->
-spec start_network(Id :: integer()) -> {ok, Pid :: pid()} | {error, Reason :: any()}. -spec start_network(Id :: integer()) -> {ok, Pid :: pid()} | {error, Reason :: any()}.
start_network(Id) when is_integer(Id) -> start_network(Id) when is_integer(Id) ->
case supervisor:start_child(?MODULE, child_spec(Id)) of case child_spec(Id) of
{ok, Spec} ->
start_child(Spec);
{error, Reason} ->
{error, Reason}
end.
-spec start_child(Spec :: map()) -> {ok, Pid :: pid()} | {error, Reason :: any()}.
start_child(Spec) ->
case supervisor:start_child(?MODULE, Spec) of
{ok, Pid} when is_pid(Pid) -> {ok, Pid} when is_pid(Pid) ->
{ok, Pid}; {ok, Pid};
{ok, undefined} ->
{error, ignored};
{error, {'already_started', Pid}} when is_pid(Pid) -> {error, {'already_started', Pid}} when is_pid(Pid) ->
{ok, Pid}; {ok, Pid};
{error, Error} -> {error, Error} ->
@ -99,17 +111,72 @@ delete_network(NetworkId) when is_integer(NetworkId) ->
Error Error
end. end.
-spec child_spec(Id :: integer()) -> map(). -spec child_spec(Id :: integer()) -> {ok, map()} | {error, Reason :: any()}.
child_spec(Id) when is_integer(Id) -> child_spec(Id) when is_integer(Id) ->
case load_network_data(Id) of
{ok, NetworkData} ->
Name = sdlan_network:get_name(Id), Name = sdlan_network:get_name(Id),
#{ {ok, #{
id => Name, id => Name,
start => {sdlan_network, start_link, [Name, Id]}, start => {sdlan_network, start_link, [Name, NetworkData]},
restart => permanent, restart => permanent,
shutdown => 2000, shutdown => 2000,
type => worker, type => worker,
modules => ['sdlan_network'] modules => ['sdlan_network']
}. }};
{error, Reason} ->
{error, Reason}
end.
-spec load_child_spec(Id :: integer()) -> {true, map()} | false.
load_child_spec(Id) ->
case child_spec(Id) of
{ok, Spec} ->
{true, Spec};
{error, Reason} ->
logger:warning("[sdlan_network_sup] skip network: ~p, reason: ~p", [Id, Reason]),
false
end.
-spec load_network_data(Id :: integer()) -> {ok, tuple()} | {error, Reason :: any()}.
load_network_data(Id) when is_integer(Id) ->
case sdlan_api:get_network(Id) of
{ok, #{<<"ipaddr">> := Null}} when Null == <<"null">>; Null == <<"NULL">> ->
{error, <<"ipaddrr is null">>};
{ok, #{<<"id">> := NetworkId}} when NetworkId =/= Id ->
{error, {network_id_mismatch, Id, NetworkId}};
{ok, NetworkInfo = #{<<"id">> := Id, <<"name">> := Name, <<"domain">> := Domain,
<<"algorithm">> := Algorithm, <<"ipaddr">> := IpAddr0, <<"owner_id">> := OwnerId}} ->
logger:debug("[sdlan_network_sup] load network info: ~p", [NetworkInfo]),
case parse_ipaddr(IpAddr0) of
{ok, IpAddr, MaskLen} ->
{ok, {network, Id, Name, Domain, IpAddr, MaskLen, OwnerId, Algorithm}};
{error, Reason} ->
{error, Reason}
end;
{ok, NetworkInfo} ->
{error, {invalid_network_info, NetworkInfo}};
{error, Reason} ->
logger:warning("[sdlan_network_sup] load network: ~p, get error: ~p", [Id, Reason]),
{error, Reason}
end.
%% IpAddr: <<"192.168.172/24">>
-spec parse_ipaddr(IpAddr0 :: binary()) -> {ok, IpAddr :: binary(), MaskLen :: integer()} | {error, Reason :: any()}.
parse_ipaddr(IpAddr0) when is_binary(IpAddr0) ->
try
case binary:split(IpAddr0, <<"/">>) of
[IpAddr, MaskLen] ->
{ok, IpAddr, binary_to_integer(MaskLen)};
_ ->
{ok, IpAddr0, 24}
end
catch
_:_ ->
{error, {invalid_ipaddr, IpAddr0}}
end;
parse_ipaddr(IpAddr0) ->
{error, {invalid_ipaddr, IpAddr0}}.
set_network_bind(0) -> set_network_bind(0) ->
ok; ok;