it is now possible to start TCP/UDP on the same port

SVN Revision: 2452
This commit is contained in:
Evgeniy Khramtsov 2009-08-11 07:15:36 +00:00
parent d967054a9f
commit 01a9f981f4
2 changed files with 62 additions and 29 deletions

View File

@ -331,9 +331,9 @@ process_term(Term, State) ->
Listeners2 = Listeners2 =
lists:map( lists:map(
fun({PortIP, Module, Opts}) -> fun({PortIP, Module, Opts}) ->
{Port, IPT, _, _, OptsClean} = {Port, IPT, _, _, Proto, OptsClean} =
ejabberd_listener:parse_listener_portip(PortIP, Opts), ejabberd_listener:parse_listener_portip(PortIP, Opts),
{{Port, IPT}, Module, OptsClean} {{Port, IPT, Proto}, Module, OptsClean}
end, end,
Listeners), Listeners),
add_option(listen, Listeners2, State); add_option(listen, Listeners2, State);

View File

@ -97,7 +97,7 @@ start_dependent(Port, Module, Opts) ->
end. end.
init(PortIP, Module, RawOpts) -> 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, %% The first inet|inet6 and the last {ip, _} work,
%% so overriding those in Opts %% so overriding those in Opts
Opts = [IPV | OptsClean] ++ [{ip, IPT}], Opts = [IPV | OptsClean] ++ [{ip, IPT}],
@ -106,10 +106,9 @@ init(PortIP, Module, RawOpts) ->
(inet) -> true; (inet) -> true;
(_) -> false (_) -> false
end, Opts), end, Opts),
case lists:member(udp, RawOpts) of if Proto == udp ->
true ->
init_udp(PortIP, Module, Opts, SockOpts, Port, IPS); init_udp(PortIP, Module, Opts, SockOpts, Port, IPS);
false -> true ->
init_tcp(PortIP, Module, Opts, SockOpts, Port, IPS) init_tcp(PortIP, Module, Opts, SockOpts, Port, IPS)
end. end.
@ -167,24 +166,34 @@ parse_listener_portip(PortIP, Opts) ->
true -> {inet6, Opts2 -- [inet6]}; true -> {inet6, Opts2 -- [inet6]};
false -> {inet, Opts2} false -> {inet, Opts2}
end, end,
{Port, IPT, IPS} = case PortIP of {Port, IPT, IPS, Proto} =
P when is_integer(P) -> case add_proto(PortIP, Opts) of
T = get_ip_tuple(IPOpt, IPVOpt), {P, Prot} ->
S = inet_parse:ntoa(T), T = get_ip_tuple(IPOpt, IPVOpt),
{P, T, S}; S = inet_parse:ntoa(T),
{P, T} when is_integer(P) and is_tuple(T) -> {P, T, S, Prot};
S = inet_parse:ntoa(T), {P, T, Prot} when is_integer(P) and is_tuple(T) ->
{P, T, S}; S = inet_parse:ntoa(T),
{P, S} when is_integer(P) and is_list(S) -> {P, T, S, Prot};
[S | _] = string:tokens(S, "/"), {P, S, Prot} when is_integer(P) and is_list(S) ->
{ok, T} = inet_parse:address(S), [S | _] = string:tokens(S, "/"),
{P, T, S} {ok, T} = inet_parse:address(S),
end, {P, T, S, Prot}
end,
IPV = case size(IPT) of IPV = case size(IPT) of
4 -> inet; 4 -> inet;
8 -> inet6 8 -> inet6
end, 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) -> strip_ip_option(Opts) ->
{IPL, OptsNoIP} = lists:partition( {IPL, OptsNoIP} = lists:partition(
@ -312,7 +321,9 @@ stop_listener(PortIP, _Module) ->
%% Opts = [IPV | {ip, IPT} | atom() | tuple()] %% Opts = [IPV | {ip, IPT} | atom() | tuple()]
%% @doc Add a listener and store in config if success %% @doc Add a listener and store in config if success
add_listener(PortIP, Module, Opts) -> 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} -> {ok, _Pid} ->
Ports = case ejabberd_config:get_local_option(listen) of Ports = case ejabberd_config:get_local_option(listen) of
undefined -> undefined ->
@ -320,33 +331,39 @@ add_listener(PortIP, Module, Opts) ->
Ls -> Ls ->
Ls Ls
end, end,
Ports1 = lists:keydelete(PortIP, 1, Ports), Ports1 = lists:keydelete(PortIP1, 1, Ports),
Ports2 = [{PortIP, Module, Opts} | Ports1], Ports2 = [{PortIP1, Module, Opts} | Ports1],
ejabberd_config:add_local_option(listen, Ports2), ejabberd_config:add_local_option(listen, Ports2),
ok; ok;
{error, {already_started, _Pid}} -> {error, {already_started, _Pid}} ->
{error, {already_started, PortIP}}; {error, {already_started, PortIP}};
{error, Error} -> {error, Error} ->
{error, Error} {error, Error}
end. end.
%% @spec (PortIP, Module) -> ok delete_listener(PortIP, Module) ->
delete_listener(PortIP, Module, []).
%% @spec (PortIP, Module, Opts) -> ok
%% where %% where
%% PortIP = {Port, IPT | IPS} %% PortIP = {Port, IPT | IPS}
%% Port = integer() %% Port = integer()
%% IPT = tuple() %% IPT = tuple()
%% IPS = string() %% IPS = string()
%% Module = atom() %% 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 Ports = case ejabberd_config:get_local_option(listen) of
undefined -> undefined ->
[]; [];
Ls -> Ls ->
Ls Ls
end, end,
Ports1 = lists:keydelete(PortIP, 1, Ports), Ports1 = lists:keydelete(PortIP1, 1, Ports),
ejabberd_config:add_local_option(listen, Ports1), ejabberd_config:add_local_option(listen, Ports1),
stop_listener(PortIP, Module). stop_listener(PortIP1, Module).
is_frontend({frontend, _Module}) -> true; is_frontend({frontend, _Module}) -> true;
is_frontend(_) -> false. is_frontend(_) -> false.
@ -401,6 +418,22 @@ certfile_readable(Opts) ->
end end
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) -> socket_error(Reason, PortIP, Module, SockOpts, Port, IPS) ->
ReasonT = case Reason of ReasonT = case Reason of
eaddrnotavail -> eaddrnotavail ->