diff options
-rw-r--r-- | src/cowboy_acceptor.erl | 30 | ||||
-rw-r--r-- | src/cowboy_acceptors_sup.erl | 3 |
2 files changed, 23 insertions, 10 deletions
diff --git a/src/cowboy_acceptor.erl b/src/cowboy_acceptor.erl index f27f446..9bcc733 100644 --- a/src/cowboy_acceptor.erl +++ b/src/cowboy_acceptor.erl @@ -13,28 +13,31 @@ %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -module(cowboy_acceptor). --export([start_link/5]). %% API. --export([acceptor/5]). %% Internal. +-export([start_link/6]). %% API. +-export([acceptor/6]). %% Internal. %% API. -spec start_link(LSocket::inet:socket(), Transport::module(), - Protocol::module(), Opts::term(), ReqsSup::pid()) -> {ok, Pid::pid()}. -start_link(LSocket, Transport, Protocol, Opts, ReqsSup) -> + Protocol::module(), Opts::term(), + MaxConns::non_neg_integer(), ReqsSup::pid()) -> {ok, Pid::pid()}. +start_link(LSocket, Transport, Protocol, Opts, MaxConns, ReqsSup) -> Pid = spawn_link(?MODULE, acceptor, - [LSocket, Transport, Protocol, Opts, ReqsSup]), + [LSocket, Transport, Protocol, Opts, MaxConns, ReqsSup]), {ok, Pid}. %% Internal. -spec acceptor(LSocket::inet:socket(), Transport::module(), - Protocol::module(), Opts::term(), ReqsSup::pid()) -> no_return(). -acceptor(LSocket, Transport, Protocol, Opts, ReqsSup) -> + Protocol::module(), Opts::term(), + MaxConns::non_neg_integer(), ReqsSup::pid()) -> no_return(). +acceptor(LSocket, Transport, Protocol, Opts, MaxConns, ReqsSup) -> case Transport:accept(LSocket, 2000) of {ok, CSocket} -> {ok, Pid} = supervisor:start_child(ReqsSup, [CSocket, Transport, Protocol, Opts]), - Transport:controlling_process(CSocket, Pid); + Transport:controlling_process(CSocket, Pid), + limit_reqs(MaxConns, ReqsSup); {error, timeout} -> ignore; {error, _Reason} -> @@ -42,4 +45,13 @@ acceptor(LSocket, Transport, Protocol, Opts, ReqsSup) -> %% we may want to try and listen again on the port? ignore end, - ?MODULE:acceptor(LSocket, Transport, Protocol, Opts, ReqsSup). + ?MODULE:acceptor(LSocket, Transport, Protocol, Opts, MaxConns, ReqsSup). + +-spec limit_reqs(MaxConns::non_neg_integer(), ReqsSup::pid()) -> ok. +limit_reqs(MaxConns, ReqsSup) -> + Counts = supervisor:count_children(ReqsSup), + Active = lists:keyfind(active, 1, Counts), + case Active < MaxConns of + true -> ok; + false -> timer:sleep(1) + end. diff --git a/src/cowboy_acceptors_sup.erl b/src/cowboy_acceptors_sup.erl index 3fbffb1..f5b2de3 100644 --- a/src/cowboy_acceptors_sup.erl +++ b/src/cowboy_acceptors_sup.erl @@ -32,8 +32,9 @@ start_link(NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts, ReqsPid) -> -spec init(list(term())) -> term(). %% @todo These specs should be improved. init([NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts, ReqsPid]) -> {ok, LSocket} = Transport:listen(TransOpts), + MaxConns = proplists:get_value(max_connections, TransOpts, 1024), Procs = [{{acceptor, self(), N}, {cowboy_acceptor, start_link, [ - LSocket, Transport, Protocol, ProtoOpts, ReqsPid + LSocket, Transport, Protocol, ProtoOpts, MaxConns, ReqsPid ]}, permanent, brutal_kill, worker, dynamic} || N <- lists:seq(1, NbAcceptors)], {ok, {{one_for_one, 10, 10}, Procs}}. |