Jelajahi Sumber

refactor: more random bytes for broker assigned IDs

Also got rid of base62 encode for GUID as integer.
zmstone 1 tahun lalu
induk
melakukan
0d7175af92

+ 1 - 3
apps/emqx/src/emqx_base62.erl

@@ -27,9 +27,7 @@
 %%--------------------------------------------------------------------
 
 %% @doc Encode any data to base62 binary
--spec encode(string() | integer() | binary()) -> binary().
-encode(I) when is_integer(I) ->
-    encode(integer_to_binary(I));
+-spec encode(string() | binary()) -> binary().
 encode(S) when is_list(S) ->
     encode(unicode:characters_to_binary(S));
 encode(B) when is_binary(B) ->

+ 2 - 2
apps/emqx/src/emqx_channel.erl

@@ -155,6 +155,7 @@
 
 -define(LIMITER_ROUTING, message_routing).
 -define(chan_terminating, chan_terminating).
+-define(RAND_CLIENTID_BYTES, 16).
 
 -dialyzer({no_match, [shutdown/4, ensure_timer/2, interval/2]}).
 
@@ -1704,8 +1705,7 @@ maybe_assign_clientid(_ConnPkt, ClientInfo = #{clientid := ClientId}) when
 ->
     {ok, ClientInfo};
 maybe_assign_clientid(#mqtt_packet_connect{clientid = <<>>}, ClientInfo) ->
-    %% Generate a rand clientId
-    {ok, ClientInfo#{clientid => emqx_guid:to_base62(emqx_guid:gen())}};
+    {ok, ClientInfo#{clientid => emqx_utils:rand_id(?RAND_CLIENTID_BYTES)}};
 maybe_assign_clientid(#mqtt_packet_connect{clientid = ClientId}, ClientInfo) ->
     {ok, ClientInfo#{clientid => ClientId}}.
 

+ 2 - 11
apps/emqx/src/emqx_guid.erl

@@ -35,9 +35,7 @@
     new/0,
     timestamp/1,
     to_hexstr/1,
-    from_hexstr/1,
-    to_base62/1,
-    from_base62/1
+    from_hexstr/1
 ]).
 
 -export_type([guid/0]).
@@ -83,7 +81,7 @@ npid() ->
     <<NodeD01, NodeD02, NodeD03, NodeD04, NodeD05, NodeD06, NodeD07, NodeD08, NodeD09, NodeD10,
         NodeD11, NodeD12, NodeD13, NodeD14, NodeD15, NodeD16, NodeD17, NodeD18, NodeD19,
         NodeD20>> =
-        crypto:hash(sha, erlang:list_to_binary(erlang:atom_to_list(node()))),
+        crypto:hash(sha, erlang:atom_to_binary(node())),
 
     PidBin =
         case erlang:term_to_binary(self()) of
@@ -149,10 +147,3 @@ to_hexstr(I) when byte_size(I) =:= 16 ->
 
 from_hexstr(S) when byte_size(S) =:= 32 ->
     emqx_utils:hexstr_to_bin(S).
-
-to_base62(<<I:128>>) ->
-    emqx_base62:encode(I).
-
-from_base62(S) ->
-    I = binary_to_integer(emqx_base62:decode(S)),
-    <<I:128>>.

+ 0 - 4
apps/emqx/test/emqx_guid_SUITE.erl

@@ -35,7 +35,3 @@ t_guid_gen(_) ->
 t_guid_hexstr(_) ->
     Guid = emqx_guid:gen(),
     ?assertEqual(Guid, emqx_guid:from_hexstr(emqx_guid:to_hexstr(Guid))).
-
-t_guid_base62(_) ->
-    Guid = emqx_guid:gen(),
-    ?assertEqual(Guid, emqx_guid:from_base62(emqx_guid:to_base62(Guid))).

+ 1 - 1
apps/emqx/test/props/prop_emqx_base62.erl

@@ -75,4 +75,4 @@ base62_size(Data, Encoded) ->
 %%--------------------------------------------------------------------
 
 raw_data() ->
-    oneof([integer(), string(), binary()]).
+    oneof([string(), binary()]).

+ 1 - 1
apps/emqx_bridge_rocketmq/src/emqx_bridge_rocketmq.app.src

@@ -1,6 +1,6 @@
 {application, emqx_bridge_rocketmq, [
     {description, "EMQX Enterprise RocketMQ Bridge"},
-    {vsn, "0.2.3"},
+    {vsn, "0.2.4"},
     {registered, []},
     {applications, [kernel, stdlib, emqx_resource, rocketmq]},
     {env, [

+ 1 - 1
apps/emqx_bridge_rocketmq/src/emqx_bridge_rocketmq_connector.erl

@@ -360,7 +360,7 @@ parse_dispatch_strategy(Template) ->
                         %% better distribute the load, effectively making it `random'
                         %% dispatch if the key is absent and we are using `key_dispatch'.
                         %% Otherwise, it'll be deterministic.
-                        emqx_guid:to_base62(emqx_guid:gen());
+                        emqx_utils:rand_id(8);
                     Key ->
                         Key
                 end

+ 1 - 1
apps/emqx_ft/test/emqx_ft_conf_SUITE.erl

@@ -349,7 +349,7 @@ mk_s3_config(S3Config) ->
     maps:merge(BaseS3Config, S3Config).
 
 gen_clientid() ->
-    emqx_base62:encode(emqx_guid:gen()).
+    emqx_utils:rand_id(16).
 
 list_ssl_certfiles(_Config) ->
     CertDir = emqx:mutable_certs_dir(),

+ 2 - 1
apps/emqx_gateway_coap/src/emqx_coap_channel.erl

@@ -86,6 +86,7 @@
 -define(INFO_KEYS, [conninfo, conn_state, clientinfo, session]).
 
 -define(DEF_IDLE_SECONDS, 30).
+-define(RAND_CLIENTID_BYTES, 16).
 
 -import(emqx_coap_medium, [reply/2, reply/3, reply/4, iter/3, iter/4]).
 
@@ -142,7 +143,7 @@ init(
             peerhost => PeerHost,
             peername => PeerName,
             sockport => SockPort,
-            clientid => emqx_guid:to_base62(emqx_guid:gen()),
+            clientid => emqx_utils:rand_id(?RAND_CLIENTID_BYTES),
             username => undefined,
             is_bridge => false,
             is_superuser => false,

+ 1 - 1
apps/emqx_gateway_coap/src/emqx_gateway_coap.app.src

@@ -1,7 +1,7 @@
 %% -*- mode: erlang -*-
 {application, emqx_gateway_coap, [
     {description, "CoAP Gateway"},
-    {vsn, "0.1.10"},
+    {vsn, "0.1.11"},
     {registered, []},
     {applications, [kernel, stdlib, emqx, emqx_gateway]},
     {env, []},

+ 1 - 1
apps/emqx_gateway_mqttsn/src/emqx_gateway_mqttsn.app.src

@@ -1,7 +1,7 @@
 %% -*- mode: erlang -*-
 {application, emqx_gateway_mqttsn, [
     {description, "MQTT-SN Gateway"},
-    {vsn, "0.2.3"},
+    {vsn, "0.2.4"},
     {registered, []},
     {applications, [kernel, stdlib, emqx, emqx_gateway]},
     {env, []},

+ 3 - 1
apps/emqx_gateway_mqttsn/src/emqx_mqttsn_channel.erl

@@ -123,6 +123,8 @@
 %% 2h
 -define(DEFAULT_SESSION_EXPIRY, 7200000).
 
+-define(RAND_CLIENTID_BYTES, 16).
+
 %%--------------------------------------------------------------------
 %% Init the channel
 %%--------------------------------------------------------------------
@@ -307,7 +309,7 @@ maybe_assign_clientid(_Packet, ClientInfo = #{clientid := ClientId}) when
     ClientId == undefined;
     ClientId == <<>>
 ->
-    {ok, ClientInfo#{clientid => emqx_guid:to_base62(emqx_guid:gen())}};
+    {ok, ClientInfo#{clientid => emqx_utils:rand_id(?RAND_CLIENTID_BYTES)}};
 maybe_assign_clientid(_Packet, ClientInfo) ->
     {ok, ClientInfo}.
 

+ 1 - 1
apps/emqx_gateway_stomp/src/emqx_gateway_stomp.app.src

@@ -1,7 +1,7 @@
 %% -*- mode: erlang -*-
 {application, emqx_gateway_stomp, [
     {description, "Stomp Gateway"},
-    {vsn, "0.1.7"},
+    {vsn, "0.1.8"},
     {registered, []},
     {applications, [kernel, stdlib, emqx, emqx_gateway]},
     {env, []},

+ 2 - 1
apps/emqx_gateway_stomp/src/emqx_stomp_channel.erl

@@ -109,6 +109,7 @@
 ).
 
 -define(INFO_KEYS, [conninfo, conn_state, clientinfo, session, will_msg]).
+-define(RAND_CLIENTID_BYETS, 16).
 
 %%--------------------------------------------------------------------
 %% Init the channel
@@ -303,7 +304,7 @@ maybe_assign_clientid(_Packet, ClientInfo = #{clientid := ClientId}) when
     ClientId == undefined;
     ClientId == <<>>
 ->
-    {ok, ClientInfo#{clientid => emqx_guid:to_base62(emqx_guid:gen())}};
+    {ok, ClientInfo#{clientid => emqx_utils:rand_id(?RAND_CLIENTID_BYETS)}};
 maybe_assign_clientid(_Packet, ClientInfo) ->
     {ok, ClientInfo}.
 

+ 1 - 1
apps/emqx_management/test/emqx_mgmt_api_test_util.erl

@@ -212,7 +212,7 @@ upload_request(URL, FilePath, Name, MimeType, RequestData, AuthorizationToken) -
     Method = post,
     Filename = filename:basename(FilePath),
     {ok, Data} = file:read_file(FilePath),
-    Boundary = emqx_guid:to_base62(emqx_guid:gen()),
+    Boundary = emqx_utils:rand_id(32),
     RequestBody = format_multipart_formdata(
         Data,
         RequestData,

+ 1 - 1
apps/emqx_utils/src/emqx_utils.app.src

@@ -2,7 +2,7 @@
 {application, emqx_utils, [
     {description, "Miscellaneous utilities for EMQX apps"},
     % strict semver, bump manually!
-    {vsn, "5.3.0"},
+    {vsn, "5.4.0"},
     {modules, [
         emqx_utils,
         emqx_utils_api,

+ 21 - 0
apps/emqx_utils/src/emqx_utils.erl

@@ -43,6 +43,7 @@
     proc_stats/0,
     proc_stats/1,
     rand_seed/0,
+    rand_id/1,
     now_to_secs/1,
     now_to_ms/1,
     index_of/2,
@@ -901,6 +902,26 @@ is_restricted_str(String) ->
     RE = <<"^[A-Za-z0-9]+[A-Za-z0-9-_]*$">>,
     match =:= re:run(String, RE, [{capture, none}]).
 
+%% @doc Generate random, printable bytes as an ID.
+%% The first byte is ensured to be a-z or A-Z.
+rand_id(Len) when Len > 0 ->
+    iolist_to_binary([rand_first_char(), rand_chars(Len - 1)]).
+
+rand_first_char() ->
+    base62(rand:uniform(52) - 1).
+
+rand_chars(0) ->
+    [];
+rand_chars(N) ->
+    [rand_char() | rand_chars(N - 1)].
+
+rand_char() ->
+    base62(rand:uniform(62) - 1).
+
+base62(I) when I < 26 -> $A + I;
+base62(I) when I < 52 -> $a + I - 26;
+base62(I) -> $0 + I - 52.
+
 -ifdef(TEST).
 -include_lib("eunit/include/eunit.hrl").
 

+ 1 - 0
changes/ce/fix-13756.en.md

@@ -0,0 +1 @@
+Introduced more randomness to broker assigned client IDs.