]> granicus.if.org Git - ejabberd/commitdiff
it is now possible to start TCP/UDP on the same port
authorEvgeniy Khramtsov <xramtsov@gmail.com>
Tue, 11 Aug 2009 07:15:36 +0000 (07:15 +0000)
committerEvgeniy Khramtsov <xramtsov@gmail.com>
Tue, 11 Aug 2009 07:15:36 +0000 (07:15 +0000)
SVN Revision: 2452

src/ejabberd_config.erl
src/ejabberd_listener.erl

index d673818c1bb9271dc6240ce31573171472905363..1f583114027db1ff101855393fddb6ef4330285f 100644 (file)
@@ -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);
index f612723d8ff381be23faeceefe87fab4ecca233a..26167351f3872318ee60d479dbc2f9c911154914 100644 (file)
@@ -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 ->