25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-26 16:26:24 +01:00

Add rate limit command to ejabberd_listener. You can now limit the max number of TCP connects per second on a given port. (thanks to Mickael Remond)

This commit is contained in:
Christophe Romain 2010-07-13 22:07:43 +02:00
parent 2b48732de4
commit e64d69350f

View File

@ -35,7 +35,8 @@
stop_listener/2, stop_listener/2,
parse_listener_portip/2, parse_listener_portip/2,
add_listener/3, add_listener/3,
delete_listener/2 delete_listener/2,
rate_limit/2
]). ]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
@ -223,6 +224,9 @@ get_ip_tuple(IPOpt, _IPVOpt) ->
IPOpt. IPOpt.
accept(ListenSocket, Module, Opts) -> accept(ListenSocket, Module, Opts) ->
accept(ListenSocket, Module, Opts, 0).
accept(ListenSocket, Module, Opts, Interval) ->
NewInterval = check_rate_limit(Interval),
case gen_tcp:accept(ListenSocket) of case gen_tcp:accept(ListenSocket) of
{ok, Socket} -> {ok, Socket} ->
case {inet:sockname(Socket), inet:peername(Socket)} of case {inet:sockname(Socket), inet:peername(Socket)} of
@ -237,11 +241,11 @@ accept(ListenSocket, Module, Opts) ->
false -> ejabberd_socket false -> ejabberd_socket
end, end,
CallMod:start(strip_frontend(Module), gen_tcp, Socket, Opts), CallMod:start(strip_frontend(Module), gen_tcp, Socket, Opts),
accept(ListenSocket, Module, Opts); accept(ListenSocket, Module, Opts, NewInterval);
{error, Reason} -> {error, Reason} ->
?INFO_MSG("(~w) Failed TCP accept: ~w", ?INFO_MSG("(~w) Failed TCP accept: ~w",
[ListenSocket, Reason]), [ListenSocket, Reason]),
accept(ListenSocket, Module, Opts) accept(ListenSocket, Module, Opts, NewInterval)
end. end.
udp_recv(Socket, Module, Opts) -> udp_recv(Socket, Module, Opts) ->
@ -469,3 +473,39 @@ format_error(Reason) ->
ReasonStr -> ReasonStr ->
ReasonStr ReasonStr
end. end.
%% Set interval between two accepts on given port
rate_limit([], _Interval) ->
ok;
rate_limit([Port|Ports], Interval) ->
rate_limit(Port, Interval),
rate_limit(Ports, Interval);
rate_limit(Port, Interval) ->
case get_listener_pid_by_port(Port) of
undefined -> no_listener;
Pid -> Pid ! {rate_limit, Interval}, ok
end.
get_listener_pid_by_port(Port) ->
ListenerPids = [Pid || {{P,_,_},Pid,_,_} <-
supervisor:which_children(erlang:whereis(ejabberd_listeners)),
P == Port],
ListenerPid = case ListenerPids of
[] -> undefined;
[LPid|_] -> LPid
end,
ListenerPid.
check_rate_limit(Interval) ->
NewInterval = receive
{rate_limit, AcceptInterval} ->
AcceptInterval
after 0 ->
Interval
end,
case NewInterval of
0 -> ok;
Ms ->
timer:sleep(Ms)
end,
NewInterval.