From 45348170f468fadd73e7541aac5bc6f664475d0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Sun, 22 Jul 2012 05:50:10 +0200 Subject: Add support for listening on random port numbers (port 0) ranch:get_port/1 returns the given listener's port. --- src/ranch.app.src | 2 +- src/ranch.erl | 8 ++++++++ src/ranch_acceptors_sup.erl | 2 ++ src/ranch_listener.erl | 17 +++++++++++++++++ test/acceptor_SUITE.erl | 7 +++---- 5 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/ranch.app.src b/src/ranch.app.src index 88e1362..dd2840c 100644 --- a/src/ranch.app.src +++ b/src/ranch.app.src @@ -14,7 +14,7 @@ {application, ranch, [ {description, "Socket acceptor pool for TCP protocols."}, - {vsn, "0.2.1"}, + {vsn, git}, {modules, []}, {registered, [ranch_sup]}, {applications, [ diff --git a/src/ranch.erl b/src/ranch.erl index b6008fa..3f07df7 100644 --- a/src/ranch.erl +++ b/src/ranch.erl @@ -19,6 +19,7 @@ -export([stop_listener/1]). -export([child_spec/6]). -export([accept_ack/1]). +-export([get_port/1]). -export([get_protocol_options/1]). -export([set_protocol_options/2]). @@ -88,6 +89,13 @@ child_spec(Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts) accept_ack(ListenerPid) -> receive {shoot, ListenerPid} -> ok end. +%% @doc Return the listener's port. +-spec get_port(any()) -> inet:port_number(). +get_port(Ref) -> + ListenerPid = ref_to_listener_pid(Ref), + {ok, Port} = ranch_listener:get_port(ListenerPid), + Port. + %% @doc Return the current protocol options for the given listener. -spec get_protocol_options(any()) -> any(). get_protocol_options(Ref) -> diff --git a/src/ranch_acceptors_sup.erl b/src/ranch_acceptors_sup.erl index 963b4d3..5617873 100644 --- a/src/ranch_acceptors_sup.erl +++ b/src/ranch_acceptors_sup.erl @@ -36,6 +36,8 @@ start_link(NbAcceptors, Transport, TransOpts, init([NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts, ListenerPid, ConnsPid]) -> {ok, LSocket} = Transport:listen(TransOpts), + {ok, {_, Port}} = Transport:sockname(LSocket), + ranch_listener:set_port(ListenerPid, Port), Procs = [{{acceptor, self(), N}, {ranch_acceptor, start_link, [ LSocket, Transport, Protocol, ProtoOpts, ListenerPid, ConnsPid diff --git a/src/ranch_listener.erl b/src/ranch_listener.erl index 8a78472..40528f5 100644 --- a/src/ranch_listener.erl +++ b/src/ranch_listener.erl @@ -23,6 +23,8 @@ -export([move_connection/3]). -export([remove_connection/2]). -export([check_upgrades/2]). +-export([get_port/1]). +-export([set_port/2]). -export([get_protocol_options/1]). -export([set_protocol_options/2]). @@ -41,6 +43,7 @@ conns_table :: ets:tid(), queue = undefined :: queue(), max_conns = undefined :: non_neg_integer(), + port = undefined :: undefined | inet:port_number(), proto_opts :: any(), proto_opts_vsn = 1 :: non_neg_integer() }). @@ -102,6 +105,16 @@ remove_connection(ServerPid, ConnPid) -> check_upgrades(ServerPid, OptsVsn) -> gen_server:call(ServerPid, {check_upgrades, OptsVsn}). +%% @doc Return the listener's port. +-spec get_port(pid()) -> {ok, inet:port_number()}. +get_port(ServerPid) -> + gen_server:call(ServerPid, get_port). + +%% @private +-spec set_port(pid(), inet:port_number()) -> ok. +set_port(ServerPid, Port) -> + gen_server:cast(ServerPid, {set_port, Port}). + %% @doc Return the current protocol options. -spec get_protocol_options(pid()) -> {ok, any()}. get_protocol_options(ServerPid) -> @@ -143,6 +156,8 @@ handle_call({check_upgrades, AccOptsVsn}, _From, State=#state{ true -> {reply, ok, State} end; +handle_call(get_port, _From, State=#state{port=Port}) -> + {reply, {ok, Port}, State}; handle_call(get_protocol_options, _From, State=#state{proto_opts=ProtoOpts}) -> {reply, {ok, ProtoOpts}, State}; handle_call({set_protocol_options, ProtoOpts}, _From, @@ -154,6 +169,8 @@ handle_call(_, _From, State) -> {reply, ignored, State}. %% @private +handle_cast({set_port, Port}, State) -> + {noreply, State#state{port=Port}}; handle_cast({move_connection, DestPool, ConnPid}, State=#state{ conn_pools=Pools, conns_table=ConnsTable}) -> Pools2 = move_pid(ConnPid, DestPool, Pools, ConnsTable), diff --git a/test/acceptor_SUITE.erl b/test/acceptor_SUITE.erl index cfb5cd8..0a15916 100644 --- a/test/acceptor_SUITE.erl +++ b/test/acceptor_SUITE.erl @@ -39,11 +39,10 @@ end_per_suite(_) -> %% tcp. tcp_echo(_) -> - %% @todo Don't use a fixed port. start_listener should return the port used? {ok, _} = ranch:start_listener(tcp_echo, 1, - ranch_tcp, [{port, 33333}], - echo_protocol, []), - {ok, Socket} = gen_tcp:connect("localhost", 33333, + ranch_tcp, [{port, 0}], echo_protocol, []), + Port = ranch:get_port(tcp_echo), + {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = gen_tcp:send(Socket, <<"Ranch is working!">>), {ok, <<"Ranch is working!">>} = gen_tcp:recv(Socket, 0, 1000), -- cgit v1.2.3