Просмотр исходного кода

Merge pull request #8547 from HJianBo/support-listen-ipv6

fix(listener): support listen on ipv6 address
JianBo He 3 лет назад
Родитель
Сommit
39cb667497
3 измененных файлов с 35 добавлено и 8 удалено
  1. 1 0
      CHANGES-5.0.md
  2. 26 2
      apps/emqx/src/emqx_schema.erl
  3. 8 6
      apps/emqx_management/src/emqx_mgmt_cli.erl

+ 1 - 0
CHANGES-5.0.md

@@ -17,6 +17,7 @@
 * Fix `chars_limit` is not working when `formatter` is `json`. [#8518](http://github.com/emqx/emqx/pull/8518)
 * Ensuring that exhook dispatches the client events are sequential. [#8530](https://github.com/emqx/emqx/pull/8530)
 * Avoid using RocksDB backend for persistent sessions when such backend is unavailable. [#8528](https://github.com/emqx/emqx/pull/8528)
+* Support listen on an IPv6 address, e.g: [::1]:1883 or ::1:1883. [#8547](https://github.com/emqx/emqx/pull/8547)
 * GET '/rules' support for pagination and fuzzy search. [#8472](https://github.com/emqx/emqx/pull/8472)
   **‼️ Note** : The previous API only returns array: `[RuleObj1,RuleObj2]`, after updating, it will become
   `{"data": [RuleObj1,RuleObj2], "meta":{"count":2, "limit":100, "page":1}`,

+ 26 - 2
apps/emqx/src/emqx_schema.erl

@@ -2113,9 +2113,13 @@ to_comma_separated_atoms(Str) ->
 to_bar_separated_list(Str) ->
     {ok, string:tokens(Str, "| ")}.
 
+%% @doc support the following format:
+%%  - 127.0.0.1:1883
+%%  - ::1:1883
+%%  - [::1]:1883
 to_ip_port(Str) ->
-    case string:tokens(Str, ": ") of
-        [Ip, Port] ->
+    case split_ip_port(Str) of
+        {Ip, Port} ->
             PortVal = list_to_integer(Port),
             case inet:parse_address(Ip) of
                 {ok, R} ->
@@ -2133,6 +2137,26 @@ to_ip_port(Str) ->
             {error, Str}
     end.
 
+split_ip_port(Str0) ->
+    Str = re:replace(Str0, " ", "", [{return, list}, global]),
+    case lists:split(string:rchr(Str, $:), Str) of
+        %% no port
+        {[], Str} ->
+            error;
+        {IpPlusColon, PortString} ->
+            IpStr0 = lists:droplast(IpPlusColon),
+            case IpStr0 of
+                %% dropp head/tail brackets
+                [$[ | S] ->
+                    case lists:last(S) of
+                        $] -> {lists:droplast(S), PortString};
+                        _ -> error
+                    end;
+                _ ->
+                    {IpStr0, PortString}
+            end
+    end.
+
 to_erl_cipher_suite(Str) ->
     case ssl:str_to_suite(Str) of
         {error, Reason} -> error({invalid_cipher, Reason});

+ 8 - 6
apps/emqx_management/src/emqx_mgmt_cli.erl

@@ -566,23 +566,23 @@ trace_type(_, _) -> error.
 listeners([]) ->
     lists:foreach(
         fun({ID, Conf}) ->
-            {Host, Port} = maps:get(bind, Conf),
+            Bind = maps:get(bind, Conf),
             Acceptors = maps:get(acceptors, Conf),
             ProxyProtocol = maps:get(proxy_protocol, Conf, undefined),
             Running = maps:get(running, Conf),
             CurrentConns =
-                case emqx_listeners:current_conns(ID, {Host, Port}) of
+                case emqx_listeners:current_conns(ID, Bind) of
                     {error, _} -> [];
                     CC -> [{current_conn, CC}]
                 end,
             MaxConn =
-                case emqx_listeners:max_conns(ID, {Host, Port}) of
+                case emqx_listeners:max_conns(ID, Bind) of
                     {error, _} -> [];
                     MC -> [{max_conns, MC}]
                 end,
             Info =
                 [
-                    {listen_on, {string, format_listen_on(Port)}},
+                    {listen_on, {string, format_listen_on(Bind)}},
                     {acceptors, Acceptors},
                     {proxy_protocol, ProxyProtocol},
                     {running, Running}
@@ -806,8 +806,10 @@ format_listen_on(Port) when is_integer(Port) ->
     io_lib:format("0.0.0.0:~w", [Port]);
 format_listen_on({Addr, Port}) when is_list(Addr) ->
     io_lib:format("~ts:~w", [Addr, Port]);
-format_listen_on({Addr, Port}) when is_tuple(Addr) ->
-    io_lib:format("~ts:~w", [inet:ntoa(Addr), Port]).
+format_listen_on({Addr, Port}) when is_tuple(Addr) andalso tuple_size(Addr) == 4 ->
+    io_lib:format("~ts:~w", [inet:ntoa(Addr), Port]);
+format_listen_on({Addr, Port}) when is_tuple(Addr) andalso tuple_size(Addr) == 8 ->
+    io_lib:format("[~ts]:~w", [inet:ntoa(Addr), Port]).
 
 name(Filter) ->
     iolist_to_binary(["CLI-", Filter]).