From 7813f402c6164ba4f00d23ebedd6e1107bbd2b0b Mon Sep 17 00:00:00 2001 From: JianBo He Date: Tue, 3 May 2022 16:52:38 +0800 Subject: [PATCH 1/6] feat(api-clients): return client mountpoint property --- .../i18n/emqx_gateway_api_clients_i18n.conf | 7 +++++++ apps/emqx_gateway/src/emqx_gateway_api_clients.erl | 14 +++++++++----- apps/emqx_management/src/emqx_mgmt_api_clients.erl | 2 +- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/apps/emqx_gateway/i18n/emqx_gateway_api_clients_i18n.conf b/apps/emqx_gateway/i18n/emqx_gateway_api_clients_i18n.conf index 8da672586..1e6f575c3 100644 --- a/apps/emqx_gateway/i18n/emqx_gateway_api_clients_i18n.conf +++ b/apps/emqx_gateway/i18n/emqx_gateway_api_clients_i18n.conf @@ -245,6 +245,13 @@ emqx_gateway_api_clients { } } + mountpoint { + desc { + en: """Topic mountpoint""" + zh: """主题固定前缀""" + } + } + proto_name { desc { en: """Client protocol name""" diff --git a/apps/emqx_gateway/src/emqx_gateway_api_clients.erl b/apps/emqx_gateway/src/emqx_gateway_api_clients.erl index af6393a27..ac0e72c83 100644 --- a/apps/emqx_gateway/src/emqx_gateway_api_clients.erl +++ b/apps/emqx_gateway/src/emqx_gateway_api_clients.erl @@ -174,9 +174,7 @@ clients_insta(delete, #{ {204} end). -%% FIXME: -%% List the subscription without mountpoint, but has SubOpts, -%% for example, share group ... +%% List the established subscriptions with mountpoint subscriptions(get, #{ bindings := #{ name := Name0, @@ -189,7 +187,7 @@ subscriptions(get, #{ {error, not_found} -> return_http_error(404, "client process not found"); {error, Reason} -> - return_http_error(500, Reason); + return_http_error(400, Reason); {ok, Subs} -> {200, Subs} end @@ -216,7 +214,7 @@ subscriptions(post, #{ {error, not_found} -> return_http_error(404, "client process not found"); {error, Reason} -> - return_http_error(500, Reason); + return_http_error(400, Reason); {ok, {NTopic, NSubOpts}} -> {201, maps:merge(NSubOpts, #{topic => NTopic})} end @@ -368,6 +366,7 @@ format_channel_info({_, Infos, Stats} = R) -> {node, ClientInfo, Node}, {clientid, ClientInfo}, {username, ClientInfo}, + {mountpoint, ClientInfo}, {proto_name, ConnInfo}, {proto_ver, ConnInfo}, {ip_address, {peername, ConnInfo, fun peer_to_binary_addr/1}}, @@ -813,6 +812,11 @@ common_client_props() -> binary(), #{desc => ?DESC(username)} )}, + {mountpoint, + mk( + binary(), + #{desc => ?DESC(mountpoint)} + )}, {proto_name, mk( binary(), diff --git a/apps/emqx_management/src/emqx_mgmt_api_clients.erl b/apps/emqx_management/src/emqx_mgmt_api_clients.erl index 033373655..c7ceb26d5 100644 --- a/apps/emqx_management/src/emqx_mgmt_api_clients.erl +++ b/apps/emqx_management/src/emqx_mgmt_api_clients.erl @@ -492,6 +492,7 @@ fields(client) -> " Maximum number of subscriptions allowed by this client">> })}, {username, hoconsc:mk(binary(), #{desc => <<"User name of client when connecting">>})}, + {mountpoint, hoconsc:mk(binary(), #{desc => <<"Topic mountpoint">>})}, {will_msg, hoconsc:mk(binary(), #{desc => <<"Client will message">>})}, {zone, hoconsc:mk(binary(), #{ @@ -849,7 +850,6 @@ format_channel_info({_, ClientInfo0, ClientStats}) -> is_superuser, sockport, anonymous, - mountpoint, socktype, active_n, await_rel_timeout, From 42e193d9be5dd5ce4fd6cd18883a53b744625f82 Mon Sep 17 00:00:00 2001 From: JianBo He Date: Tue, 3 May 2022 16:54:14 +0800 Subject: [PATCH 2/6] refactor(mqttsn): create subscription with any topic format --- .../src/mqttsn/emqx_sn_channel.erl | 24 ++++--------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/apps/emqx_gateway/src/mqttsn/emqx_sn_channel.erl b/apps/emqx_gateway/src/mqttsn/emqx_sn_channel.erl index cf0681c25..9955f75d9 100644 --- a/apps/emqx_gateway/src/mqttsn/emqx_sn_channel.erl +++ b/apps/emqx_gateway/src/mqttsn/emqx_sn_channel.erl @@ -1782,25 +1782,11 @@ message_to_packet( | {shutdown, Reason :: term(), Reply :: term(), channel()} | {shutdown, Reason :: term(), Reply :: term(), emqx_types:packet(), channel()}. handle_call({subscribe, Topic, SubOpts}, _From, Channel) -> - %% XXX: Only support short_topic_name - SubProps = maps:get(sub_props, SubOpts, #{}), - case maps:get(subtype, SubProps, short_topic_name) of - short_topic_name -> - case byte_size(Topic) of - 2 -> - case do_subscribe({?SN_INVALID_TOPIC_ID, Topic, SubOpts}, Channel) of - {ok, {_, NTopicName, NSubOpts}, NChannel} -> - reply({ok, {NTopicName, NSubOpts}}, NChannel); - {error, ?SN_RC2_EXCEED_LIMITATION} -> - reply({error, exceed_limitation}, Channel) - end; - _ -> - reply({error, bad_topic_name}, Channel) - end; - predefined_topic_id -> - reply({error, only_support_short_name_topic}, Channel); - _ -> - reply({error, only_support_short_name_topic}, Channel) + case do_subscribe({?SN_INVALID_TOPIC_ID, Topic, SubOpts}, Channel) of + {ok, {_, NTopicName, NSubOpts}, NChannel} -> + reply({ok, {NTopicName, NSubOpts}}, NChannel); + {error, ?SN_RC2_EXCEED_LIMITATION} -> + reply({error, exceed_limitation}, Channel) end; handle_call({unsubscribe, Topic}, _From, Channel) -> TopicFilters = [emqx_topic:parse(Topic)], From 5d362eeb60ca65e2bee7abd1ab40f7c0da7f9c17 Mon Sep 17 00:00:00 2001 From: JianBo He Date: Tue, 3 May 2022 11:33:41 +0800 Subject: [PATCH 3/6] fix(gw): fix bad conn property type --- apps/emqx_gateway/src/coap/emqx_coap_channel.erl | 2 +- apps/emqx_gateway/src/stomp/emqx_stomp_channel.erl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/emqx_gateway/src/coap/emqx_coap_channel.erl b/apps/emqx_gateway/src/coap/emqx_coap_channel.erl index 1edc28494..207524448 100644 --- a/apps/emqx_gateway/src/coap/emqx_coap_channel.erl +++ b/apps/emqx_gateway/src/coap/emqx_coap_channel.erl @@ -579,7 +579,7 @@ ensure_connected( } ) -> NConnInfo = ConnInfo#{connected_at => erlang:system_time(millisecond)}, - _ = run_hooks(Ctx, 'client.connack', [NConnInfo, connection_accepted, []]), + _ = run_hooks(Ctx, 'client.connack', [NConnInfo, connection_accepted, #{}]), ok = run_hooks(Ctx, 'client.connected', [ClientInfo, NConnInfo]), Channel#channel{conninfo = NConnInfo, conn_state = connected}. diff --git a/apps/emqx_gateway/src/stomp/emqx_stomp_channel.erl b/apps/emqx_gateway/src/stomp/emqx_stomp_channel.erl index 4ef48d264..6e6a67d0b 100644 --- a/apps/emqx_gateway/src/stomp/emqx_stomp_channel.erl +++ b/apps/emqx_gateway/src/stomp/emqx_stomp_channel.erl @@ -417,10 +417,10 @@ handle_in(Packet = ?PACKET(?CMD_CONNECT), Channel) -> emqx_misc:pipeline( [ fun enrich_conninfo/2, - fun run_conn_hooks/2, fun negotiate_version/2, fun enrich_clientinfo/2, fun assign_clientid_to_conninfo/2, + fun run_conn_hooks/2, fun set_log_meta/2, %% TODO: How to implement the banned in the gateway instance? %, fun check_banned/2 @@ -755,7 +755,7 @@ handle_out( } ) -> %% XXX: connection_accepted is not defined by stomp protocol - _ = run_hooks(Ctx, 'client.connack', [ConnInfo, connection_accepted, []]), + _ = run_hooks(Ctx, 'client.connack', [ConnInfo, connection_accepted, #{}]), Replies = [ {outgoing, connected_frame(Headers)}, {event, connected} From 5698b9cfeb7e64455023883d96163b2b4ae88c35 Mon Sep 17 00:00:00 2001 From: JianBo He Date: Tue, 3 May 2022 11:58:27 +0800 Subject: [PATCH 4/6] fix(gw): fix bad_ssl_config bad match --- apps/emqx_gateway/src/emqx_gateway_http.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/emqx_gateway/src/emqx_gateway_http.erl b/apps/emqx_gateway/src/emqx_gateway_http.erl index f8cf4f96f..f104c6629 100644 --- a/apps/emqx_gateway/src/emqx_gateway_http.erl +++ b/apps/emqx_gateway/src/emqx_gateway_http.erl @@ -514,8 +514,9 @@ with_gateway(GwName0, Fun) -> ), return_http_error(404, "Resource not found. path: " ++ Path); %% Exceptions from emqx_gateway_conf:convert_certs/2,3 - error:{bad_ssl_config, #{which_option := Option}} -> - return_http_error(400, ["Bad SSL config, option: ", Option]); + error:{bad_ssl_config, Reason0} -> + Reason = emqx_gateway_utils:stringfy(Reason0), + return_http_error(400, ["Bad SSL config, reason: ", Reason]); Class:Reason:Stk -> ?SLOG(error, #{ msg => "uncatched_error", From 5bfb9367ea8ff9be8bcc20308608bc78e20506de Mon Sep 17 00:00:00 2001 From: JianBo He Date: Tue, 3 May 2022 17:54:00 +0800 Subject: [PATCH 5/6] chore(tls): guard empty pem/path string --- apps/emqx/src/emqx_tls_lib.erl | 1 + apps/emqx/test/emqx_tls_lib_tests.erl | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/apps/emqx/src/emqx_tls_lib.erl b/apps/emqx/src/emqx_tls_lib.erl index 27373eb7c..4250ff430 100644 --- a/apps/emqx/src/emqx_tls_lib.erl +++ b/apps/emqx/src/emqx_tls_lib.erl @@ -368,6 +368,7 @@ do_ensure_ssl_file(Dir, Key, SSL, MaybePem, DryRun) -> end end. +is_valid_string(Empty) when Empty == <<>>; Empty == "" -> false; is_valid_string(String) when is_list(String) -> io_lib:printable_unicode_list(String); is_valid_string(Binary) when is_binary(Binary) -> diff --git a/apps/emqx/test/emqx_tls_lib_tests.erl b/apps/emqx/test/emqx_tls_lib_tests.erl index 93a105ea3..22c480637 100644 --- a/apps/emqx/test/emqx_tls_lib_tests.erl +++ b/apps/emqx/test/emqx_tls_lib_tests.erl @@ -104,6 +104,17 @@ ssl_files_failure_test_() -> ) end}, {"bad_pem_string", fun() -> + %% empty string + ?assertMatch( + {error, #{ + reason := invalid_file_path_or_pem_string, which_options := [<<"keyfile">>] + }}, + emqx_tls_lib:ensure_ssl_files("/tmp", #{ + <<"keyfile">> => <<>>, + <<"certfile">> => bin(test_key()), + <<"cacertfile">> => bin(test_key()) + }) + ), %% not valid unicode ?assertMatch( {error, #{ From 62a0df69fc9d2065945396838254d3c5a1c8232d Mon Sep 17 00:00:00 2001 From: JianBo He Date: Thu, 5 May 2022 10:47:59 +0800 Subject: [PATCH 6/6] fix(limiter): avoid maps:get/2 crash --- apps/emqx/src/emqx_listeners.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/emqx/src/emqx_listeners.erl b/apps/emqx/src/emqx_listeners.erl index afe3cec5d..fcd952696 100644 --- a/apps/emqx/src/emqx_listeners.erl +++ b/apps/emqx/src/emqx_listeners.erl @@ -489,7 +489,7 @@ zone(Opts) -> maps:get(zone, Opts, undefined). limiter(Opts) -> - maps:get(limiter, Opts). + maps:get(limiter, Opts, #{}). ssl_opts(Opts) -> maps:to_list(