Skip to content

Commit

Permalink
TODO
Browse files Browse the repository at this point in the history
  • Loading branch information
0xAX committed Jul 21, 2021
1 parent 919bda6 commit de19bb3
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 9 deletions.
91 changes: 85 additions & 6 deletions src/eradius_client.erl
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,35 @@ send_request({IP, Port, Secret}, Request, Options) when ?GOOD_CMD(Request) andal
TS1 = eradius_lib:timestamp(milli_seconds),
ServerName = proplists:get_value(server_name, Options, undefined),
MetricsInfo = make_metrics_info(Options, {IP, Port}),
update_client_requests(MetricsInfo),
Retries = proplists:get_value(retries, Options, ?DEFAULT_RETRIES),
Timeout = proplists:get_value(timeout, Options, ?DEFAULT_TIMEOUT),
Peer = {ServerName, {IP, Port}},
{Socket, ReqId} = gen_server:call(?SERVER, {wanna_send, Peer, MetricsInfo}),
Response = send_request_loop(Socket, ReqId, Peer, Request#radius_request{reqid = ReqId, secret = Secret}, Retries, Timeout, MetricsInfo),
proceed_response(Request, Response, Peer, TS1, MetricsInfo, Options);
SendFun = fun () ->
Peer = {ServerName, {IP, Port}},
update_client_requests(MetricsInfo),
{Socket, ReqId} = gen_server:call(?SERVER, {wanna_send, Peer, MetricsInfo}),
Response = send_request_loop(Socket, ReqId, Peer,
Request#radius_request{reqid = ReqId, secret = Secret},
Retries, Timeout, MetricsInfo),
proceed_response(Request, Response, Peer, TS1, MetricsInfo, Options)
end,
% If we have other RADIUS upstream servers check current one,
% maybe it is already marked as inactive and try to find another
% one if it is
case proplists:get_value(failover, Options, []) of
[] ->
SendFun();
UpstreamServers ->
case find_suitable_peer([{IP, Port, Secret} | UpstreamServers]) of
[] ->
error(no_active_servers);
{{IP, Port, Secret}, _NewPool} ->
SendFun();
{NewPeer, NewPool} ->
% current server is not in list of active servers, so use another one
NewOptions = lists:keyreplace(failover, 1, Options, {failover, NewPool}),
send_request(NewPeer, Request, NewOptions)
end
end;
send_request({_IP, _Port, _Secret}, _Request, _Options) ->
error(badarg).

Expand Down Expand Up @@ -385,7 +407,9 @@ configure(State) ->
%% private
prepare_pools() ->
ets:new(?MODULE, [ordered_set, public, named_table, {keypos, 1}, {write_concurrency,true}]),
lists:foreach(fun({_PoolName, Servers}) -> prepare_pool(Servers) end, application:get_env(eradius, servers_pool, [])).
lists:foreach(fun({_PoolName, Servers}) -> prepare_pool(Servers) end, application:get_env(eradius, servers_pool, [])),
lists:foreach(fun(Server) -> store_upstream_servers(Server) end, application:get_env(eradius, servers, [])).

prepare_pool([]) -> ok;
prepare_pool([{Addr, Port, _, Opts} | Servers]) ->
Retries = proplists:get_value(retries, Opts, ?DEFAULT_RETRIES),
Expand All @@ -395,6 +419,61 @@ prepare_pool([{Addr, Port, _} | Servers]) ->
store_radius_server_from_pool(Addr, Port, ?DEFAULT_RETRIES),
prepare_pool(Servers).

get_routes_info(HandlerOpts) ->
DefaultRoute = lists:keyfind(default_route, 1, HandlerOpts),
Routes = lists:keyfind(routes, 1, HandlerOpts),
Options = lists:keyfind(options, 1, HandlerOpts),
Retries = case Options of
false ->
?DEFAULT_RETRIES;
{options, Opts} ->
proplists:get_value(retries, Opts, ?DEFAULT_RETRIES)
end,
{DefaultRoute, Routes, Retries}.

put_default_route_to_pool(false, _) -> ok;
put_default_route_to_pool({default_route, {Host, Port, _Secret}}, Retries) ->
store_radius_server_from_pool(Host, Port, Retries);
put_default_route_to_pool({default_route, {Host, Port, _Secret}, _PoolName}, Retries) ->
store_radius_server_from_pool(Host, Port, Retries);
put_default_route_to_pool(_, _) -> ok.

put_routes_to_pool(false, _Retries) -> ok;
put_routes_to_pool({routes, Routes}, Retries) ->
lists:foreach(fun (Route) ->
case Route of
{_RouteName, {Host, Port, _Secret}} ->
store_radius_server_from_pool(Host, Port, Retries);
{_RouteName, {Host, Port, _Secret}, _Pool} ->
store_radius_server_from_pool(Host, Port, Retries);
{Host, Port, _Secret, _Opts} ->
store_radius_server_from_pool(Host, Port, Retries);
_ -> ok
end
end, Routes).

store_upstream_servers({Server, _}) ->
store_upstream_servers(Server);
store_upstream_servers({Server, _, _}) ->
store_upstream_servers(Server);
store_upstream_servers(Server) ->
HandlerDefinitions = application:get_env(eradius, Server, []),
F = fun (HandlerOpts) ->
{DefaultRoute, Routes, Retries} = get_routes_info(HandlerOpts),
put_default_route_to_pool(DefaultRoute, Retries),
put_routes_to_pool(Routes, Retries)
end,
lists:foreach(fun (HandlerDefinition) ->
case HandlerDefinition of
{{_, []}, _} -> ok;
{{_, _, []}, _} -> ok;
{{_, HandlerOpts}, _} -> F(HandlerOpts);
{{_, _, HandlerOpts}, _} -> F(HandlerOpts);
_HandlerDefinition -> ok
end
end,
HandlerDefinitions).

%% private
store_radius_server_from_pool(Addr, Port, Retries) when is_tuple(Addr) and is_integer(Port) and is_integer(Retries) ->
ets:insert(?MODULE, {{Addr, Port}, Retries, Retries});
Expand Down
6 changes: 4 additions & 2 deletions test/eradius_client_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@
-include("test/eradius_test.hrl").

-define(BAD_SERVER_IP, {eradius_test_handler:localhost(ip), 1820, "secret"}).
-define(BAD_SERVER_TUPLE, {{eradius_test_handler:localhost(tuple), 1820}, 3, 3}).
-define(BAD_SERVER_INITIAL_RETRIES, 3).
-define(BAD_SERVER_TUPLE, {{eradius_test_handler:localhost(tuple), 1820},
?BAD_SERVER_INITIAL_RETRIES - 1,
?BAD_SERVER_INITIAL_RETRIES}).
-define(BAD_SERVER_IP_ETS_KEY, {eradius_test_handler:localhost(tuple), 1820}).

all() -> [
Expand Down Expand Up @@ -218,7 +221,6 @@ reconf_ports_10(_Config) ->

send_request_failover(_Config) ->
?equal(accept, eradius_test_handler:send_request_failover(?BAD_SERVER_IP)),
?equal([], ets:lookup(eradius_client, ?BAD_SERVER_IP_ETS_KEY)),
{ok, Timeout} = application:get_env(eradius, unreachable_timeout),
timer:sleep(Timeout * 1000),
?equal([?BAD_SERVER_TUPLE], ets:lookup(eradius_client, ?BAD_SERVER_IP_ETS_KEY)),
Expand Down
4 changes: 3 additions & 1 deletion test/eradius_test_handler.erl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ start() ->
application:set_env(eradius, one, [{{"ONE", []}, [{localhost(ip), "secret"}]}]),
application:set_env(eradius, servers, [{one, {localhost(ip), [1812]}}]),
application:set_env(eradius, unreachable_timeout, 2),
application:set_env(eradius, servers_pool, [{test_pool, [{localhost(tuple), 1812, "secret"}]}]),
application:set_env(eradius, servers_pool, [{test_pool, [{localhost(tuple), 1812, "secret"},
% fake upstream server for fail-over
{localhost(tuple), 1820, "secret"}]}]),
application:ensure_all_started(eradius),
eradius:modules_ready([?MODULE]).

Expand Down

0 comments on commit de19bb3

Please sign in to comment.