aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <xramtsov@gmail.com>2009-08-11 07:15:36 +0000
committerEvgeniy Khramtsov <xramtsov@gmail.com>2009-08-11 07:15:36 +0000
commit01a9f981f413b24e4f3fc973f2eb08cc6c6e08df (patch)
tree858d7bb4cb111803a00bb80d5d51e4d09fddba4b
parentdo not forget to close TLS socket (diff)
it is now possible to start TCP/UDP on the same port
SVN Revision: 2452
-rw-r--r--src/ejabberd_config.erl4
-rw-r--r--src/ejabberd_listener.erl87
2 files changed, 62 insertions, 29 deletions
diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl
index d673818c1..1f5831140 100644
--- a/src/ejabberd_config.erl
+++ b/src/ejabberd_config.erl
@@ -331,9 +331,9 @@ process_term(Term, State) ->
Listeners2 =
lists:map(
fun({PortIP, Module, Opts}) ->
- {Port, IPT, _, _, OptsClean} =
+ {Port, IPT, _, _, Proto, OptsClean} =
ejabberd_listener:parse_listener_portip(PortIP, Opts),
- {{Port, IPT}, Module, OptsClean}
+ {{Port, IPT, Proto}, Module, OptsClean}
end,
Listeners),
add_option(listen, Listeners2, State);
diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl
index f612723d8..26167351f 100644
--- a/src/ejabberd_listener.erl
+++ b/src/ejabberd_listener.erl
@@ -97,7 +97,7 @@ start_dependent(Port, Module, Opts) ->
end.
init(PortIP, Module, RawOpts) ->
- {Port, IPT, IPS, IPV, OptsClean} = parse_listener_portip(PortIP, RawOpts),
+ {Port, IPT, IPS, IPV, Proto, OptsClean} = parse_listener_portip(PortIP, RawOpts),
%% The first inet|inet6 and the last {ip, _} work,
%% so overriding those in Opts
Opts = [IPV | OptsClean] ++ [{ip, IPT}],
@@ -106,10 +106,9 @@ init(PortIP, Module, RawOpts) ->
(inet) -> true;
(_) -> false
end, Opts),
- case lists:member(udp, RawOpts) of
- true ->
+ if Proto == udp ->
init_udp(PortIP, Module, Opts, SockOpts, Port, IPS);
- false ->
+ true ->
init_tcp(PortIP, Module, Opts, SockOpts, Port, IPS)
end.
@@ -167,24 +166,34 @@ parse_listener_portip(PortIP, Opts) ->
true -> {inet6, Opts2 -- [inet6]};
false -> {inet, Opts2}
end,
- {Port, IPT, IPS} = case PortIP of
- P when is_integer(P) ->
- T = get_ip_tuple(IPOpt, IPVOpt),
- S = inet_parse:ntoa(T),
- {P, T, S};
- {P, T} when is_integer(P) and is_tuple(T) ->
- S = inet_parse:ntoa(T),
- {P, T, S};
- {P, S} when is_integer(P) and is_list(S) ->
- [S | _] = string:tokens(S, "/"),
- {ok, T} = inet_parse:address(S),
- {P, T, S}
- end,
+ {Port, IPT, IPS, Proto} =
+ case add_proto(PortIP, Opts) of
+ {P, Prot} ->
+ T = get_ip_tuple(IPOpt, IPVOpt),
+ S = inet_parse:ntoa(T),
+ {P, T, S, Prot};
+ {P, T, Prot} when is_integer(P) and is_tuple(T) ->
+ S = inet_parse:ntoa(T),
+ {P, T, S, Prot};
+ {P, S, Prot} when is_integer(P) and is_list(S) ->
+ [S | _] = string:tokens(S, "/"),
+ {ok, T} = inet_parse:address(S),
+ {P, T, S, Prot}
+ end,
IPV = case size(IPT) of
4 -> inet;
8 -> inet6
end,
- {Port, IPT, IPS, IPV, OptsClean}.
+ {Port, IPT, IPS, IPV, Proto, OptsClean}.
+
+add_proto(Port, Opts) when is_integer(Port) ->
+ {Port, get_proto(Opts)};
+add_proto({Port, Proto}, _Opts) when is_atom(Proto) ->
+ {Port, normalize_proto(Proto)};
+add_proto({Port, Addr}, Opts) ->
+ {Port, Addr, get_proto(Opts)};
+add_proto({Port, Addr, Proto}, _Opts) ->
+ {Port, Addr, normalize_proto(Proto)}.
strip_ip_option(Opts) ->
{IPL, OptsNoIP} = lists:partition(
@@ -312,7 +321,9 @@ stop_listener(PortIP, _Module) ->
%% Opts = [IPV | {ip, IPT} | atom() | tuple()]
%% @doc Add a listener and store in config if success
add_listener(PortIP, Module, Opts) ->
- case start_listener(PortIP, Module, Opts) of
+ {Port, IPT, _, _, Proto, _} = parse_listener_portip(PortIP, Opts),
+ PortIP1 = {Port, IPT, Proto},
+ case start_listener(PortIP1, Module, Opts) of
{ok, _Pid} ->
Ports = case ejabberd_config:get_local_option(listen) of
undefined ->
@@ -320,33 +331,39 @@ add_listener(PortIP, Module, Opts) ->
Ls ->
Ls
end,
- Ports1 = lists:keydelete(PortIP, 1, Ports),
- Ports2 = [{PortIP, Module, Opts} | Ports1],
+ Ports1 = lists:keydelete(PortIP1, 1, Ports),
+ Ports2 = [{PortIP1, Module, Opts} | Ports1],
ejabberd_config:add_local_option(listen, Ports2),
- ok;
+ ok;
{error, {already_started, _Pid}} ->
{error, {already_started, PortIP}};
{error, Error} ->
{error, Error}
end.
-
-%% @spec (PortIP, Module) -> ok
+
+delete_listener(PortIP, Module) ->
+ delete_listener(PortIP, Module, []).
+
+%% @spec (PortIP, Module, Opts) -> ok
%% where
%% PortIP = {Port, IPT | IPS}
%% Port = integer()
%% IPT = tuple()
%% IPS = string()
%% Module = atom()
-delete_listener(PortIP, Module) ->
+%% Opts = [term()]
+delete_listener(PortIP, Module, Opts) ->
+ {Port, IPT, _, _, Proto, _} = parse_listener_portip(PortIP, Opts),
+ PortIP1 = {Port, IPT, Proto},
Ports = case ejabberd_config:get_local_option(listen) of
undefined ->
[];
Ls ->
Ls
end,
- Ports1 = lists:keydelete(PortIP, 1, Ports),
+ Ports1 = lists:keydelete(PortIP1, 1, Ports),
ejabberd_config:add_local_option(listen, Ports1),
- stop_listener(PortIP, Module).
+ stop_listener(PortIP1, Module).
is_frontend({frontend, _Module}) -> true;
is_frontend(_) -> false.
@@ -401,6 +418,22 @@ certfile_readable(Opts) ->
end
end.
+get_proto(Opts) ->
+ case proplists:get_value(proto, Opts) of
+ undefined ->
+ tcp;
+ Proto ->
+ normalize_proto(Proto)
+ end.
+
+normalize_proto(tcp) -> tcp;
+normalize_proto(udp) -> udp;
+normalize_proto(UnknownProto) ->
+ ?WARNING_MSG("There is a problem in the configuration: "
+ "~p is an unknown IP protocol. Using tcp as fallback",
+ [UnknownProto]),
+ tcp.
+
socket_error(Reason, PortIP, Module, SockOpts, Port, IPS) ->
ReasonT = case Reason of
eaddrnotavail ->