summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChunyi Lyu <chunyineko@gmail.com>2023-01-27 18:25:57 +0000
committerGitHub <noreply@github.com>2023-01-27 18:25:57 +0000
commit209f23fa2f58e0240116b3e8e5be9cd54d34b569 (patch)
treee1d0cf90db0c4fcbea2633a2ebc070c8a5341b87
parent6806a9a45e1e2aa7ce8806c8ca5c4ee14dfef02e (diff)
downloadrabbitmq-server-git-209f23fa2f58e0240116b3e8e5be9cd54d34b569.tar.gz
Revert "Format MQTT code with `erlfmt`"
-rw-r--r--.git-blame-ignore-revs1
-rw-r--r--deps/rabbitmq_mqtt/src/Elixir.RabbitMQ.CLI.Ctl.Commands.DecommissionMqttNodeCommand.erl45
-rw-r--r--deps/rabbitmq_mqtt/src/Elixir.RabbitMQ.CLI.Ctl.Commands.ListMqttConnectionsCommand.erl62
-rw-r--r--deps/rabbitmq_mqtt/src/mqtt_machine.erl284
-rw-r--r--deps/rabbitmq_mqtt/src/mqtt_machine_v0.erl112
-rw-r--r--deps/rabbitmq_mqtt/src/mqtt_node.erl119
-rw-r--r--deps/rabbitmq_mqtt/src/rabbit_mqtt.erl62
-rw-r--r--deps/rabbitmq_mqtt/src/rabbit_mqtt_collector.erl35
-rw-r--r--deps/rabbitmq_mqtt/src/rabbit_mqtt_confirms.erl71
-rw-r--r--deps/rabbitmq_mqtt/src/rabbit_mqtt_ff.erl20
-rw-r--r--deps/rabbitmq_mqtt/src/rabbit_mqtt_internal_event_handler.erl4
-rw-r--r--deps/rabbitmq_mqtt/src/rabbit_mqtt_keepalive.erl80
-rw-r--r--deps/rabbitmq_mqtt/src/rabbit_mqtt_packet.erl300
-rw-r--r--deps/rabbitmq_mqtt/src/rabbit_mqtt_processor.erl2427
-rw-r--r--deps/rabbitmq_mqtt/src/rabbit_mqtt_qos0_queue.erl228
-rw-r--r--deps/rabbitmq_mqtt/src/rabbit_mqtt_reader.erl543
-rw-r--r--deps/rabbitmq_mqtt/src/rabbit_mqtt_retained_msg_store_dets.erl52
-rw-r--r--deps/rabbitmq_mqtt/src/rabbit_mqtt_retained_msg_store_ets.erl52
-rw-r--r--deps/rabbitmq_mqtt/src/rabbit_mqtt_retained_msg_store_noop.erl12
-rw-r--r--deps/rabbitmq_mqtt/src/rabbit_mqtt_retainer.erl64
-rw-r--r--deps/rabbitmq_mqtt/src/rabbit_mqtt_retainer_sup.erl41
-rw-r--r--deps/rabbitmq_mqtt/src/rabbit_mqtt_sup.erl139
-rw-r--r--deps/rabbitmq_mqtt/src/rabbit_mqtt_util.erl98
-rw-r--r--deps/rabbitmq_mqtt/test/auth_SUITE.erl937
-rw-r--r--deps/rabbitmq_mqtt/test/cluster_SUITE.erl101
-rw-r--r--deps/rabbitmq_mqtt/test/command_SUITE.erl72
-rw-r--r--deps/rabbitmq_mqtt/test/config_SUITE.erl77
-rw-r--r--deps/rabbitmq_mqtt/test/config_schema_SUITE.erl29
-rw-r--r--deps/rabbitmq_mqtt/test/event_recorder.erl9
-rw-r--r--deps/rabbitmq_mqtt/test/ff_SUITE.erl128
-rw-r--r--deps/rabbitmq_mqtt/test/java_SUITE.erl80
-rw-r--r--deps/rabbitmq_mqtt/test/mqtt_machine_SUITE.erl90
-rw-r--r--deps/rabbitmq_mqtt/test/processor_SUITE.erl106
-rw-r--r--deps/rabbitmq_mqtt/test/proxy_protocol_SUITE.erl63
-rw-r--r--deps/rabbitmq_mqtt/test/rabbit_auth_backend_mqtt_mock.erl24
-rw-r--r--deps/rabbitmq_mqtt/test/reader_SUITE.erl186
-rw-r--r--deps/rabbitmq_mqtt/test/retainer_SUITE.erl84
-rw-r--r--deps/rabbitmq_mqtt/test/shared_SUITE.erl1245
-rw-r--r--deps/rabbitmq_mqtt/test/util.erl160
-rw-r--r--deps/rabbitmq_mqtt/test/util_SUITE.erl17
-rw-r--r--deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_app.erl125
-rw-r--r--deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_handler.erl347
-rw-r--r--deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_stream_handler.erl1
-rw-r--r--deps/rabbitmq_web_mqtt/test/config_schema_SUITE.erl29
-rw-r--r--deps/rabbitmq_web_mqtt/test/proxy_protocol_SUITE.erl78
-rw-r--r--deps/rabbitmq_web_mqtt/test/system_SUITE.erl39
-rw-r--r--rebar.config7
47 files changed, 3500 insertions, 5385 deletions
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
deleted file mode 100644
index a751518a68..0000000000
--- a/.git-blame-ignore-revs
+++ /dev/null
@@ -1 +0,0 @@
-1de9fcf582def91d1cee6bea457dd24e8a53a431
diff --git a/deps/rabbitmq_mqtt/src/Elixir.RabbitMQ.CLI.Ctl.Commands.DecommissionMqttNodeCommand.erl b/deps/rabbitmq_mqtt/src/Elixir.RabbitMQ.CLI.Ctl.Commands.DecommissionMqttNodeCommand.erl
index a89dad8d16..fa8e09341c 100644
--- a/deps/rabbitmq_mqtt/src/Elixir.RabbitMQ.CLI.Ctl.Commands.DecommissionMqttNodeCommand.erl
+++ b/deps/rabbitmq_mqtt/src/Elixir.RabbitMQ.CLI.Ctl.Commands.DecommissionMqttNodeCommand.erl
@@ -10,20 +10,18 @@
-behaviour('Elixir.RabbitMQ.CLI.CommandBehaviour').
--export([
- scopes/0,
- switches/0,
- aliases/0,
- usage/0,
- usage_doc_guides/0,
- banner/2,
- validate/2,
- merge_defaults/2,
- run/2,
- output/2,
- description/0,
- help_section/0
-]).
+-export([scopes/0,
+ switches/0,
+ aliases/0,
+ usage/0,
+ usage_doc_guides/0,
+ banner/2,
+ validate/2,
+ merge_defaults/2,
+ run/2,
+ output/2,
+ description/0,
+ help_section/0]).
scopes() -> [ctl].
switches() -> [].
@@ -50,29 +48,20 @@ usage() ->
usage_doc_guides() ->
[?MQTT_GUIDE_URL].
-run([Node], #{
- node := NodeName,
- timeout := Timeout
-}) ->
+run([Node], #{node := NodeName,
+ timeout := Timeout}) ->
case rabbit_misc:rpc_call(NodeName, rabbit_mqtt_collector, leave, [Node], Timeout) of
{badrpc, _} = Error ->
Error;
nodedown ->
- {ok,
- list_to_binary(
- io_lib:format(
- "Node ~ts is down but has been successfully removed"
- " from the cluster",
- [Node]
- )
- )};
+ {ok, list_to_binary(io_lib:format("Node ~ts is down but has been successfully removed"
+ " from the cluster", [Node]))};
Result ->
%% 'ok' or 'timeout'
Result
end.
-banner([Node], _) ->
- list_to_binary(io_lib:format("Removing node ~ts from the list of MQTT nodes...", [Node])).
+banner([Node], _) -> list_to_binary(io_lib:format("Removing node ~ts from the list of MQTT nodes...", [Node])).
output(Result, _Opts) ->
'Elixir.RabbitMQ.CLI.DefaultOutput':output(Result).
diff --git a/deps/rabbitmq_mqtt/src/Elixir.RabbitMQ.CLI.Ctl.Commands.ListMqttConnectionsCommand.erl b/deps/rabbitmq_mqtt/src/Elixir.RabbitMQ.CLI.Ctl.Commands.ListMqttConnectionsCommand.erl
index f40868cd83..07265b56e1 100644
--- a/deps/rabbitmq_mqtt/src/Elixir.RabbitMQ.CLI.Ctl.Commands.ListMqttConnectionsCommand.erl
+++ b/deps/rabbitmq_mqtt/src/Elixir.RabbitMQ.CLI.Ctl.Commands.ListMqttConnectionsCommand.erl
@@ -10,22 +10,20 @@
-behaviour('Elixir.RabbitMQ.CLI.CommandBehaviour').
--export([
- formatter/0,
- scopes/0,
- switches/0,
- aliases/0,
- usage/0,
- usage_additional/0,
- usage_doc_guides/0,
- banner/2,
- validate/2,
- merge_defaults/2,
- run/2,
- output/2,
- description/0,
- help_section/0
-]).
+-export([formatter/0,
+ scopes/0,
+ switches/0,
+ aliases/0,
+ usage/0,
+ usage_additional/0,
+ usage_doc_guides/0,
+ banner/2,
+ validate/2,
+ merge_defaults/2,
+ run/2,
+ output/2,
+ description/0,
+ help_section/0]).
formatter() -> 'Elixir.RabbitMQ.CLI.Formatters.Table'.
scopes() -> [ctl, diagnostics].
@@ -39,14 +37,10 @@ help_section() ->
validate(Args, _) ->
InfoItems = lists:map(fun atom_to_list/1, ?INFO_ITEMS),
- case
- 'Elixir.RabbitMQ.CLI.Ctl.InfoKeys':validate_info_keys(
- Args,
- InfoItems
- )
- of
+ case 'Elixir.RabbitMQ.CLI.Ctl.InfoKeys':validate_info_keys(Args,
+ InfoItems) of
{ok, _} -> ok;
- Error -> Error
+ Error -> Error
end.
merge_defaults([], Opts) ->
@@ -61,22 +55,19 @@ usage_additional() ->
Prefix = <<" must be one of ">>,
InfoItems = 'Elixir.Enum':join(lists:usort(?INFO_ITEMS), <<", ">>),
[
- {<<"<column>">>, <<Prefix/binary, InfoItems/binary>>}
+ {<<"<column>">>, <<Prefix/binary, InfoItems/binary>>}
].
usage_doc_guides() ->
[?MQTT_GUIDE_URL].
-run(Args, #{
- node := NodeName,
- timeout := Timeout,
- verbose := Verbose
-}) ->
- InfoKeys =
- case Verbose of
- true -> ?INFO_ITEMS;
- false -> 'Elixir.RabbitMQ.CLI.Ctl.InfoKeys':prepare_info_keys(Args)
- end,
+run(Args, #{node := NodeName,
+ timeout := Timeout,
+ verbose := Verbose}) ->
+ InfoKeys = case Verbose of
+ true -> ?INFO_ITEMS;
+ false -> 'Elixir.RabbitMQ.CLI.Ctl.InfoKeys':prepare_info_keys(Args)
+ end,
Nodes = 'Elixir.RabbitMQ.CLI.Core.Helpers':nodes_in_cluster(NodeName),
@@ -87,8 +78,7 @@ run(Args, #{
[Nodes, InfoKeys],
Timeout,
InfoKeys,
- length(Nodes)
- ).
+ length(Nodes)).
banner(_, _) -> <<"Listing MQTT connections ...">>.
diff --git a/deps/rabbitmq_mqtt/src/mqtt_machine.erl b/deps/rabbitmq_mqtt/src/mqtt_machine.erl
index 36c0c7e70f..20e69a7a2a 100644
--- a/deps/rabbitmq_mqtt/src/mqtt_machine.erl
+++ b/deps/rabbitmq_mqtt/src/mqtt_machine.erl
@@ -9,15 +9,13 @@
-include("mqtt_machine.hrl").
--export([
- version/0,
- which_module/1,
- init/1,
- apply/3,
- state_enter/2,
- notify_connection/2,
- overview/1
-]).
+-export([version/0,
+ which_module/1,
+ init/1,
+ apply/3,
+ state_enter/2,
+ notify_connection/2,
+ overview/1]).
-type state() :: #machine_state{}.
@@ -26,10 +24,9 @@
-type reply() :: {ok, term()} | {error, term()}.
-type client_id() :: term().
--type command() ::
- {register, client_id(), pid()}
- | {unregister, client_id(), pid()}
- | list.
+-type command() :: {register, client_id(), pid()} |
+ {unregister, client_id(), pid()} |
+ list.
version() -> 1.
which_module(1) -> ?MODULE;
@@ -41,130 +38,93 @@ init(_Conf) ->
-spec apply(map(), command(), state()) ->
{state(), reply(), ra_machine:effects()}.
-apply(
- _Meta,
- {register, ClientId, Pid},
- #machine_state{
- client_ids = Ids,
- pids = Pids0
- } = State0
-) ->
+apply(_Meta, {register, ClientId, Pid},
+ #machine_state{client_ids = Ids,
+ pids = Pids0} = State0) ->
{Effects, Ids1, Pids} =
case maps:find(ClientId, Ids) of
{ok, OldPid} when Pid =/= OldPid ->
- Effects0 = [
- {demonitor, process, OldPid},
- {monitor, process, Pid},
- {mod_call, ?MODULE, notify_connection, [OldPid, duplicate_id]}
- ],
- Pids2 =
- case maps:take(OldPid, Pids0) of
- error ->
- Pids0;
- {[ClientId], Pids1} ->
- Pids1;
- {ClientIds, Pids1} ->
- Pids1#{ClientId => lists:delete(ClientId, ClientIds)}
- end,
- Pids3 = maps:update_with(
- Pid,
- fun(CIds) -> [ClientId | CIds] end,
- [ClientId],
- Pids2
- ),
+ Effects0 = [{demonitor, process, OldPid},
+ {monitor, process, Pid},
+ {mod_call, ?MODULE, notify_connection,
+ [OldPid, duplicate_id]}],
+ Pids2 = case maps:take(OldPid, Pids0) of
+ error ->
+ Pids0;
+ {[ClientId], Pids1} ->
+ Pids1;
+ {ClientIds, Pids1} ->
+ Pids1#{ClientId => lists:delete(ClientId, ClientIds)}
+ end,
+ Pids3 = maps:update_with(Pid, fun(CIds) -> [ClientId | CIds] end,
+ [ClientId], Pids2),
{Effects0, maps:remove(ClientId, Ids), Pids3};
- {ok, Pid} ->
+
+ {ok, Pid} ->
{[], Ids, Pids0};
error ->
- Pids1 = maps:update_with(
- Pid,
- fun(CIds) -> [ClientId | CIds] end,
- [ClientId],
- Pids0
- ),
+ Pids1 = maps:update_with(Pid, fun(CIds) -> [ClientId | CIds] end,
+ [ClientId], Pids0),
Effects0 = [{monitor, process, Pid}],
{Effects0, Ids, Pids1}
end,
- State = State0#machine_state{
- client_ids = maps:put(ClientId, Pid, Ids1),
- pids = Pids
- },
+ State = State0#machine_state{client_ids = maps:put(ClientId, Pid, Ids1),
+ pids = Pids},
{State, ok, Effects};
-apply(
- Meta,
- {unregister, ClientId, Pid},
- #machine_state{
- client_ids = Ids,
- pids = Pids0
- } = State0
-) ->
- State =
- case maps:find(ClientId, Ids) of
- {ok, Pid} ->
- Pids =
- case maps:get(Pid, Pids0, undefined) of
- undefined ->
- Pids0;
- [ClientId] ->
- maps:remove(Pid, Pids0);
- Cids ->
- Pids0#{Pid => lists:delete(ClientId, Cids)}
- end,
- State0#machine_state{
- client_ids = maps:remove(ClientId, Ids),
- pids = Pids
- };
- %% don't delete client id that might belong to a newer connection
- %% that kicked the one with Pid out
- {ok, _AnotherPid} ->
- State0;
- error ->
- State0
- end,
+apply(Meta, {unregister, ClientId, Pid}, #machine_state{client_ids = Ids,
+ pids = Pids0} = State0) ->
+ State = case maps:find(ClientId, Ids) of
+ {ok, Pid} ->
+ Pids = case maps:get(Pid, Pids0, undefined) of
+ undefined ->
+ Pids0;
+ [ClientId] ->
+ maps:remove(Pid, Pids0);
+ Cids ->
+ Pids0#{Pid => lists:delete(ClientId, Cids)}
+ end,
+
+ State0#machine_state{client_ids = maps:remove(ClientId, Ids),
+ pids = Pids};
+ %% don't delete client id that might belong to a newer connection
+ %% that kicked the one with Pid out
+ {ok, _AnotherPid} ->
+ State0;
+ error ->
+ State0
+ end,
Effects0 = [{demonitor, process, Pid}],
%% snapshot only when the map has changed
- Effects =
- case State of
- State0 -> Effects0;
- _ -> Effects0 ++ snapshot_effects(Meta, State)
- end,
+ Effects = case State of
+ State0 -> Effects0;
+ _ -> Effects0 ++ snapshot_effects(Meta, State)
+ end,
{State, ok, Effects};
+
apply(_Meta, {down, DownPid, noconnection}, State) ->
%% Monitor the node the pid is on (see {nodeup, Node} below)
%% so that we can detect when the node is re-connected and discover the
%% actual fate of the connection processes on it
Effect = {monitor, node, node(DownPid)},
{State, ok, Effect};
-apply(
- Meta,
- {down, DownPid, _},
- #machine_state{
- client_ids = Ids,
- pids = Pids0
- } = State0
-) ->
+
+apply(Meta, {down, DownPid, _}, #machine_state{client_ids = Ids,
+ pids = Pids0} = State0) ->
case maps:get(DownPid, Pids0, undefined) of
undefined ->
{State0, ok, []};
ClientIds ->
Ids1 = maps:without(ClientIds, Ids),
- State = State0#machine_state{
- client_ids = Ids1,
- pids = maps:remove(DownPid, Pids0)
- },
- Effects = lists:map(
- fun(Id) ->
- [
- {mod_call, rabbit_log, debug, [
- "MQTT connection with client id '~ts' failed", [Id]
- ]}
- ]
- end,
- ClientIds
- ),
+ State = State0#machine_state{client_ids = Ids1,
+ pids = maps:remove(DownPid, Pids0)},
+ Effects = lists:map(fun(Id) ->
+ [{mod_call, rabbit_log, debug,
+ ["MQTT connection with client id '~ts' failed", [Id]]}]
+ end, ClientIds),
{State, ok, Effects ++ snapshot_effects(Meta, State)}
end;
+
apply(_Meta, {nodeup, Node}, State) ->
%% Work out if any pids that were disconnected are still
%% alive.
@@ -173,69 +133,41 @@ apply(_Meta, {nodeup, Node}, State) ->
{State, ok, Effects};
apply(_Meta, {nodedown, _Node}, State) ->
{State, ok};
-apply(
- Meta,
- {leave, Node},
- #machine_state{
- client_ids = Ids,
- pids = Pids0
- } = State0
-) ->
- {Keep, Remove} = maps:fold(
- fun(ClientId, Pid, {In, Out}) ->
- case node(Pid) =/= Node of
- true ->
- {In#{ClientId => Pid}, Out};
- false ->
- {In, Out#{ClientId => Pid}}
- end
- end,
- {#{}, #{}},
- Ids
- ),
- Effects = maps:fold(
- fun(ClientId, _Pid, Acc) ->
- Pid = maps:get(ClientId, Ids),
- [
- {demonitor, process, Pid},
- {mod_call, ?MODULE, notify_connection, [Pid, decommission_node]},
- {mod_call, rabbit_log, debug, [
- "MQTT will remove client ID '~ts' from known "
- "as its node has been decommissioned",
- [ClientId]
- ]}
- ] ++ Acc
- end,
- [],
- Remove
- ),
- State = State0#machine_state{
- client_ids = Keep,
- pids = maps:without(maps:keys(Remove), Pids0)
- },
+apply(Meta, {leave, Node}, #machine_state{client_ids = Ids,
+ pids = Pids0} = State0) ->
+ {Keep, Remove} = maps:fold(
+ fun (ClientId, Pid, {In, Out}) ->
+ case node(Pid) =/= Node of
+ true ->
+ {In#{ClientId => Pid}, Out};
+ false ->
+ {In, Out#{ClientId => Pid}}
+ end
+ end, {#{}, #{}}, Ids),
+ Effects = maps:fold(fun (ClientId, _Pid, Acc) ->
+ Pid = maps:get(ClientId, Ids),
+ [
+ {demonitor, process, Pid},
+ {mod_call, ?MODULE, notify_connection, [Pid, decommission_node]},
+ {mod_call, rabbit_log, debug,
+ ["MQTT will remove client ID '~ts' from known "
+ "as its node has been decommissioned", [ClientId]]}
+ ] ++ Acc
+ end, [], Remove),
+
+ State = State0#machine_state{client_ids = Keep,
+ pids = maps:without(maps:keys(Remove), Pids0)},
{State, ok, Effects ++ snapshot_effects(Meta, State)};
apply(_Meta, {machine_version, 0, 1}, {machine_state, Ids}) ->
Pids = maps:fold(
- fun(Id, Pid, Acc) ->
- maps:update_with(
- Pid,
- fun(CIds) -> [Id | CIds] end,
- [Id],
- Acc
- )
- end,
- #{},
- Ids
- ),
- {
- #machine_state{
- client_ids = Ids,
- pids = Pids
- },
- ok,
- []
- };
+ fun(Id, Pid, Acc) ->
+ maps:update_with(Pid,
+ fun(CIds) -> [Id | CIds] end,
+ [Id], Acc)
+ end, #{}, Ids),
+ {#machine_state{client_ids = Ids,
+ pids = Pids}, ok, []};
apply(_Meta, Unknown, State) ->
logger:error("MQTT Raft state machine v1 received unknown command ~tp", [Unknown]),
{State, {error, {unknown_command, Unknown}}, []}.
@@ -250,21 +182,17 @@ state_enter(_, _) ->
[].
-spec overview(state()) -> map().
-overview(#machine_state{
- client_ids = ClientIds,
- pids = Pids
-}) ->
- #{
- num_client_ids => maps:size(ClientIds),
- num_pids => maps:size(Pids)
- }.
+overview(#machine_state{client_ids = ClientIds,
+ pids = Pids}) ->
+ #{num_client_ids => maps:size(ClientIds),
+ num_pids => maps:size(Pids)}.
%% ==========================
%% Avoids blocking the Raft leader.
-spec notify_connection(pid(), duplicate_id | decommission_node) -> pid().
notify_connection(Pid, Reason) ->
- spawn(fun() -> gen_server2:cast(Pid, Reason) end).
+ spawn(fun() -> gen_server2:cast(Pid, Reason) end).
-spec snapshot_effects(map(), state()) -> ra_machine:effects().
snapshot_effects(#{index := RaftIdx}, State) ->
diff --git a/deps/rabbitmq_mqtt/src/mqtt_machine_v0.erl b/deps/rabbitmq_mqtt/src/mqtt_machine_v0.erl
index 702053b7b5..4b32ac88dd 100644
--- a/deps/rabbitmq_mqtt/src/mqtt_machine_v0.erl
+++ b/deps/rabbitmq_mqtt/src/mqtt_machine_v0.erl
@@ -9,12 +9,10 @@
-include("mqtt_machine_v0.hrl").
--export([
- init/1,
- apply/3,
- state_enter/2,
- notify_connection/2
-]).
+-export([init/1,
+ apply/3,
+ state_enter/2,
+ notify_connection/2]).
-type state() :: #machine_state{}.
@@ -23,10 +21,9 @@
-type reply() :: {ok, term()} | {error, term()}.
-type client_id() :: term().
--type command() ::
- {register, client_id(), pid()}
- | {unregister, client_id(), pid()}
- | list.
+-type command() :: {register, client_id(), pid()} |
+ {unregister, client_id(), pid()} |
+ list.
-spec init(config()) -> state().
init(_Conf) ->
@@ -38,60 +35,53 @@ apply(_Meta, {register, ClientId, Pid}, #machine_state{client_ids = Ids} = State
{Effects, Ids1} =
case maps:find(ClientId, Ids) of
{ok, OldPid} when Pid =/= OldPid ->
- Effects0 = [
- {demonitor, process, OldPid},
- {monitor, process, Pid},
- {mod_call, ?MODULE, notify_connection, [OldPid, duplicate_id]}
- ],
+ Effects0 = [{demonitor, process, OldPid},
+ {monitor, process, Pid},
+ {mod_call, ?MODULE, notify_connection, [OldPid, duplicate_id]}],
{Effects0, maps:remove(ClientId, Ids)};
_ ->
- Effects0 = [{monitor, process, Pid}],
- {Effects0, Ids}
+ Effects0 = [{monitor, process, Pid}],
+ {Effects0, Ids}
end,
State = State0#machine_state{client_ids = maps:put(ClientId, Pid, Ids1)},
{State, ok, Effects};
+
apply(Meta, {unregister, ClientId, Pid}, #machine_state{client_ids = Ids} = State0) ->
- State =
- case maps:find(ClientId, Ids) of
- {ok, Pid} -> State0#machine_state{client_ids = maps:remove(ClientId, Ids)};
- %% don't delete client id that might belong to a newer connection
- %% that kicked the one with Pid out
- {ok, _AnotherPid} -> State0;
- error -> State0
- end,
+ State = case maps:find(ClientId, Ids) of
+ {ok, Pid} -> State0#machine_state{client_ids = maps:remove(ClientId, Ids)};
+ %% don't delete client id that might belong to a newer connection
+ %% that kicked the one with Pid out
+ {ok, _AnotherPid} -> State0;
+ error -> State0
+ end,
Effects0 = [{demonitor, process, Pid}],
%% snapshot only when the map has changed
- Effects =
- case State of
- State0 -> Effects0;
- _ -> Effects0 ++ snapshot_effects(Meta, State)
- end,
+ Effects = case State of
+ State0 -> Effects0;
+ _ -> Effects0 ++ snapshot_effects(Meta, State)
+ end,
{State, ok, Effects};
+
apply(_Meta, {down, DownPid, noconnection}, State) ->
%% Monitor the node the pid is on (see {nodeup, Node} below)
%% so that we can detect when the node is re-connected and discover the
%% actual fate of the connection processes on it
Effect = {monitor, node, node(DownPid)},
{State, ok, Effect};
+
apply(Meta, {down, DownPid, _}, #machine_state{client_ids = Ids} = State0) ->
- Ids1 = maps:filter(
- fun
- (_ClientId, Pid) when Pid =:= DownPid ->
- false;
- (_, _) ->
- true
- end,
- Ids
- ),
+ Ids1 = maps:filter(fun (_ClientId, Pid) when Pid =:= DownPid ->
+ false;
+ (_, _) ->
+ true
+ end, Ids),
State = State0#machine_state{client_ids = Ids1},
Delta = maps:keys(Ids) -- maps:keys(Ids1),
- Effects = lists:map(
- fun(Id) ->
- [{mod_call, rabbit_log, debug, ["MQTT connection with client id '~ts' failed", [Id]]}]
- end,
- Delta
- ),
+ Effects = lists:map(fun(Id) ->
+ [{mod_call, rabbit_log, debug,
+ ["MQTT connection with client id '~ts' failed", [Id]]}] end, Delta),
{State, ok, Effects ++ snapshot_effects(Meta, State)};
+
apply(_Meta, {nodeup, Node}, State) ->
%% Work out if any pids that were disconnected are still
%% alive.
@@ -100,29 +90,25 @@ apply(_Meta, {nodeup, Node}, State) ->
{State, ok, Effects};
apply(_Meta, {nodedown, _Node}, State) ->
{State, ok};
+
apply(Meta, {leave, Node}, #machine_state{client_ids = Ids} = State0) ->
- Ids1 = maps:filter(fun(_ClientId, Pid) -> node(Pid) =/= Node end, Ids),
+ Ids1 = maps:filter(fun (_ClientId, Pid) -> node(Pid) =/= Node end, Ids),
Delta = maps:keys(Ids) -- maps:keys(Ids1),
- Effects = lists:foldl(
- fun(ClientId, Acc) ->
- Pid = maps:get(ClientId, Ids),
- [
- {demonitor, process, Pid},
- {mod_call, ?MODULE, notify_connection, [Pid, decommission_node]},
- {mod_call, rabbit_log, debug, [
- "MQTT will remove client ID '~ts' from known "
- "as its node has been decommissioned",
- [ClientId]
- ]}
- ] ++ Acc
- end,
- [],
- Delta
- ),
+ Effects = lists:foldl(fun (ClientId, Acc) ->
+ Pid = maps:get(ClientId, Ids),
+ [
+ {demonitor, process, Pid},
+ {mod_call, ?MODULE, notify_connection, [Pid, decommission_node]},
+ {mod_call, rabbit_log, debug,
+ ["MQTT will remove client ID '~ts' from known "
+ "as its node has been decommissioned", [ClientId]]}
+ ] ++ Acc
+ end, [], Delta),
State = State0#machine_state{client_ids = Ids1},
{State, ok, Effects ++ snapshot_effects(Meta, State)};
+
apply(_Meta, Unknown, State) ->
logger:error("MQTT Raft state machine received an unknown command ~tp", [Unknown]),
{State, {error, {unknown_command, Unknown}}, []}.
@@ -141,7 +127,7 @@ state_enter(_, _) ->
%% Avoids blocking the Raft leader.
-spec notify_connection(pid(), duplicate_id | decommission_node) -> pid().
notify_connection(Pid, Reason) ->
- spawn(fun() -> gen_server2:cast(Pid, Reason) end).
+ spawn(fun() -> gen_server2:cast(Pid, Reason) end).
-spec snapshot_effects(map(), state()) -> ra_machine:effects().
snapshot_effects(#{index := RaftIdx}, State) ->
diff --git a/deps/rabbitmq_mqtt/src/mqtt_node.erl b/deps/rabbitmq_mqtt/src/mqtt_node.erl
index 8a3c850b78..a6442fa85b 100644
--- a/deps/rabbitmq_mqtt/src/mqtt_node.erl
+++ b/deps/rabbitmq_mqtt/src/mqtt_node.erl
@@ -6,15 +6,8 @@
%%
-module(mqtt_node).
--export([
- start/0,
- node_id/0,
- server_id/0,
- all_node_ids/0,
- leave/1,
- trigger_election/0,
- delete/1
-]).
+-export([start/0, node_id/0, server_id/0, all_node_ids/0, leave/1, trigger_election/0,
+ delete/1]).
-define(ID_NAME, mqtt_node).
-define(START_TIMEOUT, 100_000).
@@ -32,11 +25,8 @@ server_id(Node) ->
{?ID_NAME, Node}.
all_node_ids() ->
- [
- server_id(N)
- || N <- rabbit_nodes:all(),
- can_participate_in_clientid_tracking(N)
- ].
+ [server_id(N) || N <- rabbit_nodes:all(),
+ can_participate_in_clientid_tracking(N)].
start() ->
%% 3s to 6s randomized
@@ -50,41 +40,34 @@ start(Delay, AttemptsLeft) ->
NodeId = server_id(),
Nodes = compatible_peer_servers(),
case ra_directory:uid_of(?RA_SYSTEM, ?ID_NAME) of
- undefined ->
- case Nodes of
- [] ->
- %% Since cluster members are not known ahead of time and initial boot can be happening in parallel,
- %% we wait and check a few times (up to a few seconds) to see if we can discover any peers to
- %% join before forming a cluster. This reduces the probability of N independent clusters being
- %% formed in the common scenario of N nodes booting in parallel e.g. because they were started
- %% at the same time by a deployment tool.
- %%
- %% This scenario does not guarantee single cluster formation but without knowing the list of members
- %% ahead of time, this is a best effort workaround. Multi-node consensus is apparently hard
- %% to achieve without having consensus around expected cluster members.
- rabbit_log:info(
- "MQTT: will wait for ~tp more ms for cluster members to join before triggering a Raft leader election",
- [Delay]
- ),
- timer:sleep(Delay),
- start(Delay, AttemptsLeft - 1);
- Peers ->
- %% Trigger an election.
- %% This is required when we start a node for the first time.
- %% Using default timeout because it supposed to reply fast.
- rabbit_log:info(
- "MQTT: discovered ~tp cluster peers that support client ID tracking", [
- length(Peers)
- ]
- ),
- ok = start_server(),
- _ = join_peers(NodeId, Peers),
- ra:trigger_election(NodeId, ?RA_OPERATION_TIMEOUT)
- end;
- _ ->
- _ = join_peers(NodeId, Nodes),
- ok = ra:restart_server(?RA_SYSTEM, NodeId),
- ra:trigger_election(NodeId, ?RA_OPERATION_TIMEOUT)
+ undefined ->
+ case Nodes of
+ [] ->
+ %% Since cluster members are not known ahead of time and initial boot can be happening in parallel,
+ %% we wait and check a few times (up to a few seconds) to see if we can discover any peers to
+ %% join before forming a cluster. This reduces the probability of N independent clusters being
+ %% formed in the common scenario of N nodes booting in parallel e.g. because they were started
+ %% at the same time by a deployment tool.
+ %%
+ %% This scenario does not guarantee single cluster formation but without knowing the list of members
+ %% ahead of time, this is a best effort workaround. Multi-node consensus is apparently hard
+ %% to achieve without having consensus around expected cluster members.
+ rabbit_log:info("MQTT: will wait for ~tp more ms for cluster members to join before triggering a Raft leader election", [Delay]),
+ timer:sleep(Delay),
+ start(Delay, AttemptsLeft - 1);
+ Peers ->
+ %% Trigger an election.
+ %% This is required when we start a node for the first time.
+ %% Using default timeout because it supposed to reply fast.
+ rabbit_log:info("MQTT: discovered ~tp cluster peers that support client ID tracking", [length(Peers)]),
+ ok = start_server(),
+ _ = join_peers(NodeId, Peers),
+ ra:trigger_election(NodeId, ?RA_OPERATION_TIMEOUT)
+ end;
+ _ ->
+ _ = join_peers(NodeId, Nodes),
+ ok = ra:restart_server(?RA_SYSTEM, NodeId),
+ ra:trigger_election(NodeId, ?RA_OPERATION_TIMEOUT)
end.
compatible_peer_servers() ->
@@ -95,15 +78,14 @@ start_server() ->
Nodes = compatible_peer_servers(),
UId = ra:new_uid(ra_lib:to_binary(?ID_NAME)),
Timeout = application:get_env(kernel, net_ticktime, 60) + 5,
- Conf = #{
- cluster_name => ?ID_NAME,
- id => NodeId,
- uid => UId,
- friendly_name => atom_to_list(?ID_NAME),
- initial_members => Nodes,
- log_init_args => #{uid => UId},
- tick_timeout => Timeout,
- machine => {module, mqtt_machine, #{}}
+ Conf = #{cluster_name => ?ID_NAME,
+ id => NodeId,
+ uid => UId,
+ friendly_name => atom_to_list(?ID_NAME),
+ initial_members => Nodes,
+ log_init_args => #{uid => UId},
+ tick_timeout => Timeout,
+ machine => {module, mqtt_machine, #{}}
},
ra:start_server(?RA_SYSTEM, Conf).
@@ -121,13 +103,11 @@ join_peers(NodeId, Nodes, RetriesLeft) ->
case ra:members(Nodes, ?START_TIMEOUT) of
{ok, Members, _} ->
case lists:member(NodeId, Members) of
- true -> ok;
+ true -> ok;
false -> ra:add_member(Members, NodeId)
end;
{timeout, _} ->
- rabbit_log:debug("MQTT: timed out contacting cluster peers, %s retries left", [
- RetriesLeft
- ]),
+ rabbit_log:debug("MQTT: timed out contacting cluster peers, %s retries left", [RetriesLeft]),
timer:sleep(?RETRY_INTERVAL),
join_peers(NodeId, Nodes, RetriesLeft - 1);
Err ->
@@ -148,12 +128,12 @@ leave(Node) ->
can_participate_in_clientid_tracking(Node) ->
case rpc:call(Node, mqtt_machine, module_info, []) of
{badrpc, _} -> false;
- _ -> true
+ _ -> true
end.
-spec delete(Args) -> Ret when
- Args :: rabbit_feature_flags:enable_callback_args(),
- Ret :: rabbit_feature_flags:enable_callback_ret().
+ Args :: rabbit_feature_flags:enable_callback_args(),
+ Ret :: rabbit_feature_flags:enable_callback_ret().
delete(_) ->
RaNodes = all_node_ids(),
Nodes = lists:map(fun({_, N}) -> N end, RaNodes),
@@ -171,13 +151,12 @@ delete(_) ->
{ok, _Leader} ->
rabbit_log:info("Successfully deleted Ra cluster ~s", [?ID_NAME]),
ok;
- {error, _} = Err ->
+ {error, _} = Err ->
rabbit_log:info("Failed to delete Ra cluster ~s: ~p", [?ID_NAME, Err]),
Err
- catch
- exit:{{shutdown, delete}, _Stacktrace} ->
- rabbit_log:info("Ra cluster ~s already being deleted", [?ID_NAME]),
- ok
+ catch exit:{{shutdown, delete}, _Stacktrace} ->
+ rabbit_log:info("Ra cluster ~s already being deleted", [?ID_NAME]),
+ ok
end
after
true = global:del_lock(LockId, Nodes),
diff --git a/deps/rabbitmq_mqtt/src/rabbit_mqtt.erl b/deps/rabbitmq_mqtt/src/rabbit_mqtt.erl
index 6e681ea3d2..5fb1861255 100644
--- a/deps/rabbitmq_mqtt/src/rabbit_mqtt.erl
+++ b/deps/rabbitmq_mqtt/src/rabbit_mqtt.erl
@@ -13,13 +13,11 @@
-include_lib("stdlib/include/assert.hrl").
-export([start/2, stop/1]).
--export([
- emit_connection_info_all/4,
- emit_connection_info_local/3,
- close_local_client_connections/1,
- %% Exported for tests, but could also be used for debugging.
- local_connection_pids/0
-]).
+-export([emit_connection_info_all/4,
+ emit_connection_info_local/3,
+ close_local_client_connections/1,
+ %% Exported for tests, but could also be used for debugging.
+ local_connection_pids/0]).
start(normal, []) ->
init_global_counters(),
@@ -33,11 +31,10 @@ start(normal, []) ->
ok
end,
Result = rabbit_mqtt_sup:start_link({Listeners, SslListeners}, []),
- EMPid =
- case rabbit_event:start_link() of
- {ok, Pid} -> Pid;
- {error, {already_started, Pid}} -> Pid
- end,
+ EMPid = case rabbit_event:start_link() of
+ {ok, Pid} -> Pid;
+ {error, {already_started, Pid}} -> Pid
+ end,
gen_event:add_handler(EMPid, rabbit_mqtt_internal_event_handler, []),
Result.
@@ -55,15 +52,9 @@ emit_connection_info_all(Nodes, Items, Ref, AggregatorPid) ->
%% remaining nodes, we send back 'finished' so that the CLI does not time out.
[AggregatorPid ! {Ref, finished} || _ <- lists:seq(1, length(Nodes) - 1)];
false ->
- Pids = [
- spawn_link(
- Node,
- ?MODULE,
- emit_connection_info_local,
- [Items, Ref, AggregatorPid]
- )
- || Node <- Nodes
- ],
+ Pids = [spawn_link(Node, ?MODULE, emit_connection_info_local,
+ [Items, Ref, AggregatorPid])
+ || Node <- Nodes],
rabbit_control_misc:await_emitters_termination(Pids)
end.
@@ -74,23 +65,17 @@ emit_connection_info_local(Items, Ref, AggregatorPid) ->
emit_connection_info(Items, Ref, AggregatorPid, Pids) ->
rabbit_control_misc:emitting_map_with_exit_handler(
- AggregatorPid,
- Ref,
- fun(Pid) ->
- rabbit_mqtt_reader:info(Pid, Items)
- end,
- Pids
- ).
+ AggregatorPid, Ref,
+ fun(Pid) ->
+ rabbit_mqtt_reader:info(Pid, Items)
+ end, Pids).
-spec close_local_client_connections(string() | binary()) -> {'ok', non_neg_integer()}.
close_local_client_connections(Reason) ->
Pids = local_connection_pids(),
- lists:foreach(
- fun(Pid) ->
- rabbit_mqtt_reader:close_connection(Pid, Reason)
- end,
- Pids
- ),
+ lists:foreach(fun(Pid) ->
+ rabbit_mqtt_reader:close_connection(Pid, Reason)
+ end, Pids),
{ok, length(Pids)}.
-spec local_connection_pids() -> [pid()].
@@ -101,12 +86,9 @@ local_connection_pids() ->
lists:filter(fun(Pid) -> node(Pid) =:= node() end, AllPids);
false ->
PgScope = persistent_term:get(?PG_SCOPE),
- lists:flatmap(
- fun(Group) ->
- pg:get_local_members(PgScope, Group)
- end,
- pg:which_groups(PgScope)
- )
+ lists:flatmap(fun(Group) ->
+ pg:get_local_members(PgScope, Group)
+ end, pg:which_groups(PgScope))
end.
init_global_counters() ->
diff --git a/deps/rabbitmq_mqtt/src/rabbit_mqtt_collector.erl b/deps/rabbitmq_mqtt/src/rabbit_mqtt_collector.erl
index 438b6cf9f1..5b5050d64e 100644
--- a/deps/rabbitmq_mqtt/src/rabbit_mqtt_collector.erl
+++ b/deps/rabbitmq_mqtt/src/rabbit_mqtt_collector.erl
@@ -9,13 +9,8 @@
-include("mqtt_machine.hrl").
--export([
- register/2, register/3,
- unregister/2,
- list/0,
- list_pids/0,
- leave/1
-]).
+-export([register/2, register/3, unregister/2,
+ list/0, list_pids/0, leave/1]).
%%----------------------------------------------------------------------------
-spec register(term(), pid()) -> {ok, reference()} | {error, term()}.
@@ -26,7 +21,7 @@ register(ClientId, Pid) ->
case ra:members(NodeId) of
{ok, _, Leader} ->
register(Leader, ClientId, Pid);
- _ = Error ->
+ _ = Error ->
Error
end;
Leader ->
@@ -65,31 +60,25 @@ list(QF) ->
undefined ->
NodeIds = mqtt_node:all_node_ids(),
case ra:leader_query(NodeIds, QF) of
- {ok, {_, Result}, _} ->
- Result;
- {timeout, _} ->
- rabbit_log:debug(
- "~ts:list/1 leader query timed out",
- [?MODULE]
- ),
+ {ok, {_, Result}, _} -> Result;
+ {timeout, _} ->
+ rabbit_log:debug("~ts:list/1 leader query timed out",
+ [?MODULE]),
[]
end;
Leader ->
case ra:leader_query(Leader, QF) of
- {ok, {_, Result}, _} ->
- Result;
+ {ok, {_, Result}, _} -> Result;
{error, _} ->
[];
- {timeout, _} ->
- rabbit_log:debug(
- "~ts:list/1 leader query timed out",
- [?MODULE]
- ),
+ {timeout, _} ->
+ rabbit_log:debug("~ts:list/1 leader query timed out",
+ [?MODULE]),
[]
end
end.
--spec leave(binary()) -> ok | timeout | nodedown.
+-spec leave(binary()) -> ok | timeout | nodedown.
leave(NodeBin) ->
Node = binary_to_atom(NodeBin, utf8),
ServerId = mqtt_node:server_id(),
diff --git a/deps/rabbitmq_mqtt/src/rabbit_mqtt_confirms.erl b/deps/rabbitmq_mqtt/src/rabbit_mqtt_confirms.erl
index df56b14861..a31c94bd16 100644
--- a/deps/rabbitmq_mqtt/src/rabbit_mqtt_confirms.erl
+++ b/deps/rabbitmq_mqtt/src/rabbit_mqtt_confirms.erl
@@ -10,15 +10,13 @@
-include("rabbit_mqtt_packet.hrl").
-compile({no_auto_import, [size/1]}).
--export([
- init/0,
- insert/3,
- confirm/3,
- reject/2,
- remove_queue/2,
- size/1,
- contains/2
-]).
+-export([init/0,
+ insert/3,
+ confirm/3,
+ reject/2,
+ remove_queue/2,
+ size/1,
+ contains/2]).
%% As done in OTP's sets module:
%% Empty list is cheaper to serialize than atom.
@@ -41,32 +39,26 @@ contains(PktId, State) ->
maps:is_key(PktId, State).
-spec insert(packet_id(), [queue_name()], state()) -> state().
-insert(PktId, QNames, State) when
- is_integer(PktId) andalso
- PktId > 0 andalso
- not is_map_key(PktId, State)
-->
+insert(PktId, QNames, State)
+ when is_integer(PktId) andalso
+ PktId > 0 andalso
+ not is_map_key(PktId, State) ->
QMap = maps:from_keys(QNames, ?VALUE),
maps:put(PktId, QMap, State).
-spec confirm([packet_id()], queue_name(), state()) ->
{[packet_id()], state()}.
confirm(PktIds, QName, State0) ->
- {L0, State} = lists:foldl(
- fun(PktId, Acc) ->
- confirm_one(PktId, QName, Acc)
- end,
- {[], State0},
- PktIds
- ),
+ {L0, State} = lists:foldl(fun(PktId, Acc) ->
+ confirm_one(PktId, QName, Acc)
+ end, {[], State0}, PktIds),
L = lists:reverse(L0),
{L, State}.
-spec reject(packet_id(), state()) ->
{ok, state()} | {error, not_found}.
-reject(PktId, State0) when
- is_integer(PktId)
-->
+reject(PktId, State0)
+ when is_integer(PktId) ->
case maps:take(PktId, State0) of
{_, State} ->
{ok, State};
@@ -79,31 +71,24 @@ reject(PktId, State0) when
{[packet_id()], state()}.
remove_queue(QName, State) ->
PktIds = maps:fold(
- fun
- (PktId, QMap, PktIds) when
- is_map_key(QName, QMap)
- ->
- [PktId | PktIds];
- (_, _, PktIds) ->
- PktIds
- end,
- [],
- State
- ),
+ fun(PktId, QMap, PktIds)
+ when is_map_key(QName, QMap) ->
+ [PktId | PktIds];
+ (_, _, PktIds) ->
+ PktIds
+ end, [], State),
confirm(lists:sort(PktIds), QName, State).
%% INTERNAL
-confirm_one(PktId, QName, {PktIds, State0}) when
- is_integer(PktId)
-->
+confirm_one(PktId, QName, {PktIds, State0})
+ when is_integer(PktId) ->
case maps:take(PktId, State0) of
- {QMap0, State1} when
- is_map_key(QName, QMap0) andalso
- map_size(QMap0) =:= 1
- ->
+ {QMap0, State1}
+ when is_map_key(QName, QMap0)
+ andalso map_size(QMap0) =:= 1 ->
%% last queue confirm
- {[PktId | PktIds], State1};
+ {[PktId| PktIds], State1};
{QMap0, State1} ->
QMap = maps:remove(QName, QMap0),
State = maps:put(PktId, QMap, State1),
diff --git a/deps/rabbitmq_mqtt/src/rabbit_mqtt_ff.erl b/deps/rabbitmq_mqtt/src/rabbit_mqtt_ff.erl
index e132128527..2432cc2ac5 100644
--- a/deps/rabbitmq_mqtt/src/rabbit_mqtt_ff.erl
+++ b/deps/rabbitmq_mqtt/src/rabbit_mqtt_ff.erl
@@ -12,19 +12,17 @@
-export([track_client_id_in_ra/0]).
-rabbit_feature_flag(
- {?QUEUE_TYPE_QOS_0, #{
- desc => "Support pseudo queue type for MQTT QoS 0 subscribers omitting a queue process",
- stability => stable
- }}
-).
+ {?QUEUE_TYPE_QOS_0,
+ #{desc => "Support pseudo queue type for MQTT QoS 0 subscribers omitting a queue process",
+ stability => stable
+ }}).
-rabbit_feature_flag(
- {delete_ra_cluster_mqtt_node, #{
- desc => "Delete Ra cluster 'mqtt_node' since MQTT client IDs are tracked locally",
- stability => stable,
- callbacks => #{enable => {mqtt_node, delete}}
- }}
-).
+ {delete_ra_cluster_mqtt_node,
+ #{desc => "Delete Ra cluster 'mqtt_node' since MQTT client IDs are tracked locally",
+ stability => stable,
+ callbacks => #{enable => {mqtt_node, delete}}
+ }}).
-spec track_client_id_in_ra() -> boolean().
track_client_id_in_ra() ->
diff --git a/deps/rabbitmq_mqtt/src/rabbit_mqtt_internal_event_handler.erl b/deps/rabbitmq_mqtt/src/rabbit_mqtt_internal_event_handler.erl
index c01f4cc5b3..711c065acc 100644
--- a/deps/rabbitmq_mqtt/src/rabbit_mqtt_internal_event_handler.erl
+++ b/deps/rabbitmq_mqtt/src/rabbit_mqtt_internal_event_handler.erl
@@ -28,9 +28,7 @@ handle_event({event, vhost_deleted, Info, _, _}, ?STATE) ->
{ok, ?STATE};
handle_event({event, maintenance_connections_closed, _Info, _, _}, ?STATE) ->
%% we should close our connections
- {ok, NConnections} = rabbit_mqtt:close_local_client_connections(
- "node is being put into maintenance mode"
- ),
+ {ok, NConnections} = rabbit_mqtt:close_local_client_connections("node is being put into maintenance mode"),
rabbit_log:warning("Closed ~b local MQTT client connections", [NConnections]),
{ok, ?STATE};
handle_event(_Event, ?STATE) ->
diff --git a/deps/rabbitmq_mqtt/src/rabbit_mqtt_keepalive.erl b/deps/rabbitmq_mqtt/src/rabbit_mqtt_keepalive.erl
index cadfcffdad..6b7b94b54c 100644
--- a/deps/rabbitmq_mqtt/src/rabbit_mqtt_keepalive.erl
+++ b/deps/rabbitmq_mqtt/src/rabbit_mqtt_keepalive.erl
@@ -1,26 +1,23 @@
-module(rabbit_mqtt_keepalive).
--export([
- init/0,
- start/2,
- handle/2,
- start_timer/1,
- cancel_timer/1,
- interval_secs/1
-]).
+-export([init/0,
+ start/2,
+ handle/2,
+ start_timer/1,
+ cancel_timer/1,
+ interval_secs/1]).
-export_type([state/0]).
-record(state, {
- %% Keep Alive value as sent in the CONNECT packet.
- interval_secs :: pos_integer(),
- timer :: reference(),
- socket :: inet:socket(),
- recv_oct :: non_neg_integer(),
- received :: boolean()
-}).
+ %% Keep Alive value as sent in the CONNECT packet.
+ interval_secs :: pos_integer(),
+ timer :: reference(),
+ socket :: inet:socket(),
+ recv_oct :: non_neg_integer(),
+ received :: boolean()}).
--opaque state() :: disabled | #state{}.
+-opaque(state() :: disabled | #state{}).
-spec init() -> state().
init() ->
@@ -29,9 +26,8 @@ init() ->
-spec start(IntervalSeconds :: non_neg_integer(), inet:socket()) -> ok.
start(0, _Sock) ->
ok;
-start(Seconds, Sock) when
- is_integer(Seconds) andalso Seconds > 0
-->
+start(Seconds, Sock)
+ when is_integer(Seconds) andalso Seconds > 0 ->
self() ! {keepalive, {init, Seconds, Sock}},
ok.
@@ -40,28 +36,20 @@ start(Seconds, Sock) when
handle({init, IntervalSecs, Sock}, _State) ->
case rabbit_net:getstat(Sock, [recv_oct]) of
{ok, [{recv_oct, RecvOct}]} ->
- {ok, #state{
- interval_secs = IntervalSecs,
- timer = start_timer0(IntervalSecs),
- socket = Sock,
- recv_oct = RecvOct,
- received = true
- }};
+ {ok, #state{interval_secs = IntervalSecs,
+ timer = start_timer0(IntervalSecs),
+ socket = Sock,
+ recv_oct = RecvOct,
+ received = true}};
{error, _} = Err ->
Err
end;
-handle(
- check,
- State = #state{
- socket = Sock,
- recv_oct = SameRecvOct,
- received = ReceivedPreviously
- }
-) ->
+handle(check, State = #state{socket = Sock,
+ recv_oct = SameRecvOct,
+ received = ReceivedPreviously}) ->
case rabbit_net:getstat(Sock, [recv_oct]) of
- {ok, [{recv_oct, SameRecvOct}]} when
- ReceivedPreviously
- ->
+ {ok, [{recv_oct, SameRecvOct}]}
+ when ReceivedPreviously ->
%% Did not receive from socket for the 1st time.
{ok, start_timer(State#state{received = false})};
{ok, [{recv_oct, SameRecvOct}]} ->
@@ -69,11 +57,8 @@ handle(
{error, timeout};
{ok, [{recv_oct, NewRecvOct}]} ->
%% Received from socket.
- {ok,
- start_timer(State#state{
- recv_oct = NewRecvOct,
- received = true
- })};
+ {ok, start_timer(State#state{recv_oct = NewRecvOct,
+ received = true})};
{error, _} = Err ->
Err
end.
@@ -89,13 +74,10 @@ start_timer0(KeepAliveSeconds) ->
erlang:send_after(timer_ms(KeepAliveSeconds), self(), {keepalive, check}).
-spec cancel_timer(state()) -> state().
-cancel_timer(#state{timer = Ref} = State) when
- is_reference(Ref)
-->
- ok = erlang:cancel_timer(Ref, [
- {async, true},
- {info, false}
- ]),
+cancel_timer(#state{timer = Ref} = State)
+ when is_reference(Ref) ->
+ ok = erlang:cancel_timer(Ref, [{async, true},
+ {info, false}]),
State;
cancel_timer(disabled) ->
disabled.
diff --git a/deps/rabbitmq_mqtt/src/rabbit_mqtt_packet.erl b/deps/rabbitmq_mqtt/src/rabbit_mqtt_packet.erl
index bcd31d3529..ededed8c5b 100644
--- a/deps/rabbitmq_mqtt/src/rabbit_mqtt_packet.erl
+++ b/deps/rabbitmq_mqtt/src/rabbit_mqtt_packet.erl
@@ -24,148 +24,119 @@
initial_state() -> none.
-spec parse(binary(), state()) ->
- {more, state()}
- | {ok, mqtt_packet(), binary()}
- | {error, any()}.
+ {more, state()} |
+ {ok, mqtt_packet(), binary()} |
+ {error, any()}.
parse(<<>>, none) ->
{more, fun(Bin) -> parse(Bin, none) end};
parse(<<MessageType:4, Dup:1, QoS:2, Retain:1, Rest/binary>>, none) ->
- parse_remaining_len(Rest, #mqtt_packet_fixed{
- type = MessageType,
- dup = bool(Dup),
- qos = QoS,
- retain = bool(Retain)
- });
-parse(Bin, Cont) ->
- Cont(Bin).
+ parse_remaining_len(Rest, #mqtt_packet_fixed{ type = MessageType,
+ dup = bool(Dup),
+ qos = QoS,
+ retain = bool(Retain) });
+parse(Bin, Cont) -> Cont(Bin).
parse_remaining_len(<<>>, Fixed) ->
{more, fun(Bin) -> parse_remaining_len(Bin, Fixed) end};
parse_remaining_len(Rest, Fixed) ->
parse_remaining_len(Rest, Fixed, 1, 0).
-parse_remaining_len(_Bin, _Fixed, _Multiplier, Length) when
- Length > ?MAX_LEN
-->
+parse_remaining_len(_Bin, _Fixed, _Multiplier, Length)
+ when Length > ?MAX_LEN ->
{error, invalid_mqtt_packet_len};
parse_remaining_len(<<>>, Fixed, Multiplier, Length) ->
{more, fun(Bin) -> parse_remaining_len(Bin, Fixed, Multiplier, Length) end};
parse_remaining_len(<<1:1, Len:7, Rest/binary>>, Fixed, Multiplier, Value) ->
parse_remaining_len(Rest, Fixed, Multiplier * ?HIGHBIT, Value + Len * Multiplier);
-parse_remaining_len(<<0:1, Len:7, Rest/binary>>, Fixed, Multiplier, Value) ->
+parse_remaining_len(<<0:1, Len:7, Rest/binary>>, Fixed, Multiplier, Value) ->
parse_packet(Rest, Fixed, Value + Len * Multiplier).
-parse_packet(
- Bin,
- #mqtt_packet_fixed{
- type = Type,
- qos = Qos
- } = Fixed,
- Length
-) when
- Length =< ?MAX_LEN
-->
+parse_packet(Bin, #mqtt_packet_fixed{ type = Type,
+ qos = Qos } = Fixed, Length)
+ when Length =< ?MAX_LEN ->
case {Type, Bin} of
{?CONNECT, <<PacketBin:Length/binary, Rest/binary>>} ->
{ProtoName, Rest1} = parse_utf(PacketBin),
- <<ProtoVersion:8, Rest2/binary>> = Rest1,
- <<UsernameFlag:1, PasswordFlag:1, WillRetain:1, WillQos:2, WillFlag:1, CleanSession:1,
- _Reserved:1, KeepAlive:16/big, Rest3/binary>> = Rest2,
- {ClientId, Rest4} = parse_utf(Rest3),
+ <<ProtoVersion : 8, Rest2/binary>> = Rest1,
+ <<UsernameFlag : 1,
+ PasswordFlag : 1,
+ WillRetain : 1,
+ WillQos : 2,
+ WillFlag : 1,
+ CleanSession : 1,
+ _Reserved : 1,
+ KeepAlive : 16/big,
+ Rest3/binary>> = Rest2,
+ {ClientId, Rest4} = parse_utf(Rest3),
{WillTopic, Rest5} = parse_utf(Rest4, WillFlag),
- {WillMsg, Rest6} = parse_msg(Rest5, WillFlag),
- {UserName, Rest7} = parse_utf(Rest6, UsernameFlag),
- {PasssWord, <<>>} = parse_utf(Rest7, PasswordFlag),
+ {WillMsg, Rest6} = parse_msg(Rest5, WillFlag),
+ {UserName, Rest7} = parse_utf(Rest6, UsernameFlag),
+ {PasssWord, <<>>} = parse_utf(Rest7, PasswordFlag),
case protocol_name_approved(ProtoVersion, ProtoName) of
true ->
- wrap(
- Fixed,
- #mqtt_packet_connect{
- proto_ver = ProtoVersion,
- will_retain = bool(WillRetain),
- will_qos = WillQos,
- will_flag = bool(WillFlag),
- clean_sess = bool(CleanSession),
- keep_alive = KeepAlive,
- client_id = ClientId,
- will_topic = WillTopic,
- will_msg = WillMsg,
- username = UserName,
- password = PasssWord
- },
- Rest
- );
- false ->
+ wrap(Fixed,
+ #mqtt_packet_connect{
+ proto_ver = ProtoVersion,
+ will_retain = bool(WillRetain),
+ will_qos = WillQos,
+ will_flag = bool(WillFlag),
+ clean_sess = bool(CleanSession),
+ keep_alive = KeepAlive,
+ client_id = ClientId,
+ will_topic = WillTopic,
+ will_msg = WillMsg,
+ username = UserName,
+ password = PasssWord}, Rest);
+ false ->
{error, protocol_header_corrupt}
end;
{?PUBLISH, <<PacketBin:Length/binary, Rest/binary>>} ->
{TopicName, Rest1} = parse_utf(PacketBin),
- {PacketId, Payload} =
- case Qos of
- 0 ->
- {undefined, Rest1};
- _ ->
- <<M:16/big, R/binary>> = Rest1,
- {M, R}
- end,
- wrap(
- Fixed,
- #mqtt_packet_publish{
- topic_name = TopicName,
- packet_id = PacketId
- },
- Payload,
- Rest
- );
+ {PacketId, Payload} = case Qos of
+ 0 -> {undefined, Rest1};
+ _ -> <<M:16/big, R/binary>> = Rest1,
+ {M, R}
+ end,
+ wrap(Fixed, #mqtt_packet_publish { topic_name = TopicName,
+ packet_id = PacketId },
+ Payload, Rest);
{?PUBACK, <<PacketBin:Length/binary, Rest/binary>>} ->
<<PacketId:16/big>> = PacketBin,
- wrap(Fixed, #mqtt_packet_publish{packet_id = PacketId}, Rest);
- {Subs, <<PacketBin:Length/binary, Rest/binary>>} when
- Subs =:= ?SUBSCRIBE orelse Subs =:= ?UNSUBSCRIBE
- ->
+ wrap(Fixed, #mqtt_packet_publish { packet_id = PacketId }, Rest);
+ {Subs, <<PacketBin:Length/binary, Rest/binary>>}
+ when Subs =:= ?SUBSCRIBE orelse Subs =:= ?UNSUBSCRIBE ->
1 = Qos,
<<PacketId:16/big, Rest1/binary>> = PacketBin,
Topics = parse_topics(Subs, Rest1, []),
- wrap(
- Fixed,
- #mqtt_packet_subscribe{
- packet_id = PacketId,
- topic_table = Topics
- },
- Rest
- );
- {Minimal, Rest} when
- Minimal =:= ?DISCONNECT orelse Minimal =:= ?PINGREQ
- ->
+ wrap(Fixed, #mqtt_packet_subscribe { packet_id = PacketId,
+ topic_table = Topics }, Rest);
+ {Minimal, Rest}
+ when Minimal =:= ?DISCONNECT orelse Minimal =:= ?PINGREQ ->
Length = 0,
wrap(Fixed, Rest);
- {_, TooShortBin} when
- byte_size(TooShortBin) < Length
- ->
+ {_, TooShortBin}
+ when byte_size(TooShortBin) < Length ->
{more, fun(BinMore) ->
- parse_packet(
- <<TooShortBin/binary, BinMore/binary>>,
- Fixed,
- Length
- )
- end}
+ parse_packet(<<TooShortBin/binary, BinMore/binary>>,
+ Fixed, Length)
+ end}
end.
parse_topics(_, <<>>, Topics) ->
Topics;
parse_topics(?SUBSCRIBE = Sub, Bin, Topics) ->
{Name, <<_:6, QoS:2, Rest/binary>>} = parse_utf(Bin),
- parse_topics(Sub, Rest, [#mqtt_topic{name = Name, qos = QoS} | Topics]);
+ parse_topics(Sub, Rest, [#mqtt_topic { name = Name, qos = QoS } | Topics]);
parse_topics(?UNSUBSCRIBE = Sub, Bin, Topics) ->
{Name, <<Rest/binary>>} = parse_utf(Bin),
- parse_topics(Sub, Rest, [#mqtt_topic{name = Name} | Topics]).
+ parse_topics(Sub, Rest, [#mqtt_topic { name = Name } | Topics]).
wrap(Fixed, Variable, Payload, Rest) ->
- {ok, #mqtt_packet{variable = Variable, fixed = Fixed, payload = Payload}, Rest}.
+ {ok, #mqtt_packet { variable = Variable, fixed = Fixed, payload = Payload }, Rest}.
wrap(Fixed, Variable, Rest) ->
- {ok, #mqtt_packet{variable = Variable, fixed = Fixed}, Rest}.
+ {ok, #mqtt_packet { variable = Variable, fixed = Fixed }, Rest}.
wrap(Fixed, Rest) ->
- {ok, #mqtt_packet{fixed = Fixed}, Rest}.
+ {ok, #mqtt_packet { fixed = Fixed }, Rest}.
parse_utf(Bin, 0) ->
{undefined, Bin};
@@ -187,109 +158,72 @@ bool(1) -> true.
-spec serialise(#mqtt_packet{}, ?MQTT_PROTO_V3 | ?MQTT_PROTO_V4) ->
iodata().
-serialise(
- #mqtt_packet{
- fixed = Fixed,
- variable = Variable,
- payload = Payload
- },
- Vsn
-) ->
+serialise(#mqtt_packet{fixed = Fixed,
+ variable = Variable,
+ payload = Payload}, Vsn) ->
serialise_variable(Fixed, Variable, serialise_payload(Payload), Vsn).
serialise_payload(undefined) ->
<<>>;
-serialise_payload(P) when
- is_binary(P) orelse is_list(P)
-->
+serialise_payload(P)
+ when is_binary(P) orelse is_list(P) ->
P.
-serialise_variable(
- #mqtt_packet_fixed{type = ?CONNACK} = Fixed,
- #mqtt_packet_connack{
- session_present = SessionPresent,
- return_code = ReturnCode
- },
- <<>> = PayloadBin,
- _Vsn
-) ->
+serialise_variable(#mqtt_packet_fixed { type = ?CONNACK } = Fixed,
+ #mqtt_packet_connack { session_present = SessionPresent,
+ return_code = ReturnCode },
+ <<>> = PayloadBin, _Vsn) ->
VariableBin = <<?RESERVED:7, (opt(SessionPresent)):1, ReturnCode:8>>,
serialise_fixed(Fixed, VariableBin, PayloadBin);
-serialise_variable(
- #mqtt_packet_fixed{type = SubAck} = Fixed,
- #mqtt_packet_suback{
- packet_id = PacketId,
- qos_table = Qos
- },
- <<>> = _PayloadBin,
- Vsn
-) when
- SubAck =:= ?SUBACK orelse SubAck =:= ?UNSUBACK
-->
+
+serialise_variable(#mqtt_packet_fixed { type = SubAck } = Fixed,
+ #mqtt_packet_suback { packet_id = PacketId,
+ qos_table = Qos },
+ <<>> = _PayloadBin, Vsn)
+ when SubAck =:= ?SUBACK orelse SubAck =:= ?UNSUBACK ->
VariableBin = <<PacketId:16/big>>,
- QosBin =
- case Vsn of
- ?MQTT_PROTO_V3 ->
- <<<<?RESERVED:6, Q:2>> || Q <- Qos>>;
- ?MQTT_PROTO_V4 ->
- %% Allow error code (0x80) in the MQTT SUBACK message.
- <<<<Q:8>> || Q <- Qos>>
- end,
+ QosBin = case Vsn of
+ ?MQTT_PROTO_V3 ->
+ << <<?RESERVED:6, Q:2>> || Q <- Qos >>;
+ ?MQTT_PROTO_V4 ->
+ %% Allow error code (0x80) in the MQTT SUBACK message.
+ << <<Q:8>> || Q <- Qos >>
+ end,
serialise_fixed(Fixed, VariableBin, QosBin);
-serialise_variable(
- #mqtt_packet_fixed{
- type = ?PUBLISH,
- qos = Qos
- } = Fixed,
- #mqtt_packet_publish{
- topic_name = TopicName,
- packet_id = PacketId
- },
- Payload,
- _Vsn
-) ->
+
+serialise_variable(#mqtt_packet_fixed { type = ?PUBLISH,
+ qos = Qos } = Fixed,
+ #mqtt_packet_publish { topic_name = TopicName,
+ packet_id = PacketId },
+ Payload, _Vsn) ->
TopicBin = serialise_utf(TopicName),
- PacketIdBin =
- case Qos of
- 0 -> <<>>;
- 1 -> <<PacketId:16/big>>
- end,
+ PacketIdBin = case Qos of
+ 0 -> <<>>;
+ 1 -> <<PacketId:16/big>>
+ end,
serialise_fixed(Fixed, <<TopicBin/binary, PacketIdBin/binary>>, Payload);
-serialise_variable(
- #mqtt_packet_fixed{type = ?PUBACK} = Fixed,
- #mqtt_packet_publish{packet_id = PacketId},
- PayloadBin,
- _Vsn
-) ->
+
+serialise_variable(#mqtt_packet_fixed { type = ?PUBACK } = Fixed,
+ #mqtt_packet_publish { packet_id = PacketId },
+ PayloadBin, _Vsn) ->
PacketIdBin = <<PacketId:16/big>>,
serialise_fixed(Fixed, PacketIdBin, PayloadBin);
-serialise_variable(
- #mqtt_packet_fixed{} = Fixed,
- undefined,
- <<>> = _PayloadBin,
- _Vsn
-) ->
+
+serialise_variable(#mqtt_packet_fixed {} = Fixed,
+ undefined,
+ <<>> = _PayloadBin, _Vsn) ->
serialise_fixed(Fixed, <<>>, <<>>).
-serialise_fixed(
- #mqtt_packet_fixed{
- type = Type,
- dup = Dup,
- qos = Qos,
- retain = Retain
- },
- VariableBin,
- Payload
-) when
- is_integer(Type) andalso ?CONNECT =< Type andalso Type =< ?DISCONNECT
-->
+serialise_fixed(#mqtt_packet_fixed{ type = Type,
+ dup = Dup,
+ qos = Qos,
+ retain = Retain }, VariableBin, Payload)
+ when is_integer(Type) andalso ?CONNECT =< Type andalso Type =< ?DISCONNECT ->
Len = size(VariableBin) + iolist_size(Payload),
true = (Len =< ?MAX_LEN),
LenBin = serialise_len(Len),
- [
- <<Type:4, (opt(Dup)):1, (opt(Qos)):2, (opt(Retain)):1, LenBin/binary, VariableBin/binary>>,
- Payload
- ].
+ [<<Type:4, (opt(Dup)):1, (opt(Qos)):2, (opt(Retain)):1,
+ LenBin/binary, VariableBin/binary>>, Payload].
serialise_utf(String) ->
StringBin = unicode:characters_to_binary(String),
@@ -302,9 +236,9 @@ serialise_len(N) when N =< ?LOWBITS ->
serialise_len(N) ->
<<1:1, (N rem ?HIGHBIT):7, (serialise_len(N div ?HIGHBIT))/binary>>.
-opt(undefined) -> ?RESERVED;
-opt(false) -> 0;
-opt(true) -> 1;
+opt(undefined) -> ?RESERVED;
+opt(false) -> 0;
+opt(true) -> 1;
opt(X) when is_integer(X) -> X.
protocol_name_approved(Ver, Name) ->
diff --git a/deps/rabbitmq_mqtt/src/rabbit_mqtt_processor.erl b/deps/rabbitmq_mqtt/src/rabbit_mqtt_processor.erl
index 31c149cf5f..58bccaa2f5 100644
--- a/deps/rabbitmq_mqtt/src/rabbit_mqtt_processor.erl
+++ b/deps/rabbitmq_mqtt/src/rabbit_mqtt_processor.erl
@@ -8,31 +8,20 @@
%% This module contains code that is common to MQTT and Web MQTT connections.
-module(rabbit_mqtt_processor).
--export([
- info/2,
- initial_state/2, initial_state/4,
- process_packet/2,
- serialise/2,
- terminate/4,
- handle_pre_hibernate/0,
- handle_ra_event/2,
- handle_down/2,
- handle_queue_event/2,
- proto_version_tuple/1,
- throttle/3,
- format_status/1,
- update_trace/2
-]).
+-export([info/2, initial_state/2, initial_state/4,
+ process_packet/2, serialise/2,
+ terminate/4, handle_pre_hibernate/0,
+ handle_ra_event/2, handle_down/2, handle_queue_event/2,
+ proto_version_tuple/1, throttle/3, format_status/1,
+ update_trace/2]).
%% for testing purposes
-export([get_vhost_username/1, get_vhost/3, get_vhost_from_user_mapping/2]).
-export_type([state/0]).
--import(rabbit_mqtt_util, [
- mqtt_to_amqp/1,
- amqp_to_mqtt/1
-]).
+-import(rabbit_mqtt_util, [mqtt_to_amqp/1,
+ amqp_to_mqtt/1]).
-include_lib("kernel/include/logger.hrl").
-include_lib("rabbit_common/include/rabbit.hrl").
@@ -44,57 +33,57 @@
-define(MAX_PERMISSION_CACHE_SIZE, 12).
-define(CONSUMER_TAG, <<"mqtt">>).
--record(auth_state, {
- username :: rabbit_types:username(),
- user :: #user{},
- vhost :: rabbit_types:vhost(),
- authz_ctx :: #{binary() := binary()}
-}).
-
--record(cfg, {
- socket :: rabbit_net:socket(),
- proto_ver :: option(mqtt310 | mqtt311),
- clean_sess :: option(boolean()),
- will_msg :: option(mqtt_msg()),
- exchange :: option(rabbit_exchange:name()),
- %% Set if client has at least one subscription with QoS 1.
- queue_qos1 :: option(rabbit_amqqueue:name()),
- %% Did the client ever sent us a PUBLISH packet?
- published = false :: boolean(),
- ssl_login_name :: none | binary(),
- retainer_pid :: option(pid()),
- delivery_flow :: flow | noflow,
- trace_state :: option(rabbit_trace:state()),
- prefetch :: non_neg_integer(),
- client_id :: option(binary()),
- conn_name :: option(binary()),
- peer_addr :: inet:ip_address(),
- host :: inet:ip_address(),
- port :: inet:port_number(),
- peer_host :: inet:ip_address(),
- peer_port :: inet:port_number(),
- connected_at :: pos_integer(),
- send_fun :: fun((Packet :: tuple(), state()) -> term())
-}).
-
--record(state, {
- cfg :: #cfg{},
- queue_states = rabbit_queue_type:init() :: rabbit_queue_type:state(),
- %% Packet IDs published to queues but not yet confirmed.
- unacked_client_pubs = rabbit_mqtt_confirms:init() :: rabbit_mqtt_confirms:state(),
- %% Packet IDs published to MQTT subscribers but not yet acknowledged.
- unacked_server_pubs = #{} :: #{packet_id() => QueueMsgId :: non_neg_integer()},
- %% Packet ID of next PUBLISH packet (with QoS > 0) sent from server to client.
- %% (Not to be confused with packet IDs sent from client to server which can be the
- %% same IDs because client and server assign IDs independently of each other.)
- packet_id = 1 :: packet_id(),
- subscriptions = #{} :: #{Topic :: binary() => QoS :: ?QOS_0..?QOS_1},
- auth_state :: option(#auth_state{}),
- register_state :: option(registered | {pending, reference()}),
- %% quorum queues and streams whose soft limit has been exceeded
- queues_soft_limit_exceeded = sets:new([{version, 2}]) :: sets:set(),
- qos0_messages_dropped = 0 :: non_neg_integer()
-}).
+-record(auth_state,
+ {username :: rabbit_types:username(),
+ user :: #user{},
+ vhost :: rabbit_types:vhost(),
+ authz_ctx :: #{binary() := binary()}
+ }).
+
+-record(cfg,
+ {socket :: rabbit_net:socket(),
+ proto_ver :: option(mqtt310 | mqtt311),
+ clean_sess :: option(boolean()),
+ will_msg :: option(mqtt_msg()),
+ exchange :: option(rabbit_exchange:name()),
+ %% Set if client has at least one subscription with QoS 1.
+ queue_qos1 :: option(rabbit_amqqueue:name()),
+ %% Did the client ever sent us a PUBLISH packet?
+ published = false :: boolean(),
+ ssl_login_name :: none | binary(),
+ retainer_pid :: option(pid()),
+ delivery_flow :: flow | noflow,
+ trace_state :: option(rabbit_trace:state()),
+ prefetch :: non_neg_integer(),
+ client_id :: option(binary()),
+ conn_name :: option(binary()),
+ peer_addr :: inet:ip_address(),
+ host :: inet:ip_address(),
+ port :: inet:port_number(),
+ peer_host :: inet:ip_address(),
+ peer_port :: inet:port_number(),
+ connected_at :: pos_integer(),
+ send_fun :: fun((Packet :: tuple(), state()) -> term())
+ }).
+
+-record(state,
+ {cfg :: #cfg{},
+ queue_states = rabbit_queue_type:init() :: rabbit_queue_type:state(),
+ %% Packet IDs published to queues but not yet confirmed.
+ unacked_client_pubs = rabbit_mqtt_confirms:init() :: rabbit_mqtt_confirms:state(),
+ %% Packet IDs published to MQTT subscribers but not yet acknowledged.
+ unacked_server_pubs = #{} :: #{packet_id() => QueueMsgId :: non_neg_integer()},
+ %% Packet ID of next PUBLISH packet (with QoS > 0) sent from server to client.
+ %% (Not to be confused with packet IDs sent from client to server which can be the
+ %% same IDs because client and server assign IDs independently of each other.)
+ packet_id = 1 :: packet_id(),
+ subscriptions = #{} :: #{Topic :: binary() => QoS :: ?QOS_0..?QOS_1},
+ auth_state :: option(#auth_state{}),
+ register_state :: option(registered | {pending, reference()}),
+ %% quorum queues and streams whose soft limit has been exceeded
+ queues_soft_limit_exceeded = sets:new([{version, 2}]) :: sets:set(),
+ qos0_messages_dropped = 0 :: non_neg_integer()
+ }).
-opaque state() :: #state{}.
@@ -102,62 +91,50 @@
state().
initial_state(Socket, ConnectionName) ->
{ok, {PeerAddr, _PeerPort}} = rabbit_net:peername(Socket),
- initial_state(
- Socket,
- ConnectionName,
- fun serialise_and_send_to_client/2,
- PeerAddr
- ).
-
--spec initial_state(
- Socket :: any(),
- ConnectionName :: binary(),
- SendFun :: fun((mqtt_packet(), state()) -> any()),
- PeerAddr :: inet:ip_address()
-) ->
+ initial_state(Socket,
+ ConnectionName,
+ fun serialise_and_send_to_client/2,
+ PeerAddr).
+
+-spec initial_state(Socket :: any(),
+ ConnectionName :: binary(),
+ SendFun :: fun((mqtt_packet(), state()) -> any()),
+ PeerAddr :: inet:ip_address()) ->
state().
initial_state(Socket, ConnectionName, SendFun, PeerAddr) ->
- Flow =
- case rabbit_misc:get_env(rabbit, mirroring_flow_control, true) of
- true -> flow;
- false -> noflow
- end,
+ Flow = case rabbit_misc:get_env(rabbit, mirroring_flow_control, true) of
+ true -> flow;
+ false -> noflow
+ end,
{ok, {PeerHost, PeerPort, Host, Port}} = rabbit_net:socket_ends(Socket, inbound),
- #state{
- cfg = #cfg{
- socket = Socket,
- conn_name = ConnectionName,
- ssl_login_name = ssl_login_name(Socket),
- send_fun = SendFun,
- prefetch = rabbit_mqtt_util:env(prefetch),
- delivery_flow = Flow,
- connected_at = os:system_time(milli_seconds),
- peer_addr = PeerAddr,
- peer_host = PeerHost,
- peer_port = PeerPort,
- host = Host,
- port = Port
- }
- }.
+ #state{cfg = #cfg{socket = Socket,
+ conn_name = ConnectionName,
+ ssl_login_name = ssl_login_name(Socket),
+ send_fun = SendFun,
+ prefetch = rabbit_mqtt_util:env(prefetch),
+ delivery_flow = Flow,
+ connected_at = os:system_time(milli_seconds),
+ peer_addr = PeerAddr,
+ peer_host = PeerHost,
+ peer_port = PeerPort,
+ host = Host,
+ port = Port}}.
-spec process_packet(mqtt_packet(), state()) ->
- {ok, state()}
- | {stop, disconnect, state()}
- | {error, Reason :: term(), state()}.
-process_packet(
- #mqtt_packet{fixed = #mqtt_packet_fixed{type = Type}},
- State = #state{auth_state = undefined}
-) when
- Type =/= ?CONNECT
-->
+ {ok, state()} |
+ {stop, disconnect, state()} |
+ {error, Reason :: term(), state()}.
+process_packet(#mqtt_packet{fixed = #mqtt_packet_fixed{type = Type}},
+ State = #state{auth_state = undefined})
+ when Type =/= ?CONNECT ->
{error, connect_expected, State};
process_packet(Packet = #mqtt_packet{fixed = #mqtt_packet_fixed{type = Type}}, State) ->
process_request(Type, Packet, State).
-spec process_request(packet_type(), mqtt_packet(), state()) ->
- {ok, state()}
- | {stop, disconnect, state()}
- | {error, Reason :: term(), state()}.
+ {ok, state()} |
+ {stop, disconnect, state()} |
+ {error, Reason :: term(), state()}.
process_request(?CONNECT, Packet, State = #state{cfg = #cfg{socket = Socket}}) ->
%% Check whether peer closed the connection.
%% For example, this can happen when connection was blocked because of resource
@@ -168,92 +145,68 @@ process_request(?CONNECT, Packet, State = #state{cfg = #cfg{socket = Socket}}) -
_ ->
process_connect(Packet, State)
end;
-process_request(
- ?PUBACK,
- #mqtt_packet{variable = #mqtt_packet_publish{packet_id = PacketId}},
- #state{
- unacked_server_pubs = U0,
- queue_states = QStates0,
- cfg = #cfg{queue_qos1 = QName}
- } = State
-) ->
+
+process_request(?PUBACK,
+ #mqtt_packet{variable = #mqtt_packet_publish{packet_id = PacketId}},
+ #state{unacked_server_pubs = U0,
+ queue_states = QStates0,
+ cfg = #cfg{queue_qos1 = QName}} = State) ->
case maps:take(PacketId, U0) of
{QMsgId, U} ->
case rabbit_queue_type:settle(QName, complete, ?CONSUMER_TAG, [QMsgId], QStates0) of
{ok, QStates, Actions} ->
message_acknowledged(QName, State),
- {ok,
- handle_queue_actions(Actions, State#state{
- unacked_server_pubs = U,
- queue_states = QStates
- })};
+ {ok, handle_queue_actions(Actions, State#state{unacked_server_pubs = U,
+ queue_states = QStates})};
{protocol_error, _ErrorType, _Reason, _ReasonArgs} = Err ->
{error, Err, State}
end;
error ->
{ok, State}
end;
-process_request(
- ?PUBLISH,
- Packet = #mqtt_packet{
- fixed = Fixed = #mqtt_packet_fixed{qos = ?QOS_2}
- },
- State
-) ->
+
+process_request(?PUBLISH,
+ Packet = #mqtt_packet{
+ fixed = Fixed = #mqtt_packet_fixed{qos = ?QOS_2}},
+ State) ->
% Downgrade QOS_2 to QOS_1
- process_request(
- ?PUBLISH,
- Packet#mqtt_packet{
- fixed = Fixed#mqtt_packet_fixed{qos = ?QOS_1}
- },
- State
- );
-process_request(
- ?PUBLISH,
- #mqtt_packet{
- fixed = #mqtt_packet_fixed{
- qos = Qos,
- retain = Retain,
- dup = Dup
- },
- variable = #mqtt_packet_publish{
- topic_name = Topic,
- packet_id = PacketId
- },
- payload = Payload
- },
- State0 = #state{
- unacked_client_pubs = U,
- cfg = #cfg{
- retainer_pid = RPid,
- proto_ver = ProtoVer
- }
- }
-) ->
+ process_request(?PUBLISH,
+ Packet#mqtt_packet{
+ fixed = Fixed#mqtt_packet_fixed{qos = ?QOS_1}},
+ State);
+process_request(?PUBLISH,
+ #mqtt_packet{
+ fixed = #mqtt_packet_fixed{qos = Qos,
+ retain = Retain,
+ dup = Dup },
+ variable = #mqtt_packet_publish{topic_name = Topic,
+ packet_id = PacketId },
+ payload = Payload},
+ State0 = #state{unacked_client_pubs = U,
+ cfg = #cfg{retainer_pid = RPid,
+ proto_ver = ProtoVer}}) ->
rabbit_global_counters:messages_received(ProtoVer, 1),
State = maybe_increment_publisher(State0),
Publish = fun() ->
- Msg = #mqtt_msg{
- retain = Retain,
- qos = Qos,
- topic = Topic,
- dup = Dup,
- packet_id = PacketId,
- payload = Payload
- },
- case publish_to_queues(Msg, State) of
- {ok, _} = Ok ->
- case Retain of
- false ->
- ok;
- true ->
- hand_off_to_retainer(RPid, Topic, Msg)
- end,
- Ok;
- Error ->
- Error
- end
- end,
+ Msg = #mqtt_msg{retain = Retain,
+ qos = Qos,
+ topic = Topic,
+ dup = Dup,
+ packet_id = PacketId,
+ payload = Payload},
+ case publish_to_queues(Msg, State) of
+ {ok, _} = Ok ->
+ case Retain of
+ false ->
+ ok;
+ true ->
+ hand_off_to_retainer(RPid, Topic, Msg)
+ end,
+ Ok;
+ Error ->
+ Error
+ end
+ end,
case Qos of
N when N > ?QOS_0 ->
rabbit_global_counters:messages_received_confirm(ProtoVer, 1),
@@ -269,219 +222,157 @@ process_request(
_ ->
publish_to_queues_with_checks(Topic, Publish, State)
end;
-process_request(
- ?SUBSCRIBE,
- #mqtt_packet{
- variable = #mqtt_packet_subscribe{
- packet_id = SubscribePktId,
- topic_table = Topics
- },
- payload = undefined
- },
- #state{
- cfg = #cfg{
- send_fun = SendFun,
- retainer_pid = RPid
- }
- } = State0
-) ->
+
+process_request(?SUBSCRIBE,
+ #mqtt_packet{
+ variable = #mqtt_packet_subscribe{
+ packet_id = SubscribePktId,
+ topic_table = Topics},
+ payload = undefined},
+ #state{cfg = #cfg{send_fun = SendFun,
+ retainer_pid = RPid}} = State0) ->
?LOG_DEBUG("Received a SUBSCRIBE for topic(s) ~p", [Topics]),
{QosResponse, State1} =
- lists:foldl(
- fun
- (_Topic, {[?SUBACK_FAILURE | _] = L, S}) ->
- %% Once a subscription failed, mark all following subscriptions
- %% as failed instead of creating bindings because we are going
- %% to close the client connection anyway.
- {[?SUBACK_FAILURE | L], S};
- (
- #mqtt_topic{
- name = TopicName,
- qos = TopicQos
- },
- {L, S0}
- ) ->
- QoS = supported_sub_qos(TopicQos),
- case maybe_replace_old_sub(TopicName, QoS, S0) of
- {ok, S1} ->
- case ensure_queue(QoS, S1) of
- {ok, Q} ->
- QName = amqqueue:get_name(Q),
- case bind(QName, TopicName, S1) of
- {ok, _Output, S2 = #state{subscriptions = Subs}} ->
- S3 = S2#state{
- subscriptions = maps:put(TopicName, QoS, Subs)
- },
- maybe_increment_consumer(S2, S3),
- case self_consumes(Q) of
- false ->
- case consume(Q, QoS, S3) of
- {ok, S4} ->
- {[QoS | L], S4};
- {error, _Reason} ->
- {[?SUBACK_FAILURE | L], S3}
- end;
- true ->
- {[QoS | L], S3}
- end;
- {error, Reason, S2} ->
- ?LOG_ERROR(
- "Failed to bind ~s with topic ~s: ~p",
- [rabbit_misc:rs(QName), TopicName, Reason]
- ),
- {[?SUBACK_FAILURE | L], S2}
- end;
- {error, _} ->
- {[?SUBACK_FAILURE | L], S1}
- end;
- {error, _Reason, S1} ->
- {[?SUBACK_FAILURE | L], S1}
- end
- end,
- {[], State0},
- Topics
- ),
+ lists:foldl(
+ fun(_Topic, {[?SUBACK_FAILURE | _] = L, S}) ->
+ %% Once a subscription failed, mark all following subscriptions
+ %% as failed instead of creating bindings because we are going
+ %% to close the client connection anyway.
+ {[?SUBACK_FAILURE | L], S};
+ (#mqtt_topic{name = TopicName,
+ qos = TopicQos},
+ {L, S0}) ->
+ QoS = supported_sub_qos(TopicQos),
+ case maybe_replace_old_sub(TopicName, QoS, S0) of
+ {ok, S1} ->
+ case ensure_queue(QoS, S1) of
+ {ok, Q} ->
+ QName = amqqueue:get_name(Q),
+ case bind(QName, TopicName, S1) of
+ {ok, _Output, S2 = #state{subscriptions = Subs}} ->
+ S3 = S2#state{subscriptions = maps:put(TopicName, QoS, Subs)},
+ maybe_increment_consumer(S2, S3),
+ case self_consumes(Q) of
+ false ->
+ case consume(Q, QoS, S3) of
+ {ok, S4} ->
+ {[QoS | L], S4};
+ {error, _Reason} ->
+ {[?SUBACK_FAILURE | L], S3}
+ end;
+ true ->
+ {[QoS | L], S3}
+ end;
+ {error, Reason, S2} ->
+ ?LOG_ERROR("Failed to bind ~s with topic ~s: ~p",
+ [rabbit_misc:rs(QName), TopicName, Reason]),
+ {[?SUBACK_FAILURE | L], S2}
+ end;
+ {error, _} ->
+ {[?SUBACK_FAILURE | L], S1}
+ end;
+ {error, _Reason, S1} ->
+ {[?SUBACK_FAILURE | L], S1}
+ end
+ end, {[], State0}, Topics),
SendFun(
- #mqtt_packet{
- fixed = #mqtt_packet_fixed{type = ?SUBACK},
- variable = #mqtt_packet_suback{
- packet_id = SubscribePktId,
- qos_table = QosResponse
- }
- },
- State1
- ),
+ #mqtt_packet{fixed = #mqtt_packet_fixed{type = ?SUBACK},
+ variable = #mqtt_packet_suback{
+ packet_id = SubscribePktId,
+ qos_table = QosResponse}},
+ State1),
case QosResponse of
[?SUBACK_FAILURE | _] ->
{error, subscribe_error, State1};
_ ->
- State = lists:foldl(
- fun(Topic, S) ->
- maybe_send_retained_message(RPid, Topic, S)
- end,
- State1,
- Topics
- ),
+ State = lists:foldl(fun(Topic, S) ->
+ maybe_send_retained_message(RPid, Topic, S)
+ end, State1, Topics),
{ok, State}
end;
-process_request(
- ?UNSUBSCRIBE,
- #mqtt_packet{
- variable = #mqtt_packet_subscribe{
- packet_id = PacketId,
- topic_table = Topics
- },
- payload = undefined
- },
- State0 = #state{cfg = #cfg{send_fun = SendFun}}
-) ->
+
+process_request(?UNSUBSCRIBE,
+ #mqtt_packet{variable = #mqtt_packet_subscribe{packet_id = PacketId,
+ topic_table = Topics},
+ payload = undefined},
+ State0 = #state{cfg = #cfg{send_fun = SendFun}}) ->
?LOG_DEBUG("Received an UNSUBSCRIBE for topic(s) ~p", [Topics]),
State = lists:foldl(
- fun(#mqtt_topic{name = TopicName}, #state{subscriptions = Subs0} = S0) ->
- case maps:take(TopicName, Subs0) of
- {QoS, Subs} ->
- QName = queue_name(QoS, S0),
- case unbind(QName, TopicName, S0) of
- {ok, _, S1} ->
- S = S1#state{subscriptions = Subs},
- maybe_decrement_consumer(S1, S),
- S;
- {error, Reason, S} ->
- ?LOG_ERROR(
- "Failed to unbind ~s with topic ~s: ~p",
- [rabbit_misc:rs(QName), TopicName, Reason]
- ),
- S
- end;
- error ->
- S0
- end
- end,
- State0,
- Topics
- ),
+ fun(#mqtt_topic{name = TopicName}, #state{subscriptions = Subs0} = S0) ->
+ case maps:take(TopicName, Subs0) of
+ {QoS, Subs} ->
+ QName = queue_name(QoS, S0),
+ case unbind(QName, TopicName, S0) of
+ {ok, _, S1} ->
+ S = S1#state{subscriptions = Subs},
+ maybe_decrement_consumer(S1, S),
+ S;
+ {error, Reason, S} ->
+ ?LOG_ERROR("Failed to unbind ~s with topic ~s: ~p",
+ [rabbit_misc:rs(QName), TopicName, Reason]),
+ S
+ end;
+ error ->
+ S0
+ end
+ end, State0, Topics),
SendFun(
- #mqtt_packet{
- fixed = #mqtt_packet_fixed{type = ?UNSUBACK},
- variable = #mqtt_packet_suback{packet_id = PacketId}
- },
- State
- ),
+ #mqtt_packet{fixed = #mqtt_packet_fixed {type = ?UNSUBACK},
+ variable = #mqtt_packet_suback{packet_id = PacketId}},
+ State),
{ok, State};
-process_request(
- ?PINGREQ,
- #mqtt_packet{},
- State = #state{
- cfg = #cfg{
- send_fun = SendFun,
- client_id = ClientId
- }
- }
-) ->
+
+process_request(?PINGREQ, #mqtt_packet{},
+ State = #state{cfg = #cfg{send_fun = SendFun,
+ client_id = ClientId}}) ->
?LOG_DEBUG("Received a PINGREQ, client ID: ~s", [ClientId]),
SendFun(
- #mqtt_packet{fixed = #mqtt_packet_fixed{type = ?PINGRESP}},
- State
- ),
+ #mqtt_packet{fixed = #mqtt_packet_fixed{type = ?PINGRESP}},
+ State),
?LOG_DEBUG("Sent a PINGRESP, client ID: ~s", [ClientId]),
{ok, State};
+
process_request(?DISCONNECT, #mqtt_packet{}, State) ->
?LOG_DEBUG("Received a DISCONNECT"),
{stop, disconnect, State}.
-process_connect(
- #mqtt_packet{
- variable =
- #mqtt_packet_connect{
- username = Username,
- proto_ver = ProtoVersion,
- clean_sess = CleanSess,
- client_id = ClientId,
- keep_alive = Keepalive
- } = PacketConnect
- },
- State0 = #state{cfg = #cfg{send_fun = SendFun}}
-) ->
- ?LOG_DEBUG(
- "Received a CONNECT, client ID: ~s, username: ~s, "
- "clean session: ~s, protocol version: ~p, keepalive: ~p",
- [ClientId, Username, CleanSess, ProtoVersion, Keepalive]
- ),
+process_connect(#mqtt_packet{
+ variable = #mqtt_packet_connect{
+ username = Username,
+ proto_ver = ProtoVersion,
+ clean_sess = CleanSess,
+ client_id = ClientId,
+ keep_alive = Keepalive} = PacketConnect},
+ State0 = #state{cfg = #cfg{send_fun = SendFun}}) ->
+ ?LOG_DEBUG("Received a CONNECT, client ID: ~s, username: ~s, "
+ "clean session: ~s, protocol version: ~p, keepalive: ~p",
+ [ClientId, Username, CleanSess, ProtoVersion, Keepalive]),
{ReturnCode, SessPresent, State} =
- case
- rabbit_misc:pipeline(
- [
- fun check_protocol_version/1,
- fun check_client_id/1,
- fun check_credentials/2,
- fun login/2,
- fun register_client/2,
- fun start_keepalive/2,
- fun notify_connection_created/1,
- fun init_trace/2,
- fun handle_clean_sess_qos0/2,
- fun handle_clean_sess_qos1/2,
- fun cache_subscriptions/2
- ],
- PacketConnect,
- State0
- )
- of
- {ok, SessPresent0, State1} ->
- {?CONNACK_ACCEPT, SessPresent0, State1};
- {error, ConnectionRefusedReturnCode, State1} ->
- {ConnectionRefusedReturnCode, false, State1}
- end,
- Response = #mqtt_packet{
- fixed = #mqtt_packet_fixed{type = ?CONNACK},
- variable = #mqtt_packet_connack{
- session_present = SessPresent,
- return_code = ReturnCode
- }
- },
+ case rabbit_misc:pipeline([fun check_protocol_version/1,
+ fun check_client_id/1,
+ fun check_credentials/2,
+ fun login/2,
+ fun register_client/2,
+ fun start_keepalive/2,
+ fun notify_connection_created/1,
+ fun init_trace/2,
+ fun handle_clean_sess_qos0/2,
+ fun handle_clean_sess_qos1/2,
+ fun cache_subscriptions/2
+ ],
+ PacketConnect, State0) of
+ {ok, SessPresent0, State1} ->
+ {?CONNACK_ACCEPT, SessPresent0, State1};
+ {error, ConnectionRefusedReturnCode, State1} ->
+ {ConnectionRefusedReturnCode, false, State1}
+ end,
+ Response = #mqtt_packet{fixed = #mqtt_packet_fixed{type = ?CONNACK},
+ variable = #mqtt_packet_connack{
+ session_present = SessPresent,
+ return_code = ReturnCode}},
SendFun(Response, State),
return_connack(ReturnCode, State).
@@ -493,26 +384,16 @@ check_protocol_version(#mqtt_packet_connect{proto_ver = ProtoVersion}) ->
{error, ?CONNACK_UNACCEPTABLE_PROTO_VER}
end.
-check_client_id(#mqtt_packet_connect{
- clean_sess = false,
- client_id = <<>>
-}) ->
+check_client_id(#mqtt_packet_connect{clean_sess = false,
+ client_id = <<>>}) ->
{error, ?CONNACK_ID_REJECTED};
check_client_id(_) ->
ok.
-check_credentials(
- Packet = #mqtt_packet_connect{
- username = Username,
- password = Password
- },
- State = #state{
- cfg = #cfg{
- ssl_login_name = SslLoginName,
- peer_addr = PeerAddr
- }
- }
-) ->
+check_credentials(Packet = #mqtt_packet_connect{username = Username,
+ password = Password},
+ State = #state{cfg = #cfg{ssl_login_name = SslLoginName,
+ peer_addr = PeerAddr}}) ->
Ip = list_to_binary(inet:ntoa(PeerAddr)),
case creds(Username, Password, SslLoginName) of
nocreds ->
@@ -531,21 +412,15 @@ check_credentials(
{ok, {UserBin, PassBin, Packet}, State}
end.
-login(
- {UserBin, PassBin,
- Packet = #mqtt_packet_connect{
- client_id = ClientId0,
- clean_sess = CleanSess
- }},
- State0 = #state{cfg = Cfg0}
-) ->
+login({UserBin, PassBin,
+ Packet = #mqtt_packet_connect{client_id = ClientId0,
+ clean_sess = CleanSess}},
+ State0 = #state{cfg = Cfg0}) ->
ClientId = ensure_client_id(ClientId0),
case process_login(UserBin, PassBin, ClientId, State0) of
{ok, State} ->
- Cfg = Cfg0#cfg{
- client_id = ClientId,
- clean_sess = CleanSess
- },
+ Cfg = Cfg0#cfg{client_id = ClientId,
+ clean_sess = CleanSess},
{ok, Packet, State#state{cfg = Cfg}};
{error, _ConnectionRefusedReturnCode, _State} = Err ->
Err
@@ -554,39 +429,28 @@ login(
-spec ensure_client_id(binary()) -> binary().
ensure_client_id(<<>>) ->
rabbit_data_coercion:to_binary(
- rabbit_misc:base64url(
- rabbit_guid:gen_secure()
- )
- );
-ensure_client_id(ClientId) when
- is_binary(ClientId)
-->
+ rabbit_misc:base64url(
+ rabbit_guid:gen_secure()));
+ensure_client_id(ClientId)
+ when is_binary(ClientId) ->
ClientId.
-register_client(
- Packet = #mqtt_packet_connect{proto_ver = ProtoVersion},
- State = #state{
- auth_state = #auth_state{vhost = VHost},
- cfg = Cfg0 = #cfg{client_id = ClientId}
- }
-) ->
+register_client(Packet = #mqtt_packet_connect{proto_ver = ProtoVersion},
+ State = #state{auth_state = #auth_state{vhost = VHost},
+ cfg = Cfg0 = #cfg{client_id = ClientId}}) ->
NewProcState =
- fun(RegisterState) ->
+ fun(RegisterState) ->
rabbit_mqtt_util:register_clientid(VHost, ClientId),
RetainerPid = rabbit_mqtt_retainer_sup:child_for_vhost(VHost),
ExchangeBin = rabbit_mqtt_util:env(exchange),
ExchangeName = rabbit_misc:r(VHost, exchange, ExchangeBin),
- Cfg = Cfg0#cfg{
- exchange = ExchangeName,
- will_msg = make_will_msg(Packet),
- retainer_pid = RetainerPid,
- proto_ver = proto_integer_to_atom(ProtoVersion)
- },
- State#state{
- cfg = Cfg,
- register_state = RegisterState
- }
- end,
+ Cfg = Cfg0#cfg{exchange = ExchangeName,
+ will_msg = make_will_msg(Packet),
+ retainer_pid = RetainerPid,
+ proto_ver = proto_integer_to_atom(ProtoVersion)},
+ State#state{cfg = Cfg,
+ register_state = RegisterState}
+ end,
case rabbit_mqtt_ff:track_client_id_in_ra() of
true ->
case rabbit_mqtt_collector:register(ClientId, self()) of
@@ -594,10 +458,8 @@ register_client(
{ok, NewProcState({pending, Corr})};
{error, _} = Err ->
%% e.g. this node was removed from the MQTT cluster members
- ?LOG_ERROR(
- "MQTT cannot accept a connection: client ID tracker is unavailable: ~p",
- [Err]
- ),
+ ?LOG_ERROR("MQTT cannot accept a connection: client ID tracker is unavailable: ~p",
+ [Err]),
{error, ?CONNACK_SERVER_UNAVAILABLE}
end;
false ->
@@ -613,25 +475,17 @@ init_trace(#mqtt_packet_connect{}, State = #state{cfg = #cfg{conn_name = ConnNam
{ok, update_trace(ConnName, State)}.
-spec update_trace(binary(), state()) -> state().
-update_trace(
- ConnName0,
- State = #state{
- cfg = Cfg0,
- auth_state = #auth_state{vhost = VHost}
- }
-) ->
- ConnName =
- case rabbit_trace:enabled(VHost) of
- true ->
- ConnName0;
- false ->
- %% We won't need conn_name. Use less memmory by setting to undefined.
- undefined
- end,
- Cfg = Cfg0#cfg{
- conn_name = ConnName,
- trace_state = rabbit_trace:init(VHost)
- },
+update_trace(ConnName0, State = #state{cfg = Cfg0,
+ auth_state = #auth_state{vhost = VHost}}) ->
+ ConnName = case rabbit_trace:enabled(VHost) of
+ true ->
+ ConnName0;
+ false ->
+ %% We won't need conn_name. Use less memmory by setting to undefined.
+ undefined
+ end,
+ Cfg = Cfg0#cfg{conn_name = ConnName,
+ trace_state = rabbit_trace:init(VHost)},
State#state{cfg = Cfg}.
return_connack(?CONNACK_ACCEPT, S) ->
@@ -653,18 +507,13 @@ self_consumes(Queue) ->
?QUEUE_TYPE_QOS_0 ->
false;
_ ->
- lists:any(
- fun(Consumer) ->
- element(1, Consumer) =:= self()
- end,
- rabbit_amqqueue:consumers(Queue)
- )
+ lists:any(fun(Consumer) ->
+ element(1, Consumer) =:= self()
+ end, rabbit_amqqueue:consumers(Queue))
end.
-start_keepalive(
- #mqtt_packet_connect{keep_alive = Seconds},
- #state{cfg = #cfg{socket = Socket}}
-) ->
+start_keepalive(#mqtt_packet_connect{keep_alive = Seconds},
+ #state{cfg = #cfg{socket = Socket}}) ->
ok = rabbit_mqtt_keepalive:start(Seconds, Socket).
handle_clean_sess_qos0(#mqtt_packet_connect{}, State) ->
@@ -673,18 +522,11 @@ handle_clean_sess_qos0(#mqtt_packet_connect{}, State) ->
handle_clean_sess_qos1(QoS0SessPresent, State) ->
handle_clean_sess(QoS0SessPresent, ?QOS_1, State).
-handle_clean_sess(
- _,
- QoS,
- State = #state{
- cfg = #cfg{clean_sess = true},
- auth_state = #auth_state{
- user = User,
- username = Username,
- authz_ctx = AuthzCtx
- }
- }
-) ->
+handle_clean_sess(_, QoS,
+ State = #state{cfg = #cfg{clean_sess = true},
+ auth_state = #auth_state{user = User,
+ username = Username,
+ authz_ctx = AuthzCtx}}) ->
%% "If the Server accepts a connection with CleanSession set to 1, the Server
%% MUST set Session Present to 0 in the CONNACK packet [MQTT-3.2.2-1].
SessPresent = false,
@@ -702,16 +544,9 @@ handle_clean_sess(
{error, ?CONNACK_NOT_AUTHORIZED}
end
end;
-handle_clean_sess(
- SessPresent,
- QoS,
- State0 = #state{
- cfg = #cfg{
- clean_sess = false,
- proto_ver = ProtoVer
- }
- }
-) ->
+handle_clean_sess(SessPresent, QoS,
+ State0 = #state{cfg = #cfg{clean_sess = false,
+ proto_ver = ProtoVer}}) ->
case get_queue(QoS, State0) of
{error, _} ->
%% Queue will be created later when client subscribes.
@@ -736,8 +571,8 @@ handle_clean_sess(
end.
-spec get_queue(qos(), state()) ->
- {ok, amqqueue:amqqueue()}
- | {error, not_found | {resource_locked, amqqueue:amqqueue()}}.
+ {ok, amqqueue:amqqueue()} |
+ {error, not_found | {resource_locked, amqqueue:amqqueue()}}.
get_queue(QoS, State) ->
QName = queue_name(QoS, State),
case rabbit_amqqueue:lookup(QName) of
@@ -757,10 +592,8 @@ get_queue(QoS, State) ->
queue_name(?QOS_1, #state{cfg = #cfg{queue_qos1 = #resource{kind = queue} = Name}}) ->
Name;
-queue_name(QoS, #state{
- auth_state = #auth_state{vhost = VHost},
- cfg = #cfg{client_id = ClientId}
-}) ->
+queue_name(QoS, #state{auth_state = #auth_state{vhost = VHost},
+ cfg = #cfg{client_id = ClientId}}) ->
QNameBin = rabbit_mqtt_util:queue_name_bin(ClientId, QoS),
rabbit_misc:r(VHost, queue, QNameBin).
@@ -769,26 +602,23 @@ queue_name(QoS, #state{
cache_subscriptions(_SessionPresent = _SubscriptionsPresent = true, State) ->
SubsQos0 = topic_names(?QOS_0, State),
SubsQos1 = topic_names(?QOS_1, State),
- Subs = maps:merge(
- maps:from_keys(SubsQos0, ?QOS_0),
- maps:from_keys(SubsQos1, ?QOS_1)
- ),
+ Subs = maps:merge(maps:from_keys(SubsQos0, ?QOS_0),
+ maps:from_keys(SubsQos1, ?QOS_1)),
{ok, State#state{subscriptions = Subs}};
cache_subscriptions(_, _) ->
ok.
topic_names(QoS, State = #state{cfg = #cfg{exchange = Exchange}}) ->
Bindings =
- rabbit_binding:list_for_source_and_destination(
- Exchange,
- queue_name(QoS, State),
- %% Querying table rabbit_route is catastrophic for CPU usage.
- %% Querying table rabbit_reverse_route is acceptable because
- %% the source exchange is always the same in the MQTT plugin whereas
- %% the destination queue is different for each MQTT client and
- %% rabbit_reverse_route is sorted by destination queue.
- _Reverse = true
- ),
+ rabbit_binding:list_for_source_and_destination(
+ Exchange,
+ queue_name(QoS, State),
+ %% Querying table rabbit_route is catastrophic for CPU usage.
+ %% Querying table rabbit_reverse_route is acceptable because
+ %% the source exchange is always the same in the MQTT plugin whereas
+ %% the destination queue is different for each MQTT client and
+ %% rabbit_reverse_route is sorted by destination queue.
+ _Reverse = true),
lists:map(fun(B) -> amqp_to_mqtt(B#binding.key) end, Bindings).
%% "If a Server receives a SUBSCRIBE Packet containing a Topic Filter that is identical
@@ -798,24 +628,21 @@ topic_names(QoS, State = #state{cfg = #cfg{exchange = Exchange}}) ->
%% could be different." [MQTT-3.8.4-3].
maybe_replace_old_sub(TopicName, QoS, State = #state{subscriptions = Subs}) ->
case Subs of
- #{TopicName := OldQoS} when
- OldQoS =/= QoS
- ->
+ #{TopicName := OldQoS}
+ when OldQoS =/= QoS ->
replace_old_sub(OldQoS, TopicName, State);
_ ->
{ok, State}
end.
-replace_old_sub(QoS, TopicName, State0) ->
+replace_old_sub(QoS, TopicName, State0)->
QName = queue_name(QoS, State0),
case unbind(QName, TopicName, State0) of
{ok, _Output, State} ->
{ok, State};
{error, Reason, _State} = Err ->
- ?LOG_ERROR(
- "Failed to unbind ~s with topic '~s': ~p",
- [rabbit_misc:rs(QName), TopicName, Reason]
- ),
+ ?LOG_ERROR("Failed to unbind ~s with topic '~s': ~p",
+ [rabbit_misc:rs(QName), TopicName, Reason]),
Err
end.
@@ -829,124 +656,85 @@ hand_off_to_retainer(RetainerPid, Topic0, Msg) ->
rabbit_mqtt_retainer:retain(RetainerPid, Topic1, Msg),
ok.
-maybe_send_retained_message(
- RPid,
- #mqtt_topic{name = Topic0, qos = SubscribeQos},
- State0 = #state{
- packet_id = PacketId0,
- cfg = #cfg{send_fun = SendFun}
- }
-) ->
+maybe_send_retained_message(RPid, #mqtt_topic{name = Topic0, qos = SubscribeQos},
+ State0 = #state{packet_id = PacketId0,
+ cfg = #cfg{send_fun = SendFun}}) ->
Topic1 = amqp_to_mqtt(Topic0),
case rabbit_mqtt_retainer:fetch(RPid, Topic1) of
undefined ->
State0;
Msg ->
Qos = effective_qos(Msg#mqtt_msg.qos, SubscribeQos),
- {PacketId, State} =
- case Qos of
- ?QOS_0 ->
- {undefined, State0};
- ?QOS_1 ->
- {PacketId0, State0#state{packet_id = increment_packet_id(PacketId0)}}
- end,
+ {PacketId, State} = case Qos of
+ ?QOS_0 ->
+ {undefined, State0};
+ ?QOS_1 ->
+ {PacketId0, State0#state{packet_id = increment_packet_id(PacketId0)}}
+ end,
SendFun(
- #mqtt_packet{
- fixed = #mqtt_packet_fixed{
- type = ?PUBLISH,
- qos = Qos,
- dup = false,
- retain = Msg#mqtt_msg.retain
- },
- variable = #mqtt_packet_publish{
- packet_id = PacketId,
- topic_name = Topic1
- },
- payload = Msg#mqtt_msg.payload
- },
- State
- ),
+ #mqtt_packet{fixed = #mqtt_packet_fixed{
+ type = ?PUBLISH,
+ qos = Qos,
+ dup = false,
+ retain = Msg#mqtt_msg.retain
+ }, variable = #mqtt_packet_publish{
+ packet_id = PacketId,
+ topic_name = Topic1
+ },
+ payload = Msg#mqtt_msg.payload},
+ State),
State
end.
-make_will_msg(#mqtt_packet_connect{will_flag = false}) ->
+make_will_msg(#mqtt_packet_connect{will_flag = false}) ->
undefined;
-make_will_msg(#mqtt_packet_connect{
- will_retain = Retain,
- will_qos = Qos,
- will_topic = Topic,
- will_msg = Msg
-}) ->
- #mqtt_msg{
- retain = Retain,
- qos = Qos,
- topic = Topic,
- dup = false,
- payload = Msg
- }.
-
-process_login(
- _UserBin,
- _PassBin,
- ClientId,
- #state{
- cfg = #cfg{peer_addr = Addr},
- auth_state = #auth_state{
- username = Username,
- user = User,
- vhost = VHost
- }
- } = State
-) when
- Username =/= undefined, User =/= undefined, VHost =/= underfined
-->
+make_will_msg(#mqtt_packet_connect{will_retain = Retain,
+ will_qos = Qos,
+ will_topic = Topic,
+ will_msg = Msg}) ->
+ #mqtt_msg{retain = Retain,
+ qos = Qos,
+ topic = Topic,
+ dup = false,
+ payload = Msg}.
+
+process_login(_UserBin, _PassBin, ClientId,
+ #state{cfg = #cfg{peer_addr = Addr},
+ auth_state = #auth_state{username = Username,
+ user = User,
+ vhost = VHost
+ }} = State)
+ when Username =/= undefined, User =/= undefined, VHost =/= underfined ->
rabbit_core_metrics:auth_attempt_failed(list_to_binary(inet:ntoa(Addr)), Username, mqtt),
?LOG_ERROR(
- "MQTT detected duplicate connect attempt for client ID '~ts', user '~ts', vhost '~ts'",
- [ClientId, Username, VHost]
- ),
+ "MQTT detected duplicate connect attempt for client ID '~ts', user '~ts', vhost '~ts'",
+ [ClientId, Username, VHost]),
{error, ?CONNACK_ID_REJECTED, State};
-process_login(
- UserBin,
- PassBin,
- ClientId,
- #state{
- auth_state = undefined,
- cfg = #cfg{
- socket = Sock,
- ssl_login_name = SslLoginName,
- peer_addr = Addr
- }
- } = State0
-) ->
+process_login(UserBin, PassBin, ClientId,
+ #state{auth_state = undefined,
+ cfg = #cfg{socket = Sock,
+ ssl_login_name = SslLoginName,
+ peer_addr = Addr
+ }} = State0) ->
{ok, {_PeerHost, _PeerPort, _Host, Port}} = rabbit_net:socket_ends(Sock, inbound),
{VHostPickedUsing, {VHost, UsernameBin}} = get_vhost(UserBin, SslLoginName, Port),
- ?LOG_DEBUG(
- "MQTT vhost picked using ~s",
- [human_readable_vhost_lookup_strategy(VHostPickedUsing)]
- ),
+ ?LOG_DEBUG("MQTT vhost picked using ~s",
+ [human_readable_vhost_lookup_strategy(VHostPickedUsing)]),
RemoteIpAddressBin = list_to_binary(inet:ntoa(Addr)),
- Input = #{
- vhost => VHost,
- username_bin => UsernameBin,
- pass_bin => PassBin,
- client_id => ClientId
- },
- case
- rabbit_misc:pipeline(
- [
- fun check_vhost_exists/1,
- fun check_vhost_connection_limit/1,
- fun check_vhost_alive/1,
- fun check_user_login/2,
- fun check_user_connection_limit/1,
- fun check_vhost_access/2,
- fun check_user_loopback/2
- ],
- Input,
- State0
- )
- of
+ Input = #{vhost => VHost,
+ username_bin => UsernameBin,
+ pass_bin => PassBin,
+ client_id => ClientId},
+ case rabbit_misc:pipeline(
+ [fun check_vhost_exists/1,
+ fun check_vhost_connection_limit/1,
+ fun check_vhost_alive/1,
+ fun check_user_login/2,
+ fun check_user_connection_limit/1,
+ fun check_vhost_access/2,
+ fun check_user_loopback/2
+ ],
+ Input, State0) of
{ok, _Output, State} ->
rabbit_core_metrics:auth_attempt_succeeded(RemoteIpAddressBin, UsernameBin, mqtt),
{ok, State};
@@ -955,174 +743,134 @@ process_login(
Err
end.
-check_vhost_exists(#{
- vhost := VHost,
- username_bin := UsernameBin
-}) ->
+check_vhost_exists(#{vhost := VHost,
+ username_bin := UsernameBin}) ->
case rabbit_vhost:exists(VHost) of
- true ->
+ true ->
ok;
false ->
- ?LOG_ERROR(
- "MQTT login failed for user '~s': virtual host '~s' does not exist",
- [UsernameBin, VHost]
- ),
+ ?LOG_ERROR("MQTT login failed for user '~s': virtual host '~s' does not exist",
+ [UsernameBin, VHost]),
{error, ?CONNACK_BAD_CREDENTIALS}
end.
-check_vhost_connection_limit(#{
- vhost := VHost,
- client_id := ClientId,
- username_bin := Username
-}) ->
+check_vhost_connection_limit(#{vhost := VHost,
+ client_id := ClientId,
+ username_bin := Username}) ->
case rabbit_vhost_limit:is_over_connection_limit(VHost) of
false ->
ok;
{true, Limit} ->
?LOG_ERROR(
- "Failed to create MQTT connection because vhost connection limit is reached; "
- "vhost: '~s'; connection limit: ~p; user: '~s'; client ID '~s'",
- [VHost, Limit, Username, ClientId]
- ),
+ "Failed to create MQTT connection because vhost connection limit is reached; "
+ "vhost: '~s'; connection limit: ~p; user: '~s'; client ID '~s'",
+ [VHost, Limit, Username, ClientId]),
{error, ?CONNACK_NOT_AUTHORIZED}
end.
-check_vhost_alive(#{
- vhost := VHost,
- client_id := ClientId,
- username_bin := UsernameBin
-}) ->
+check_vhost_alive(#{vhost := VHost,
+ client_id := ClientId,
+ username_bin := UsernameBin}) ->
case rabbit_vhost_sup_sup:is_vhost_alive(VHost) of
- true ->
+ true ->
ok;
false ->
?LOG_ERROR(
- "Failed to create MQTT connection because vhost is down; "
- "vhost: ~s; user: ~s; client ID: ~s",
- [VHost, UsernameBin, ClientId]
- ),
+ "Failed to create MQTT connection because vhost is down; "
+ "vhost: ~s; user: ~s; client ID: ~s",
+ [VHost, UsernameBin, ClientId]),
{error, ?CONNACK_NOT_AUTHORIZED}
end.
-check_user_login(
- #{
- vhost := VHost,
- username_bin := UsernameBin,
- pass_bin := PassBin,
- client_id := ClientId
- } = In,
- State
-) ->
- AuthProps =
- case PassBin of
- none ->
- %% SSL user name provided.
- %% Authenticating using username only.
- [];
- _ ->
- [
- {password, PassBin},
- {vhost, VHost},
- {client_id, ClientId}
- ]
- end,
- case
- rabbit_access_control:check_user_login(
- UsernameBin, AuthProps
- )
- of
+check_user_login(#{vhost := VHost,
+ username_bin := UsernameBin,
+ pass_bin := PassBin,
+ client_id := ClientId
+ } = In, State) ->
+ AuthProps = case PassBin of
+ none ->
+ %% SSL user name provided.
+ %% Authenticating using username only.
+ [];
+ _ ->
+ [{password, PassBin},
+ {vhost, VHost},
+ {client_id, ClientId}]
+ end,
+ case rabbit_access_control:check_user_login(
+ UsernameBin, AuthProps) of
{ok, User = #user{username = Username}} ->
notify_auth_result(user_authentication_success, Username, State),
{ok, maps:put(user, User, In), State};
{refused, Username, Msg, Args} ->
?LOG_ERROR(
- "Error on MQTT connection ~p~n"
- "access refused for user '~s' in vhost '~s' " ++
- Msg,
- [self(), Username, VHost] ++ Args
- ),
+ "Error on MQTT connection ~p~n"
+ "access refused for user '~s' in vhost '~s' "
+ ++ Msg,
+ [self(), Username, VHost] ++ Args),
notify_auth_result(user_authentication_failure, Username, State),
{error, ?CONNACK_BAD_CREDENTIALS}
end.
notify_auth_result(AuthResult, Username, #state{cfg = #cfg{conn_name = ConnName}}) ->
rabbit_event:notify(
- AuthResult,
- [
- {name, Username},
- {connection_name, ConnName},
- {connection_type, network}
- ]
- ).
-
-check_user_connection_limit(#{
- user := #user{username = Username},
- client_id := ClientId
-}) ->
+ AuthResult,
+ [{name, Username},
+ {connection_name, ConnName},
+ {connection_type, network}]).
+
+check_user_connection_limit(#{user := #user{username = Username},
+ client_id := ClientId}) ->
case rabbit_auth_backend_internal:is_over_connection_limit(Username) of
false ->
ok;
{true, Limit} ->
?LOG_ERROR(
- "Failed to create MQTT connection because user connection limit is reached; "
- "user: '~s'; connection limit: ~p; client ID '~s'",
- [Username, Limit, ClientId]
- ),
+ "Failed to create MQTT connection because user connection limit is reached; "
+ "user: '~s'; connection limit: ~p; client ID '~s'",
+ [Username, Limit, ClientId]),
{error, ?CONNACK_NOT_AUTHORIZED}
end.
-check_vhost_access(
- #{
- vhost := VHost,
- client_id := ClientId,
- user := User = #user{username = Username}
- } = In,
- #state{cfg = #cfg{peer_addr = PeerAddr}} = State
-) ->
+
+check_vhost_access(#{vhost := VHost,
+ client_id := ClientId,
+ user := User = #user{username = Username}
+ } = In,
+ #state{cfg = #cfg{peer_addr = PeerAddr}} = State) ->
AuthzCtx = #{<<"client_id">> => ClientId},
- try
- rabbit_access_control:check_vhost_access(
- User,
- VHost,
- {ip, PeerAddr},
- AuthzCtx
- )
- of
+ try rabbit_access_control:check_vhost_access(
+ User,
+ VHost,
+ {ip, PeerAddr},
+ AuthzCtx) of
ok ->
{ok, maps:put(authz_ctx, AuthzCtx, In), State}
- catch
- exit:#amqp_error{name = not_allowed} ->
- ?LOG_ERROR(
+ catch exit:#amqp_error{name = not_allowed} ->
+ ?LOG_ERROR(
"Error on MQTT connection ~p~n"
"access refused for user '~s'",
- [self(), Username]
- ),
- {error, ?CONNACK_NOT_AUTHORIZED}
+ [self(), Username]),
+ {error, ?CONNACK_NOT_AUTHORIZED}
end.
-check_user_loopback(
- #{
- vhost := VHost,
- username_bin := UsernameBin,
- user := User,
- authz_ctx := AuthzCtx
- },
- #state{cfg = #cfg{peer_addr = PeerAddr}} = State
-) ->
+check_user_loopback(#{vhost := VHost,
+ username_bin := UsernameBin,
+ user := User,
+ authz_ctx := AuthzCtx
+ },
+ #state{cfg = #cfg{peer_addr = PeerAddr}} = State) ->
case rabbit_access_control:check_user_loopback(UsernameBin, PeerAddr) of
ok ->
- AuthState = #auth_state{
- user = User,
- username = UsernameBin,
- vhost = VHost,
- authz_ctx = AuthzCtx
- },
+ AuthState = #auth_state{user = User,
+ username = UsernameBin,
+ vhost = VHost,
+ authz_ctx = AuthzCtx},
{ok, State#state{auth_state = AuthState}};
not_allowed ->
?LOG_WARNING(
- "MQTT login failed: user '~s' can only connect via localhost",
- [UsernameBin]
- ),
+ "MQTT login failed: user '~s' can only connect via localhost",
+ [UsernameBin]),
{error, ?CONNACK_NOT_AUTHORIZED}
end.
@@ -1135,12 +883,12 @@ get_vhost(UserBin, SslLogin, Port) ->
get_vhost_no_ssl(UserBin, Port) ->
case vhost_in_username(UserBin) of
- true ->
+ true ->
{vhost_in_username_or_default, get_vhost_username(UserBin)};
false ->
PortVirtualHostMapping = rabbit_runtime_parameters:value_global(
- mqtt_port_to_vhost_mapping
- ),
+ mqtt_port_to_vhost_mapping
+ ),
case get_vhost_from_port_mapping(Port, PortVirtualHostMapping) of
undefined ->
{default_vhost, {rabbit_mqtt_util:env(vhost), UserBin}};
@@ -1151,13 +899,13 @@ get_vhost_no_ssl(UserBin, Port) ->
get_vhost_ssl(UserBin, SslLoginName, Port) ->
UserVirtualHostMapping = rabbit_runtime_parameters:value_global(
- mqtt_default_vhosts
- ),
+ mqtt_default_vhosts
+ ),
case get_vhost_from_user_mapping(SslLoginName, UserVirtualHostMapping) of
undefined ->
PortVirtualHostMapping = rabbit_runtime_parameters:value_global(
- mqtt_port_to_vhost_mapping
- ),
+ mqtt_port_to_vhost_mapping
+ ),
case get_vhost_from_port_mapping(Port, PortVirtualHostMapping) of
undefined ->
{vhost_in_username_or_default, get_vhost_username(UserBin)};
@@ -1170,26 +918,24 @@ get_vhost_ssl(UserBin, SslLoginName, Port) ->
vhost_in_username(UserBin) ->
case application:get_env(?APP_NAME, ignore_colons_in_username) of
- {ok, true} ->
- false;
+ {ok, true} -> false;
_ ->
%% split at the last colon, disallowing colons in username
case re:split(UserBin, ":(?!.*?:)") of
- [_, _] -> true;
- [UserBin] -> false
+ [_, _] -> true;
+ [UserBin] -> false
end
end.
get_vhost_username(UserBin) ->
Default = {rabbit_mqtt_util:env(vhost), UserBin},
case application:get_env(?APP_NAME, ignore_colons_in_username) of
- {ok, true} ->
- Default;
+ {ok, true} -> Default;
_ ->
%% split at the last colon, disallowing colons in username
case re:split(UserBin, ":(?!.*?:)") of
- [Vhost, UserName] -> {Vhost, UserName};
- [UserBin] -> Default
+ [Vhost, UserName] -> {Vhost, UserName};
+ [UserBin] -> Default
end
end.
@@ -1208,13 +954,12 @@ get_vhost_from_port_mapping(_Port, not_found) ->
undefined;
get_vhost_from_port_mapping(Port, Mapping) ->
M = rabbit_data_coercion:to_proplist(Mapping),
- Res =
- case rabbit_misc:pget(rabbit_data_coercion:to_binary(Port), M) of
- undefined ->
- undefined;
- VHost ->
- VHost
- end,
+ Res = case rabbit_misc:pget(rabbit_data_coercion:to_binary(Port), M) of
+ undefined ->
+ undefined;
+ VHost ->
+ VHost
+ end,
Res.
human_readable_vhost_lookup_strategy(vhost_in_username_or_default) ->
@@ -1227,14 +972,13 @@ human_readable_vhost_lookup_strategy(default_vhost) ->
"plugin configuration or default".
creds(User, Pass, SSLLoginName) ->
- DefaultUser = rabbit_mqtt_util:env(default_user),
- DefaultPass = rabbit_mqtt_util:env(default_pass),
- {ok, Anon} = application:get_env(?APP_NAME, allow_anonymous),
+ DefaultUser = rabbit_mqtt_util:env(default_user),
+ DefaultPass = rabbit_mqtt_util:env(default_pass),
+ {ok, Anon} = application:get_env(?APP_NAME, allow_anonymous),
{ok, TLSAuth} = application:get_env(?APP_NAME, ssl_cert_login),
- HaveDefaultCreds =
- Anon =:= true andalso
- is_binary(DefaultUser) andalso
- is_binary(DefaultPass),
+ HaveDefaultCreds = Anon =:= true andalso
+ is_binary(DefaultUser) andalso
+ is_binary(DefaultPass),
CredentialsProvided = User =/= undefined orelse Pass =/= undefined,
CorrectCredentials = is_binary(User) andalso is_binary(Pass),
@@ -1242,15 +986,15 @@ creds(User, Pass, SSLLoginName) ->
case {CredentialsProvided, CorrectCredentials, SSLLoginProvided, HaveDefaultCreds} of
%% Username and password take priority
- {true, true, _, _} -> {User, Pass};
+ {true, true, _, _} -> {User, Pass};
%% Either username or password is provided
- {true, false, _, _} -> {invalid_creds, {User, Pass}};
+ {true, false, _, _} -> {invalid_creds, {User, Pass}};
%% rabbitmq_mqtt.ssl_cert_login is true. SSL user name provided.
%% Authenticating using username only.
- {false, false, true, _} -> {SSLLoginName, none};
+ {false, false, true, _} -> {SSLLoginName, none};
%% Anonymous connection uses default credentials
{false, false, false, true} -> {DefaultUser, DefaultPass};
- _ -> nocreds
+ _ -> nocreds
end.
supported_sub_qos(?QOS_0) -> ?QOS_0;
@@ -1267,10 +1011,8 @@ ensure_queue(QoS, State = #state{auth_state = #auth_state{user = #user{username
{ok, Q};
{error, {resource_locked, Q}} ->
QName = amqqueue:get_name(Q),
- ?LOG_DEBUG(
- "MQTT deleting exclusive ~s owned by ~p",
- [rabbit_misc:rs(QName), ?amqqueue_v2_field_exclusive_owner(Q)]
- ),
+ ?LOG_DEBUG("MQTT deleting exclusive ~s owned by ~p",
+ [rabbit_misc:rs(QName), ?amqqueue_v2_field_exclusive_owner(Q)]),
delete_queue(QName, Username),
create_queue(QoS, State);
{error, not_found} ->
@@ -1278,18 +1020,14 @@ ensure_queue(QoS, State = #state{auth_state = #auth_state{user = #user{username
end.
create_queue(
- QoS, #state{
- cfg = #cfg{
- client_id = ClientId,
- clean_sess = CleanSess
- },
- auth_state = #auth_state{
- vhost = VHost,
- user = User = #user{username = Username},
- authz_ctx = AuthzCtx
- }
- }
-) ->
+ QoS, #state{cfg = #cfg{
+ client_id = ClientId,
+ clean_sess = CleanSess},
+ auth_state = #auth_state{
+ vhost = VHost,
+ user = User = #user{username = Username},
+ authz_ctx = AuthzCtx}
+ }) ->
QNameBin = rabbit_mqtt_util:queue_name_bin(ClientId, QoS),
QName = rabbit_misc:r(VHost, queue, QNameBin),
%% configure access to queue required for queue.declare
@@ -1299,34 +1037,29 @@ create_queue(
false ->
rabbit_core_metrics:queue_declared(QName),
QArgs = queue_args(QoS, CleanSess),
- Q0 = amqqueue:new(
- QName,
- self(),
- _Durable = true,
- _AutoDelete = false,
- queue_owner(CleanSess),
- QArgs,
- VHost,
- #{user => Username},
- queue_type(QoS, CleanSess, QArgs)
- ),
+ Q0 = amqqueue:new(QName,
+ self(),
+ _Durable = true,
+ _AutoDelete = false,
+ queue_owner(CleanSess),
+ QArgs,
+ VHost,
+ #{user => Username},
+ queue_type(QoS, CleanSess, QArgs)
+ ),
case rabbit_queue_type:declare(Q0, node()) of
{new, Q} when ?is_amqqueue(Q) ->
rabbit_core_metrics:queue_created(QName),
{ok, Q};
Other ->
- ?LOG_ERROR(
- "Failed to declare ~s: ~p",
- [rabbit_misc:rs(QName), Other]
- ),
+ ?LOG_ERROR("Failed to declare ~s: ~p",
+ [rabbit_misc:rs(QName), Other]),
{error, queue_declare}
end;
{true, Limit} ->
- ?LOG_ERROR(
- "cannot declare ~s because "
- "queue limit ~p in vhost '~s' is reached",
- [rabbit_misc:rs(QName), Limit, VHost]
- ),
+ ?LOG_ERROR("cannot declare ~s because "
+ "queue limit ~p in vhost '~s' is reached",
+ [rabbit_misc:rs(QName), Limit, VHost]),
{error, access_refused}
end;
{error, access_refused} = E ->
@@ -1343,13 +1076,12 @@ queue_owner(false) ->
none.
queue_args(QoS, false) ->
- Args =
- case rabbit_mqtt_util:env(subscription_ttl) of
- Ms when is_integer(Ms) ->
- [{<<"x-expires">>, long, Ms}];
- _ ->
- []
- end,
+ Args = case rabbit_mqtt_util:env(subscription_ttl) of
+ Ms when is_integer(Ms) ->
+ [{<<"x-expires">>, long, Ms}];
+ _ ->
+ []
+ end,
case {QoS, rabbit_mqtt_util:env(durable_queue_type)} of
{?QOS_1, quorum} ->
[{<<"x-queue-type">>, longstr, <<"quorum">>} | Args];
@@ -1369,18 +1101,13 @@ queue_type(?QOS_0, true, QArgs) ->
queue_type(_, _, QArgs) ->
rabbit_amqqueue:get_queue_type(QArgs).
-consume(
- Q,
- QoS,
- #state{
- queue_states = QStates0,
- cfg = #cfg{prefetch = Prefetch},
- auth_state = #auth_state{
- authz_ctx = AuthzCtx,
- user = User = #user{username = Username}
- }
- } = State0
-) ->
+consume(Q, QoS, #state{
+ queue_states = QStates0,
+ cfg = #cfg{prefetch = Prefetch},
+ auth_state = #auth_state{
+ authz_ctx = AuthzCtx,
+ user = User = #user{username = Username}}
+ } = State0) ->
QName = amqqueue:get_name(Q),
%% read access to queue required for basic.consume
case check_resource_access(User, QName, read, AuthzCtx) of
@@ -1391,35 +1118,30 @@ consume(
%% explicitly calling rabbit_queue_type:consume/3.
{ok, State0};
_ ->
- Spec = #{
- no_ack => QoS =:= ?QOS_0,
- channel_pid => self(),
- limiter_pid => none,
- limiter_active => false,
- prefetch_count => Prefetch,
- consumer_tag => ?CONSUMER_TAG,
- exclusive_consume => false,
- args => [],
- ok_msg => undefined,
- acting_user => Username
- },
+ Spec = #{no_ack => QoS =:= ?QOS_0,
+ channel_pid => self(),
+ limiter_pid => none,
+ limiter_active => false,
+ prefetch_count => Prefetch,
+ consumer_tag => ?CONSUMER_TAG,
+ exclusive_consume => false,
+ args => [],
+ ok_msg => undefined,
+ acting_user => Username},
rabbit_amqqueue:with(
- QName,
- fun(Q1) ->
- case rabbit_queue_type:consume(Q1, Spec, QStates0) of
- {ok, QStates} ->
- State1 = State0#state{queue_states = QStates},
- State = maybe_set_queue_qos1(QoS, State1),
- {ok, State};
- {error, Reason} = Err ->
- ?LOG_ERROR(
- "Failed to consume from ~s: ~p",
- [rabbit_misc:rs(QName), Reason]
- ),
- Err
- end
- end
- )
+ QName,
+ fun(Q1) ->
+ case rabbit_queue_type:consume(Q1, Spec, QStates0) of
+ {ok, QStates} ->
+ State1 = State0#state{queue_states = QStates},
+ State = maybe_set_queue_qos1(QoS, State1),
+ {ok, State};
+ {error, Reason} = Err ->
+ ?LOG_ERROR("Failed to consume from ~s: ~p",
+ [rabbit_misc:rs(QName), Reason]),
+ Err
+ end
+ end)
end;
{error, access_refused} = Err ->
Err
@@ -1441,37 +1163,25 @@ binding_action_with_checks(Input, State) ->
%% Same permission checks required for both binding and unbinding
%% queue to / from topic exchange.
rabbit_misc:pipeline(
- [
- fun check_queue_write_access/2,
- fun check_exchange_read_access/2,
- fun check_topic_access/2,
- fun binding_action/2
- ],
- Input,
- State
- ).
+ [fun check_queue_write_access/2,
+ fun check_exchange_read_access/2,
+ fun check_topic_access/2,
+ fun binding_action/2],
+ Input, State).
check_queue_write_access(
- {QueueName, _, _},
- #state{
- auth_state = #auth_state{
- user = User,
- authz_ctx = AuthzCtx
- }
- }
-) ->
+ {QueueName, _, _},
+ #state{auth_state = #auth_state{
+ user = User,
+ authz_ctx = AuthzCtx}}) ->
%% write access to queue required for queue.(un)bind
check_resource_access(User, QueueName, write, AuthzCtx).
check_exchange_read_access(
- _, #state{
- cfg = #cfg{exchange = ExchangeName},
- auth_state = #auth_state{
- user = User,
- authz_ctx = AuthzCtx
- }
- }
-) ->
+ _, #state{cfg = #cfg{exchange = ExchangeName},
+ auth_state = #auth_state{
+ user = User,
+ authz_ctx = AuthzCtx}}) ->
%% read access to exchange required for queue.(un)bind
check_resource_access(User, ExchangeName, read, AuthzCtx).
@@ -1479,72 +1189,57 @@ check_topic_access({_, TopicName, _}, State) ->
check_topic_access(TopicName, read, State).
binding_action(
- {QueueName, TopicName, BindingFun},
- #state{
- cfg = #cfg{exchange = ExchangeName},
- auth_state = #auth_state{user = #user{username = Username}}
- }
-) ->
+ {QueueName, TopicName, BindingFun},
+ #state{cfg = #cfg{exchange = ExchangeName},
+ auth_state = #auth_state{user = #user{username = Username}}}) ->
RoutingKey = mqtt_to_amqp(TopicName),
- Binding = #binding{
- source = ExchangeName,
- destination = QueueName,
- key = RoutingKey
- },
+ Binding = #binding{source = ExchangeName,
+ destination = QueueName,
+ key = RoutingKey},
BindingFun(Binding, Username).
publish_to_queues(
- #mqtt_msg{
- qos = Qos,
- topic = Topic,
- dup = Dup,
- packet_id = PacketId,
- payload = Payload
- },
- #state{
- cfg = #cfg{
- exchange = ExchangeName,
- delivery_flow = Flow,
- conn_name = ConnName,
- trace_state = TraceState
- },
- auth_state = #auth_state{username = Username}
- } = State
-) ->
+ #mqtt_msg{qos = Qos,
+ topic = Topic,
+ dup = Dup,
+ packet_id = PacketId,
+ payload = Payload},
+ #state{cfg = #cfg{exchange = ExchangeName,
+ delivery_flow = Flow,
+ conn_name = ConnName,
+ trace_state = TraceState},
+ auth_state = #auth_state{username = Username}
+ } = State) ->
RoutingKey = mqtt_to_amqp(Topic),
Confirm = Qos > ?QOS_0,
- Headers = [
- {<<"x-mqtt-publish-qos">>, byte, Qos},
- {<<"x-mqtt-dup">>, bool, Dup}
- ],
+ Headers = [{<<"x-mqtt-publish-qos">>, byte, Qos},
+ {<<"x-mqtt-dup">>, bool, Dup}],
Props = #'P_basic'{
- headers = Headers,
- delivery_mode = delivery_mode(Qos)
- },
+ headers = Headers,
+ delivery_mode = delivery_mode(Qos)},
{ClassId, _MethodId} = rabbit_framing_amqp_0_9_1:method_id('basic.publish'),
Content = #content{
- class_id = ClassId,
- properties = Props,
- properties_bin = none,
- protocol = none,
- payload_fragments_rev = [Payload]
- },
+ class_id = ClassId,
+ properties = Props,
+ properties_bin = none,
+ protocol = none,
+ payload_fragments_rev = [Payload]
+ },
BasicMessage = #basic_message{
- exchange_name = ExchangeName,
- routing_keys = [RoutingKey],
- content = Content,
- %% GUID set in rabbit_classic_queue
- id = <<>>,
- is_persistent = Confirm
- },
+ exchange_name = ExchangeName,
+ routing_keys = [RoutingKey],
+ content = Content,
+ id = <<>>, %% GUID set in rabbit_classic_queue
+ is_persistent = Confirm
+ },
Delivery = #delivery{
- mandatory = false,
- confirm = Confirm,
- sender = self(),
- message = BasicMessage,
- msg_seq_no = PacketId,
- flow = Flow
- },
+ mandatory = false,
+ confirm = Confirm,
+ sender = self(),
+ message = BasicMessage,
+ msg_seq_no = PacketId,
+ flow = Flow
+ },
case rabbit_exchange:lookup(ExchangeName) of
{ok, Exchange} ->
QNames = rabbit_exchange:route(Exchange, Delivery),
@@ -1555,61 +1250,39 @@ publish_to_queues(
{error, exchange_not_found, State}
end.
-deliver_to_queues(
- Delivery,
- RoutedToQNames,
- State0 = #state{
- queue_states = QStates0,
- cfg = #cfg{proto_ver = ProtoVer}
- }
-) ->
+deliver_to_queues(Delivery,
+ RoutedToQNames,
+ State0 = #state{queue_states = QStates0,
+ cfg = #cfg{proto_ver = ProtoVer}}) ->
Qs0 = rabbit_amqqueue:lookup(RoutedToQNames),
Qs = rabbit_amqqueue:prepend_extra_bcc(Qs0),
case rabbit_queue_type:deliver(Qs, Delivery, QStates0) of
{ok, QStates, Actions} ->
rabbit_global_counters:messages_routed(ProtoVer, length(Qs)),
- State = process_routing_confirm(
- Delivery,
- Qs,
- State0#state{queue_states = QStates}
- ),
+ State = process_routing_confirm(Delivery, Qs,
+ State0#state{queue_states = QStates}),
%% Actions must be processed after registering confirms as actions may
%% contain rejections of publishes.
{ok, handle_queue_actions(Actions, State)};
{error, Reason} ->
- ?LOG_ERROR(
- "Failed to deliver message with packet_id=~p to queues: ~p",
- [Delivery#delivery.msg_seq_no, Reason]
- ),
+ ?LOG_ERROR("Failed to deliver message with packet_id=~p to queues: ~p",
+ [Delivery#delivery.msg_seq_no, Reason]),
{error, Reason, State0}
end.
-process_routing_confirm(
- #delivery{confirm = false},
- [],
- State = #state{cfg = #cfg{proto_ver = ProtoVer}}
-) ->
+process_routing_confirm(#delivery{confirm = false},
+ [], State = #state{cfg = #cfg{proto_ver = ProtoVer}}) ->
rabbit_global_counters:messages_unroutable_dropped(ProtoVer, 1),
State;
-process_routing_confirm(
- #delivery{
- confirm = true,
- msg_seq_no = undefined
- },
- [],
- State = #state{cfg = #cfg{proto_ver = ProtoVer}}
-) ->
+process_routing_confirm(#delivery{confirm = true,
+ msg_seq_no = undefined},
+ [], State = #state{cfg = #cfg{proto_ver = ProtoVer}}) ->
%% unroutable will message with QoS > 0
rabbit_global_counters:messages_unroutable_dropped(ProtoVer, 1),
State;
-process_routing_confirm(
- #delivery{
- confirm = true,
- msg_seq_no = PktId
- },
- [],
- State = #state{cfg = #cfg{proto_ver = ProtoVer}}
-) ->
+process_routing_confirm(#delivery{confirm = true,
+ msg_seq_no = PktId},
+ [], State = #state{cfg = #cfg{proto_ver = ProtoVer}}) ->
rabbit_global_counters:messages_unroutable_returned(ProtoVer, 1),
%% MQTT 5 spec:
%% If the Server knows that there are no matching subscribers, it MAY use
@@ -1618,75 +1291,42 @@ process_routing_confirm(
State;
process_routing_confirm(#delivery{confirm = false}, _, State) ->
State;
-process_routing_confirm(
- #delivery{
- confirm = true,
- msg_seq_no = undefined
- },
- [_ | _],
- State
-) ->
+process_routing_confirm(#delivery{confirm = true,
+ msg_seq_no = undefined}, [_|_], State) ->
%% routable will message with QoS > 0
State;
-process_routing_confirm(
- #delivery{
- confirm = true,
- msg_seq_no = PktId
- },
- Qs,
- State = #state{unacked_client_pubs = U0}
-) ->
+process_routing_confirm(#delivery{confirm = true,
+ msg_seq_no = PktId},
+ Qs, State = #state{unacked_client_pubs = U0}) ->
QNames = lists:map(fun amqqueue:get_name/1, Qs),
U = rabbit_mqtt_confirms:insert(PktId, QNames, U0),
State#state{unacked_client_pubs = U}.
-send_puback(PktIds0, State) when
- is_list(PktIds0)
-->
+send_puback(PktIds0, State)
+ when is_list(PktIds0) ->
%% Classic queues confirm messages unordered.
%% Let's sort them here assuming most MQTT clients send with an increasing packet identifier.
PktIds = lists:usort(PktIds0),
- lists:foreach(
- fun(Id) ->
- send_puback(Id, State)
- end,
- PktIds
- );
-send_puback(
- PktId,
- State = #state{
- cfg = #cfg{
- send_fun = SendFun,
- proto_ver = ProtoVer
- }
- }
-) ->
+ lists:foreach(fun(Id) ->
+ send_puback(Id, State)
+ end, PktIds);
+send_puback(PktId, State = #state{cfg = #cfg{send_fun = SendFun,
+ proto_ver = ProtoVer}}) ->
rabbit_global_counters:messages_confirmed(ProtoVer, 1),
SendFun(
- #mqtt_packet{
- fixed = #mqtt_packet_fixed{type = ?PUBACK},
- variable = #mqtt_packet_publish{packet_id = PktId}
- },
- State
- ).
-
-serialise_and_send_to_client(Packet, #state{
- cfg = #cfg{
- proto_ver = ProtoVer,
- socket = Sock
- }
-}) ->
+ #mqtt_packet{fixed = #mqtt_packet_fixed{type = ?PUBACK},
+ variable = #mqtt_packet_publish{packet_id = PktId}},
+ State).
+
+serialise_and_send_to_client(Packet, #state{cfg = #cfg{proto_ver = ProtoVer,
+ socket = Sock}}) ->
Data = rabbit_mqtt_packet:serialise(Packet, ProtoVer),
- try
- rabbit_net:port_command(Sock, Data)
- catch
- error:Error ->
- ?LOG_ERROR("MQTT: a socket write failed: ~p", [Error]),
- ?LOG_DEBUG(
- "MQTT failed to write to socket ~p, error: ~p, "
- "fixed packet header: ~p, variable packet header: ~p",
- [Sock, Error, Packet#mqtt_packet.fixed, Packet#mqtt_packet.variable]
- )
+ try rabbit_net:port_command(Sock, Data)
+ catch error:Error ->
+ ?LOG_ERROR("MQTT: a socket write failed: ~p", [Error]),
+ ?LOG_DEBUG("MQTT failed to write to socket ~p, error: ~p, "
+ "fixed packet header: ~p, variable packet header: ~p",
+ [Sock, Error, Packet#mqtt_packet.fixed, Packet#mqtt_packet.variable])
end.
-spec serialise(#mqtt_packet{}, state()) ->
@@ -1698,13 +1338,11 @@ serialise(Packet, #state{cfg = #cfg{proto_ver = ProtoVer}}) ->
ok.
terminate(SendWill, ConnName, ProtoFamily, State) ->
maybe_send_will(SendWill, ConnName, State),
- Infos =
- [
- {name, ConnName},
- {node, node()},
- {pid, self()},
- {disconnected_at, os:system_time(milli_seconds)}
- ] ++ additional_connection_closed_info(ProtoFamily, State),
+ Infos = [{name, ConnName},
+ {node, node()},
+ {pid, self()},
+ {disconnected_at, os:system_time(milli_seconds)}
+ ] ++ additional_connection_closed_info(ProtoFamily, State),
rabbit_core_metrics:connection_closed(self()),
rabbit_event:notify(connection_closed, Infos),
rabbit_networking:unregister_non_amqp_connection(self()),
@@ -1714,23 +1352,13 @@ terminate(SendWill, ConnName, ProtoFamily, State) ->
maybe_delete_mqtt_qos0_queue(State).
maybe_send_will(
- true,
- ConnStr,
- #state{
- cfg = #cfg{
- retainer_pid = RPid,
- will_msg =
- WillMsg = #mqtt_msg{
- retain = Retain,
- topic = Topic
- }
- }
- } = State
-) ->
- ?LOG_DEBUG(
- "sending MQTT will message to topic ~s on connection ~s",
- [Topic, ConnStr]
- ),
+ true, ConnStr,
+ #state{cfg = #cfg{retainer_pid = RPid,
+ will_msg = WillMsg = #mqtt_msg{retain = Retain,
+ topic = Topic}}
+ } = State) ->
+ ?LOG_DEBUG("sending MQTT will message to topic ~s on connection ~s",
+ [Topic, ConnStr]),
case check_topic_access(Topic, write, State) of
ok ->
_ = publish_to_queues(WillMsg, State),
@@ -1740,32 +1368,24 @@ maybe_send_will(
true ->
hand_off_to_retainer(RPid, Topic, WillMsg)
end;
- {error, access_refused = Reason} ->
+ {error, access_refused = Reason} ->
?LOG_ERROR("failed to send will message: ~p", [Reason])
end;
maybe_send_will(_, _, _) ->
ok.
additional_connection_closed_info(
- ProtoFamily,
- State = #state{
- auth_state = #auth_state{
- vhost = VHost,
- username = Username
- }
- }
-) ->
- [
- {protocol, {ProtoFamily, proto_version_tuple(State)}},
- {vhost, VHost},
- {user, Username}
- ];
+ ProtoFamily,
+ State = #state{auth_state = #auth_state{vhost = VHost,
+ username = Username}}) ->
+ [{protocol, {ProtoFamily, proto_version_tuple(State)}},
+ {vhost, VHost},
+ {user, Username}];
additional_connection_closed_info(_, _) ->
[].
-maybe_unregister_client(#state{cfg = #cfg{client_id = ClientId}}) when
- ClientId =/= undefined
-->
+maybe_unregister_client(#state{cfg = #cfg{client_id = ClientId}})
+ when ClientId =/= undefined ->
case rabbit_mqtt_ff:track_client_id_in_ra() of
true ->
%% ignore any errors as we are shutting down
@@ -1777,18 +1397,14 @@ maybe_unregister_client(_) ->
ok.
maybe_delete_mqtt_qos0_queue(
- State = #state{
- cfg = #cfg{clean_sess = true},
- auth_state = #auth_state{username = Username}
- }
-) ->
+ State = #state{cfg = #cfg{clean_sess = true},
+ auth_state = #auth_state{username = Username}}) ->
case get_queue(?QOS_0, State) of
{ok, Q} ->
%% double check we delete the right queue
case {amqqueue:get_type(Q), amqqueue:get_pid(Q)} of
- {?QUEUE_TYPE_QOS_0, Pid} when
- Pid =:= self()
- ->
+ {?QUEUE_TYPE_QOS_0, Pid}
+ when Pid =:= self() ->
rabbit_queue_type:delete(Q, false, false, Username);
_ ->
ok
@@ -1801,21 +1417,19 @@ maybe_delete_mqtt_qos0_queue(_) ->
delete_queue(QName, Username) ->
rabbit_amqqueue:with(
- QName,
- fun(Q) ->
- rabbit_queue_type:delete(Q, false, false, Username)
- end,
- fun
- (not_found) ->
- ok;
- ({absent, Q, crashed}) ->
- rabbit_classic_queue:delete_crashed(Q, Username);
- ({absent, Q, stopped}) ->
- rabbit_classic_queue:delete_crashed(Q, Username);
- ({absent, _Q, _Reason}) ->
- ok
- end
- ).
+ QName,
+ fun (Q) ->
+ rabbit_queue_type:delete(Q, false, false, Username)
+ end,
+ fun (not_found) ->
+ ok;
+ ({absent, Q, crashed}) ->
+ rabbit_classic_queue:delete_crashed(Q, Username);
+ ({absent, Q, stopped}) ->
+ rabbit_classic_queue:delete_crashed(Q, Username);
+ ({absent, _Q, _Reason}) ->
+ ok
+ end).
-spec handle_pre_hibernate() -> ok.
handle_pre_hibernate() ->
@@ -1823,25 +1437,16 @@ handle_pre_hibernate() ->
erase(topic_permission_cache),
ok.
--spec handle_ra_event(
- register_timeout
- | {applied, [{reference(), ok}]}
- | {not_leader, term(), reference()},
- state()
-) -> state().
-handle_ra_event(
- {applied, [{Corr, ok}]},
- State = #state{register_state = {pending, Corr}}
-) ->
+-spec handle_ra_event(register_timeout
+| {applied, [{reference(), ok}]}
+| {not_leader, term(), reference()}, state()) -> state().
+handle_ra_event({applied, [{Corr, ok}]},
+ State = #state{register_state = {pending, Corr}}) ->
%% success case - command was applied transition into registered state
State#state{register_state = registered};
-handle_ra_event(
- {not_leader, Leader, Corr},
- State = #state{
- register_state = {pending, Corr},
- cfg = #cfg{client_id = ClientId}
- }
-) ->
+handle_ra_event({not_leader, Leader, Corr},
+ State = #state{register_state = {pending, Corr},
+ cfg = #cfg{client_id = ClientId}}) ->
case rabbit_mqtt_ff:track_client_id_in_ra() of
true ->
%% retry command against actual leader
@@ -1850,13 +1455,9 @@ handle_ra_event(
false ->
State
end;
-handle_ra_event(
- register_timeout,
- State = #state{
- register_state = {pending, _Corr},
- cfg = #cfg{client_id = ClientId}
- }
-) ->
+handle_ra_event(register_timeout,
+ State = #state{register_state = {pending, _Corr},
+ cfg = #cfg{client_id = ClientId}}) ->
case rabbit_mqtt_ff:track_client_id_in_ra() of
true ->
{ok, NewCorr} = rabbit_mqtt_collector:register(ClientId, self()),
@@ -1872,13 +1473,9 @@ handle_ra_event(Evt, State) ->
-spec handle_down(term(), state()) ->
{ok, state()} | {error, Reason :: any()}.
-handle_down(
- {{'DOWN', QName}, _MRef, process, QPid, Reason},
- State0 = #state{
- queue_states = QStates0,
- unacked_client_pubs = U0
- }
-) ->
+handle_down({{'DOWN', QName}, _MRef, process, QPid, Reason},
+ State0 = #state{queue_states = QStates0,
+ unacked_client_pubs = U0}) ->
credit_flow:peer_down(QPid),
case rabbit_queue_type:handle_down(QPid, QName, Reason, QStates0) of
{ok, QStates1, Actions} ->
@@ -1886,44 +1483,33 @@ handle_down(
try handle_queue_actions(Actions, State1) of
State ->
{ok, State}
- catch
- throw:consuming_queue_down ->
- {error, consuming_queue_down}
+ catch throw:consuming_queue_down ->
+ {error, consuming_queue_down}
end;
{eol, QStates1, QRef} ->
{ConfirmPktIds, U} = rabbit_mqtt_confirms:remove_queue(QRef, U0),
QStates = rabbit_queue_type:remove(QRef, QStates1),
- State = State0#state{
- queue_states = QStates,
- unacked_client_pubs = U
- },
+ State = State0#state{queue_states = QStates,
+ unacked_client_pubs = U},
send_puback(ConfirmPktIds, State),
{ok, State}
end.
-spec handle_queue_event(
- {queue_event, rabbit_amqqueue:name() | ?QUEUE_TYPE_QOS_0, term()}, state()
-) ->
+ {queue_event, rabbit_amqqueue:name() | ?QUEUE_TYPE_QOS_0, term()}, state()) ->
{ok, state()} | {error, Reason :: any(), state()}.
-handle_queue_event(
- {queue_event, ?QUEUE_TYPE_QOS_0, Msg},
- State0 = #state{qos0_messages_dropped = N}
-) ->
- State =
- case drop_qos0_message(State0) of
- false ->
- deliver_one_to_client(Msg, false, State0);
- true ->
- State0#state{qos0_messages_dropped = N + 1}
- end,
+handle_queue_event({queue_event, ?QUEUE_TYPE_QOS_0, Msg},
+ State0 = #state{qos0_messages_dropped = N}) ->
+ State = case drop_qos0_message(State0) of
+ false ->
+ deliver_one_to_client(Msg, false, State0);
+ true ->
+ State0#state{qos0_messages_dropped = N + 1}
+ end,
{ok, State};
-handle_queue_event(
- {queue_event, QName, Evt},
- State0 = #state{
- queue_states = QStates0,
- unacked_client_pubs = U0
- }
-) ->
+handle_queue_event({queue_event, QName, Evt},
+ State0 = #state{queue_states = QStates0,
+ unacked_client_pubs = U0}) ->
case rabbit_queue_type:handle_event(QName, Evt, QStates0) of
{ok, QStates, Actions} ->
State1 = State0#state{queue_states = QStates},
@@ -1933,10 +1519,8 @@ handle_queue_event(
State1 = handle_queue_actions(Actions, State0),
{ConfirmPktIds, U} = rabbit_mqtt_confirms:remove_queue(QName, U0),
QStates = rabbit_queue_type:remove(QName, QStates0),
- State = State1#state{
- queue_states = QStates,
- unacked_client_pubs = U
- },
+ State = State1#state{queue_states = QStates,
+ unacked_client_pubs = U},
send_puback(ConfirmPktIds, State),
{ok, State};
{protocol_error, _Type, _Reason, _ReasonArgs} = Error ->
@@ -1945,37 +1529,30 @@ handle_queue_event(
handle_queue_actions(Actions, #state{} = State0) ->
lists:foldl(
- fun
- ({deliver, ?CONSUMER_TAG, Ack, Msgs}, S) ->
- deliver_to_client(Msgs, Ack, S);
- ({settled, QName, PktIds}, S = #state{unacked_client_pubs = U0}) ->
- {ConfirmPktIds, U} = rabbit_mqtt_confirms:confirm(PktIds, QName, U0),
- send_puback(ConfirmPktIds, S),
- S#state{unacked_client_pubs = U};
- ({rejected, _QName, PktIds}, S = #state{unacked_client_pubs = U0}) ->
- %% Negative acks are supported in MQTT v5 only.
- %% Therefore, in MQTT v3 and v4 we ignore rejected messages.
- U = lists:foldl(
+ fun ({deliver, ?CONSUMER_TAG, Ack, Msgs}, S) ->
+ deliver_to_client(Msgs, Ack, S);
+ ({settled, QName, PktIds}, S = #state{unacked_client_pubs = U0}) ->
+ {ConfirmPktIds, U} = rabbit_mqtt_confirms:confirm(PktIds, QName, U0),
+ send_puback(ConfirmPktIds, S),
+ S#state{unacked_client_pubs = U};
+ ({rejected, _QName, PktIds}, S = #state{unacked_client_pubs = U0}) ->
+ %% Negative acks are supported in MQTT v5 only.
+ %% Therefore, in MQTT v3 and v4 we ignore rejected messages.
+ U = lists:foldl(
fun(PktId, Acc0) ->
- case rabbit_mqtt_confirms:reject(PktId, Acc0) of
- {ok, Acc} -> Acc;
- {error, not_found} -> Acc0
- end
- end,
- U0,
- PktIds
- ),
- S#state{unacked_client_pubs = U};
- ({block, QName}, S = #state{queues_soft_limit_exceeded = QSLE}) ->
- S#state{queues_soft_limit_exceeded = sets:add_element(QName, QSLE)};
- ({unblock, QName}, S = #state{queues_soft_limit_exceeded = QSLE}) ->
- S#state{queues_soft_limit_exceeded = sets:del_element(QName, QSLE)};
- ({queue_down, QName}, S) ->
- handle_queue_down(QName, S)
- end,
- State0,
- Actions
- ).
+ case rabbit_mqtt_confirms:reject(PktId, Acc0) of
+ {ok, Acc} -> Acc;
+ {error, not_found} -> Acc0
+ end
+ end, U0, PktIds),
+ S#state{unacked_client_pubs = U};
+ ({block, QName}, S = #state{queues_soft_limit_exceeded = QSLE}) ->
+ S#state{queues_soft_limit_exceeded = sets:add_element(QName, QSLE)};
+ ({unblock, QName}, S = #state{queues_soft_limit_exceeded = QSLE}) ->
+ S#state{queues_soft_limit_exceeded = sets:del_element(QName, QSLE)};
+ ({queue_down, QName}, S) ->
+ handle_queue_down(QName, S)
+ end, State0, Actions).
handle_queue_down(QName, State0 = #state{cfg = #cfg{client_id = ClientId}}) ->
%% Classic queue is down.
@@ -1991,10 +1568,8 @@ handle_queue_down(QName, State0 = #state{cfg = #cfg{client_id = ClientId}}) ->
{ok, State} ->
State;
{error, _Reason} ->
- ?LOG_INFO(
- "Terminating MQTT connection because consuming ~s is down.",
- [rabbit_misc:rs(QName)]
- ),
+ ?LOG_INFO("Terminating MQTT connection because consuming ~s is down.",
+ [rabbit_misc:rs(QName)]),
throw(consuming_queue_down)
end
end;
@@ -2003,37 +1578,26 @@ handle_queue_down(QName, State0 = #state{cfg = #cfg{client_id = ClientId}}) ->
end.
deliver_to_client(Msgs, Ack, State) ->
- lists:foldl(
- fun(Msg, S) ->
- deliver_one_to_client(Msg, Ack, S)
- end,
- State,
- Msgs
- ).
-
-deliver_one_to_client(
- Msg =
- {QNameOrType, QPid, QMsgId, _Redelivered, #basic_message{
- content = #content{properties = #'P_basic'{headers = Headers}}
- }},
- AckRequired,
- State0
-) ->
- PublisherQoS =
- case rabbit_mqtt_util:table_lookup(Headers, <<"x-mqtt-publish-qos">>) of
- {byte, QoS0} ->
- QoS0;
- undefined ->
- %% non-MQTT publishes are assumed to be QoS 1 regardless of delivery_mode
- ?QOS_1
- end,
- SubscriberQoS =
- case AckRequired of
- true ->
- ?QOS_1;
- false ->
- ?QOS_0
- end,
+ lists:foldl(fun(Msg, S) ->
+ deliver_one_to_client(Msg, Ack, S)
+ end, State, Msgs).
+
+deliver_one_to_client(Msg = {QNameOrType, QPid, QMsgId, _Redelivered,
+ #basic_message{content = #content{properties = #'P_basic'{headers = Headers}}}},
+ AckRequired, State0) ->
+ PublisherQoS = case rabbit_mqtt_util:table_lookup(Headers, <<"x-mqtt-publish-qos">>) of
+ {byte, QoS0} ->
+ QoS0;
+ undefined ->
+ %% non-MQTT publishes are assumed to be QoS 1 regardless of delivery_mode
+ ?QOS_1
+ end,
+ SubscriberQoS = case AckRequired of
+ true ->
+ ?QOS_1;
+ false ->
+ ?QOS_0
+ end,
QoS = effective_qos(PublisherQoS, SubscriberQoS),
State1 = maybe_publish_to_client(Msg, QoS, State0),
State = maybe_auto_ack(AckRequired, QoS, QNameOrType, QMsgId, State1),
@@ -2051,33 +1615,28 @@ maybe_publish_to_client({_, _, _, _Redelivered = true, _}, ?QOS_0, State) ->
%% Do not redeliver to MQTT subscriber who gets message at most once.
State;
maybe_publish_to_client(
- {QNameOrType, _QPid, QMsgId, Redelivered, #basic_message{
- routing_keys = [RoutingKey | _CcRoutes],
- content = #content{payload_fragments_rev = FragmentsRev}
- }} = Msg,
- QoS,
- State0 = #state{cfg = #cfg{send_fun = SendFun}}
-) ->
+ {QNameOrType, _QPid, QMsgId, Redelivered,
+ #basic_message{
+ routing_keys = [RoutingKey | _CcRoutes],
+ content = #content{payload_fragments_rev = FragmentsRev}}} = Msg,
+ QoS, State0 = #state{cfg = #cfg{send_fun = SendFun}}) ->
{PacketId, State} = msg_id_to_packet_id(QMsgId, QoS, State0),
Packet =
- #mqtt_packet{
- fixed = #mqtt_packet_fixed{
- type = ?PUBLISH,
- qos = QoS,
- %% "The value of the DUP flag from an incoming PUBLISH packet is not
- %% propagated when the PUBLISH Packet is sent to subscribers by the Server.
- %% The DUP flag in the outgoing PUBLISH packet is set independently to the
- %% incoming PUBLISH packet, its value MUST be determined solely by whether
- %% the outgoing PUBLISH packet is a retransmission [MQTT-3.3.1-3]."
- %% Therefore, we do not consider header value <<"x-mqtt-dup">> here.
- dup = Redelivered
- },
- variable = #mqtt_packet_publish{
- packet_id = PacketId,
- topic_name = amqp_to_mqtt(RoutingKey)
- },
- payload = lists:reverse(FragmentsRev)
- },
+ #mqtt_packet{
+ fixed = #mqtt_packet_fixed{
+ type = ?PUBLISH,
+ qos = QoS,
+ %% "The value of the DUP flag from an incoming PUBLISH packet is not
+ %% propagated when the PUBLISH Packet is sent to subscribers by the Server.
+ %% The DUP flag in the outgoing PUBLISH packet is set independently to the
+ %% incoming PUBLISH packet, its value MUST be determined solely by whether
+ %% the outgoing PUBLISH packet is a retransmission [MQTT-3.3.1-3]."
+ %% Therefore, we do not consider header value <<"x-mqtt-dup">> here.
+ dup = Redelivered},
+ variable = #mqtt_packet_publish{
+ packet_id = PacketId,
+ topic_name = amqp_to_mqtt(RoutingKey)},
+ payload = lists:reverse(FragmentsRev)},
SendFun(Packet, State),
trace_tap_out(Msg, State),
message_delivered(QNameOrType, Redelivered, QoS, State),
@@ -2086,37 +1645,21 @@ maybe_publish_to_client(
msg_id_to_packet_id(_, ?QOS_0, State) ->
%% "A PUBLISH packet MUST NOT contain a Packet Identifier if its QoS value is set to 0 [MQTT-2.2.1-2]."
{undefined, State};
-msg_id_to_packet_id(
- QMsgId,
- ?QOS_1,
- #state{
- packet_id = PktId,
- unacked_server_pubs = U
- } = State
-) ->
- {PktId, State#state{
- packet_id = increment_packet_id(PktId),
- unacked_server_pubs = maps:put(PktId, QMsgId, U)
- }}.
+msg_id_to_packet_id(QMsgId, ?QOS_1, #state{packet_id = PktId,
+ unacked_server_pubs = U} = State) ->
+ {PktId, State#state{packet_id = increment_packet_id(PktId),
+ unacked_server_pubs = maps:put(PktId, QMsgId, U)}}.
-spec increment_packet_id(packet_id()) -> packet_id().
-increment_packet_id(Id) when
- Id >= 16#ffff
-->
+increment_packet_id(Id)
+ when Id >= 16#ffff ->
1;
increment_packet_id(Id) ->
Id + 1.
-maybe_auto_ack(
- _AckRequired = true,
- ?QOS_0,
- QName,
- QMsgId,
- State = #state{queue_states = QStates0}
-) ->
- {ok, QStates, Actions} = rabbit_queue_type:settle(
- QName, complete, ?CONSUMER_TAG, [QMsgId], QStates0
- ),
+maybe_auto_ack(_AckRequired = true, ?QOS_0, QName, QMsgId,
+ State = #state{queue_states = QStates0}) ->
+ {ok, QStates, Actions} = rabbit_queue_type:settle(QName, complete, ?CONSUMER_TAG, [QMsgId], QStates0),
handle_queue_actions(Actions, State#state{queue_states = QStates});
maybe_auto_ack(_, _, _, _, State) ->
State.
@@ -2131,21 +1674,13 @@ maybe_notify_sent(QName, QPid, #state{queue_states = QStates}) ->
ok
end.
-trace_tap_out(
- Msg = {#resource{}, _, _, _, _},
- #state{
- auth_state = #auth_state{username = Username},
- cfg = #cfg{
- conn_name = ConnName,
- trace_state = TraceState
- }
- }
-) ->
+trace_tap_out(Msg = {#resource{}, _, _, _, _},
+ #state{auth_state = #auth_state{username = Username},
+ cfg = #cfg{conn_name = ConnName,
+ trace_state = TraceState}}) ->
rabbit_trace:tap_out(Msg, ConnName, Username, TraceState);
-trace_tap_out(
- Msg0 = {?QUEUE_TYPE_QOS_0, _, _, _, _},
- State = #state{cfg = #cfg{trace_state = TraceState}}
-) ->
+trace_tap_out(Msg0 = {?QUEUE_TYPE_QOS_0, _, _, _, _},
+ State = #state{cfg = #cfg{trace_state = TraceState}}) ->
case rabbit_trace:enabled(TraceState) of
false ->
ok;
@@ -2157,16 +1692,11 @@ trace_tap_out(
end.
publish_to_queues_with_checks(
- TopicName,
- PublishFun,
- #state{
- cfg = #cfg{exchange = Exchange},
- auth_state = #auth_state{
- user = User,
- authz_ctx = AuthzCtx
- }
- } = State
-) ->
+ TopicName, PublishFun,
+ #state{cfg = #cfg{exchange = Exchange},
+ auth_state = #auth_state{user = User,
+ authz_ctx = AuthzCtx}
+ } = State) ->
case check_resource_access(User, Exchange, write, AuthzCtx) of
ok ->
case check_topic_access(TopicName, write, State) of
@@ -2181,75 +1711,57 @@ publish_to_queues_with_checks(
check_resource_access(User, Resource, Perm, Context) ->
V = {Resource, Context, Perm},
- Cache =
- case get(permission_cache) of
- undefined -> [];
- Other -> Other
- end,
+ Cache = case get(permission_cache) of
+ undefined -> [];
+ Other -> Other
+ end,
case lists:member(V, Cache) of
true ->
ok;
false ->
try rabbit_access_control:check_resource_access(User, Resource, Perm, Context) of
ok ->
- CacheTail = lists:sublist(Cache, ?MAX_PERMISSION_CACHE_SIZE - 1),
+ CacheTail = lists:sublist(Cache, ?MAX_PERMISSION_CACHE_SIZE-1),
put(permission_cache, [V | CacheTail]),
ok
catch
- exit:#amqp_error{
- name = access_refused,
- explanation = Msg
- } ->
+ exit:#amqp_error{name = access_refused,
+ explanation = Msg} ->
?LOG_ERROR("MQTT resource access refused: ~s", [Msg]),
{error, access_refused}
end
end.
check_topic_access(
- TopicName,
- Access,
- #state{
- auth_state = #auth_state{
- user = User = #user{username = Username},
- vhost = VHost,
- authz_ctx = AuthzCtx
- },
- cfg = #cfg{
- client_id = ClientId,
- exchange = #resource{name = ExchangeBin}
- }
- }
-) ->
- Cache =
- case get(topic_permission_cache) of
- undefined -> [];
- Other -> Other
- end,
+ TopicName, Access,
+ #state{auth_state = #auth_state{user = User = #user{username = Username},
+ vhost = VHost,
+ authz_ctx = AuthzCtx},
+ cfg = #cfg{client_id = ClientId,
+ exchange = #resource{name = ExchangeBin}}}) ->
+ Cache = case get(topic_permission_cache) of
+ undefined -> [];
+ Other -> Other
+ end,
Key = {TopicName, Username, ClientId, VHost, ExchangeBin, Access},
case lists:member(Key, Cache) of
true ->
ok;
false ->
- Resource = #resource{
- virtual_host = VHost,
- kind = topic,
- name = ExchangeBin
- },
+ Resource = #resource{virtual_host = VHost,
+ kind = topic,
+ name = ExchangeBin},
RoutingKey = mqtt_to_amqp(TopicName),
- Context = #{
- routing_key => RoutingKey,
- variable_map => AuthzCtx
- },
+ Context = #{routing_key => RoutingKey,
+ variable_map => AuthzCtx},
try rabbit_access_control:check_topic_access(User, Resource, Access, Context) of
ok ->
CacheTail = lists:sublist(Cache, ?MAX_PERMISSION_CACHE_SIZE - 1),
put(topic_permission_cache, [Key | CacheTail]),
ok
catch
- exit:#amqp_error{
- name = access_refused,
- explanation = Msg
- } ->
+ exit:#amqp_error{name = access_refused,
+ explanation = Msg} ->
?LOG_ERROR("MQTT topic access refused: ~s", [Msg]),
{error, access_refused}
end
@@ -2259,7 +1771,7 @@ check_topic_access(
boolean().
drop_qos0_message(State) ->
mailbox_soft_limit_exceeded() andalso
- is_socket_busy(State#state.cfg#cfg.socket).
+ is_socket_busy(State#state.cfg#cfg.socket).
-spec mailbox_soft_limit_exceeded() ->
boolean().
@@ -2278,22 +1790,19 @@ mailbox_soft_limit_exceeded() ->
is_socket_busy(Socket) ->
case rabbit_net:getstat(Socket, [send_pend]) of
- {ok, [{send_pend, NumBytes}]} when
- is_number(NumBytes) andalso NumBytes > 0
- ->
+ {ok, [{send_pend, NumBytes}]}
+ when is_number(NumBytes) andalso NumBytes > 0 ->
true;
_ ->
false
end.
-spec throttle(boolean(), boolean(), state()) -> boolean().
-throttle(Conserve, Connected, #state{
- queues_soft_limit_exceeded = QSLE,
- cfg = #cfg{published = Published}
-}) ->
+throttle(Conserve, Connected, #state{queues_soft_limit_exceeded = QSLE,
+ cfg = #cfg{published = Published}}) ->
Conserve andalso (Published orelse not Connected) orelse
- not sets:is_empty(QSLE) orelse
- credit_flow:blocked().
+ not sets:is_empty(QSLE) orelse
+ credit_flow:blocked().
-spec info(rabbit_types:info_key(), state()) -> any().
info(host, #state{cfg = #cfg{host = Val}}) -> Val;
@@ -2303,19 +1812,23 @@ info(peer_port, #state{cfg = #cfg{peer_port = Val}}) -> Val;
info(connected_at, #state{cfg = #cfg{connected_at = Val}}) -> Val;
info(ssl_login_name, #state{cfg = #cfg{ssl_login_name = Val}}) -> Val;
info(vhost, #state{auth_state = #auth_state{vhost = Val}}) -> Val;
-info(user_who_performed_action, S) -> info(user, S);
+info(user_who_performed_action, S) ->
+ info(user, S);
info(user, #state{auth_state = #auth_state{username = Val}}) -> Val;
info(clean_sess, #state{cfg = #cfg{clean_sess = Val}}) -> Val;
info(will_msg, #state{cfg = #cfg{will_msg = Val}}) -> Val;
info(retainer_pid, #state{cfg = #cfg{retainer_pid = Val}}) -> Val;
info(exchange, #state{cfg = #cfg{exchange = #resource{name = Val}}}) -> Val;
info(prefetch, #state{cfg = #cfg{prefetch = Val}}) -> Val;
-info(messages_unconfirmed, #state{unacked_client_pubs = Val}) -> rabbit_mqtt_confirms:size(Val);
-info(messages_unacknowledged, #state{unacked_server_pubs = Val}) -> maps:size(Val);
+info(messages_unconfirmed, #state{unacked_client_pubs = Val}) ->
+ rabbit_mqtt_confirms:size(Val);
+info(messages_unacknowledged, #state{unacked_server_pubs = Val}) ->
+ maps:size(Val);
info(node, _) -> node();
info(client_id, #state{cfg = #cfg{client_id = Val}}) -> Val;
%% for rabbitmq_management/priv/www/js/tmpl/connection.ejs
-info(client_properties, #state{cfg = #cfg{client_id = Val}}) -> [{client_id, longstr, Val}];
+info(client_properties, #state{cfg = #cfg{client_id = Val}}) ->
+ [{client_id, longstr, Val}];
info(channel_max, _) -> 0;
%% Maximum packet size supported only in MQTT 5.0.
info(frame_max, _) -> 0;
@@ -2327,16 +1840,13 @@ info(Other, _) -> throw({bad_argument, Other}).
none | binary().
ssl_login_name(Sock) ->
case rabbit_net:peercert(Sock) of
- {ok, C} ->
- case rabbit_ssl:peer_cert_auth_name(C) of
- unsafe -> none;
- not_found -> none;
- Name -> Name
- end;
- {error, no_peercert} ->
- none;
- nossl ->
- none
+ {ok, C} -> case rabbit_ssl:peer_cert_auth_name(C) of
+ unsafe -> none;
+ not_found -> none;
+ Name -> Name
+ end;
+ {error, no_peercert} -> none;
+ nossl -> none
end.
proto_integer_to_atom(3) ->
@@ -2350,73 +1860,47 @@ proto_version_tuple(#state{cfg = #cfg{proto_ver = ?MQTT_PROTO_V3}}) ->
proto_version_tuple(#state{cfg = #cfg{proto_ver = ?MQTT_PROTO_V4}}) ->
{3, 1, 1}.
-maybe_increment_publisher(
- State = #state{
- cfg =
- Cfg = #cfg{
- published = false,
- proto_ver = ProtoVer
- }
- }
-) ->
+maybe_increment_publisher(State = #state{cfg = Cfg = #cfg{published = false,
+ proto_ver = ProtoVer}}) ->
rabbit_global_counters:publisher_created(ProtoVer),
State#state{cfg = Cfg#cfg{published = true}};
maybe_increment_publisher(State) ->
State.
-maybe_decrement_publisher(#state{
- cfg = #cfg{
- published = true,
- proto_ver = ProtoVer
- }
-}) ->
+maybe_decrement_publisher(#state{cfg = #cfg{published = true,
+ proto_ver = ProtoVer}}) ->
rabbit_global_counters:publisher_deleted(ProtoVer);
maybe_decrement_publisher(_) ->
ok.
%% Multiple subscriptions from the same connection count as one consumer.
-maybe_increment_consumer(
- #state{subscriptions = OldSubs},
- #state{
- subscriptions = NewSubs,
- cfg = #cfg{proto_ver = ProtoVer}
- }
-) when
- map_size(OldSubs) =:= 0 andalso
- map_size(NewSubs) > 0
-->
+maybe_increment_consumer(#state{subscriptions = OldSubs},
+ #state{subscriptions = NewSubs,
+ cfg = #cfg{proto_ver = ProtoVer}})
+ when map_size(OldSubs) =:= 0 andalso
+ map_size(NewSubs) > 0 ->
rabbit_global_counters:consumer_created(ProtoVer);
maybe_increment_consumer(_, _) ->
ok.
-maybe_decrement_consumer(#state{
- subscriptions = Subs,
- cfg = #cfg{proto_ver = ProtoVer}
-}) when
- map_size(Subs) > 0
-->
+maybe_decrement_consumer(#state{subscriptions = Subs,
+ cfg = #cfg{proto_ver = ProtoVer}})
+ when map_size(Subs) > 0 ->
rabbit_global_counters:consumer_deleted(ProtoVer);
maybe_decrement_consumer(_) ->
ok.
-maybe_decrement_consumer(
- #state{subscriptions = OldSubs},
- #state{
- subscriptions = NewSubs,
- cfg = #cfg{proto_ver = ProtoVer}
- }
-) when
- map_size(OldSubs) > 0 andalso
- map_size(NewSubs) =:= 0
-->
+maybe_decrement_consumer(#state{subscriptions = OldSubs},
+ #state{subscriptions = NewSubs,
+ cfg = #cfg{proto_ver = ProtoVer}})
+ when map_size(OldSubs) > 0 andalso
+ map_size(NewSubs) =:= 0 ->
rabbit_global_counters:consumer_deleted(ProtoVer);
maybe_decrement_consumer(_, _) ->
ok.
-message_acknowledged(QName, #state{
- queue_states = QStates,
- cfg = #cfg{proto_ver = ProtoVer}
-}) ->
+message_acknowledged(QName, #state{queue_states = QStates,
+ cfg = #cfg{proto_ver = ProtoVer}}) ->
case rabbit_queue_type:module(QName, QStates) of
{ok, QType} ->
rabbit_global_counters:messages_acknowledged(ProtoVer, QType, 1);
@@ -2424,27 +1908,17 @@ message_acknowledged(QName, #state{
ok
end.
-message_delivered(
- ?QUEUE_TYPE_QOS_0,
- false,
- ?QOS_0,
- #state{cfg = #cfg{proto_ver = ProtoVer}}
-) ->
+message_delivered(?QUEUE_TYPE_QOS_0, false, ?QOS_0,
+ #state{cfg = #cfg{proto_ver = ProtoVer}}) ->
rabbit_global_counters:messages_delivered(ProtoVer, ?QUEUE_TYPE_QOS_0, 1),
%% Technically, the message is not acked to a queue at all.
%% However, from a user perspective it is still auto acked because:
%% "In automatic acknowledgement mode, a message is considered to be successfully
%% delivered immediately after it is sent."
rabbit_global_counters:messages_delivered_consume_auto_ack(ProtoVer, ?QUEUE_TYPE_QOS_0, 1);
-message_delivered(
- QName,
- Redelivered,
- QoS,
- #state{
- queue_states = QStates,
- cfg = #cfg{proto_ver = ProtoVer}
- }
-) ->
+message_delivered(QName, Redelivered, QoS,
+ #state{queue_states = QStates,
+ cfg = #cfg{proto_ver = ProtoVer}}) ->
case rabbit_queue_type:module(QName, QStates) of
{ok, QType} ->
rabbit_global_counters:messages_delivered(ProtoVer, QType, 1),
@@ -2466,72 +1940,65 @@ message_redelivered(_, _, _) ->
-spec format_status(state()) -> map().
format_status(
- #state{
- queue_states = QState,
- unacked_client_pubs = UnackClientPubs,
- unacked_server_pubs = UnackSerPubs,
- packet_id = PackID,
- subscriptions = Subscriptions,
- auth_state = AuthState,
- register_state = RegisterState,
- queues_soft_limit_exceeded = QSLE,
- qos0_messages_dropped = Qos0MsgsDropped,
- cfg = #cfg{
- socket = Socket,
- proto_ver = ProtoVersion,
- clean_sess = CleanSess,
- will_msg = WillMsg,
- exchange = Exchange,
- queue_qos1 = _,
- published = Published,
- ssl_login_name = SSLLoginName,
- retainer_pid = RetainerPid,
- delivery_flow = DeliveryFlow,
- trace_state = TraceState,
- prefetch = Prefetch,
- client_id = ClientID,
- conn_name = ConnName,
- peer_addr = PeerAddr,
- host = Host,
- port = Port,
- peer_host = PeerHost,
- peer_port = PeerPort,
- connected_at = ConnectedAt,
- send_fun = _
- }
- }
-) ->
- Cfg = #{
- socket => Socket,
- proto_ver => ProtoVersion,
- clean_sess => CleanSess,
- will_msg_defined => WillMsg =/= undefined,
- exchange => Exchange,
- published => Published,
- ssl_login_name => SSLLoginName,
- retainer_pid => RetainerPid,
-
- delivery_flow => DeliveryFlow,
- trace_state => TraceState,
- prefetch => Prefetch,
- client_id => ClientID,
- conn_name => ConnName,
- peer_addr => PeerAddr,
- host => Host,
- port => Port,
- peer_host => PeerHost,
- peer_port => PeerPort,
- connected_at => ConnectedAt
- },
- #{
- cfg => Cfg,
- queue_states => rabbit_queue_type:format_status(QState),
- unacked_client_pubs => UnackClientPubs,
- unacked_server_pubs => UnackSerPubs,
- packet_id => PackID,
- subscriptions => Subscriptions,
- auth_state => AuthState,
- register_state => RegisterState,
- queues_soft_limit_exceeded => QSLE,
- qos0_messages_dropped => Qos0MsgsDropped
- }.
+ #state{queue_states = QState,
+ unacked_client_pubs = UnackClientPubs,
+ unacked_server_pubs = UnackSerPubs,
+ packet_id = PackID,
+ subscriptions = Subscriptions,
+ auth_state = AuthState,
+ register_state = RegisterState,
+ queues_soft_limit_exceeded = QSLE,
+ qos0_messages_dropped = Qos0MsgsDropped,
+ cfg = #cfg{
+ socket = Socket,
+ proto_ver = ProtoVersion,
+ clean_sess = CleanSess,
+ will_msg = WillMsg,
+ exchange = Exchange,
+ queue_qos1 = _,
+ published = Published,
+ ssl_login_name = SSLLoginName,
+ retainer_pid = RetainerPid,
+ delivery_flow = DeliveryFlow,
+ trace_state = TraceState,
+ prefetch = Prefetch,
+ client_id = ClientID,
+ conn_name = ConnName,
+ peer_addr = PeerAddr,
+ host = Host,
+ port = Port,
+ peer_host = PeerHost,
+ peer_port = PeerPort,
+ connected_at = ConnectedAt,
+ send_fun = _
+ }}) ->
+ Cfg = #{socket => Socket,
+ proto_ver => ProtoVersion,
+ clean_sess => CleanSess,
+ will_msg_defined => WillMsg =/= undefined,
+ exchange => Exchange,
+ published => Published,
+ ssl_login_name => SSLLoginName,
+ retainer_pid => RetainerPid,
+
+ delivery_flow => DeliveryFlow,
+ trace_state => TraceState,
+ prefetch => Prefetch,
+ client_id => ClientID,
+ conn_name => ConnName,
+ peer_addr => PeerAddr,
+ host => Host,
+ port => Port,
+ peer_host => PeerHost,
+ peer_port => PeerPort,
+ connected_at => ConnectedAt},
+ #{cfg => Cfg,
+ queue_states => rabbit_queue_type:format_status(QState),
+ unacked_client_pubs => UnackClientPubs,
+ unacked_server_pubs => UnackSerPubs,
+ packet_id => PackID,
+ subscriptions => Subscriptions,
+ auth_state => AuthState,
+ register_state => RegisterState,
+ queues_soft_limit_exceeded => QSLE,
+ qos0_messages_dropped => Qos0MsgsDropped}.
diff --git a/deps/rabbitmq_mqtt/src/rabbit_mqtt_qos0_queue.erl b/deps/rabbitmq_mqtt/src/rabbit_mqtt_qos0_queue.erl
index 1244c96483..deb0eff622 100644
--- a/deps/rabbitmq_mqtt/src/rabbit_mqtt_qos0_queue.erl
+++ b/deps/rabbitmq_mqtt/src/rabbit_mqtt_qos0_queue.erl
@@ -24,50 +24,42 @@
%% Stateless rabbit_queue_type callbacks.
-export([
- is_stateful/0,
- declare/2,
- delete/4,
- deliver/2,
- is_enabled/0,
- is_compatible/3,
- is_recoverable/1,
- recover/2,
- purge/1,
- policy_changed/1,
- info/2,
- stat/1,
- capabilities/0,
- notify_decorators/1
-]).
+ is_stateful/0,
+ declare/2,
+ delete/4,
+ deliver/2,
+ is_enabled/0,
+ is_compatible/3,
+ is_recoverable/1,
+ recover/2,
+ purge/1,
+ policy_changed/1,
+ info/2,
+ stat/1,
+ capabilities/0,
+ notify_decorators/1
+ ]).
%% Stateful rabbit_queue_type callbacks are unsupported by this queue type.
--define(STATEFUL_CALLBACKS, [
- init/1,
- close/1,
- update/2,
- consume/3,
- cancel/5,
- handle_event/3,
- settle/5,
- credit/5,
- dequeue/5,
- state_info/1
-]).
+-define(STATEFUL_CALLBACKS,
+ [
+ init/1,
+ close/1,
+ update/2,
+ consume/3,
+ cancel/5,
+ handle_event/3,
+ settle/5,
+ credit/5,
+ dequeue/5,
+ state_info/1
+ ]).
-export(?STATEFUL_CALLBACKS).
-dialyzer({nowarn_function, ?STATEFUL_CALLBACKS}).
-define(UNSUPPORTED(Args), erlang:error(unsupported, Args)).
--define(INFO_KEYS, [
- type,
- name,
- durable,
- auto_delete,
- arguments,
- pid,
- owner_pid,
- state,
- messages
-]).
+-define(INFO_KEYS, [type, name, durable, auto_delete, arguments,
+ pid, owner_pid, state, messages]).
-spec is_stateful() ->
boolean().
@@ -75,8 +67,8 @@ is_stateful() ->
false.
-spec declare(amqqueue:amqqueue(), node()) ->
- {'new' | 'existing' | 'owner_died', amqqueue:amqqueue()}
- | {'absent', amqqueue:amqqueue(), rabbit_amqqueue:absent_reason()}.
+ {'new' | 'existing' | 'owner_died', amqqueue:amqqueue()} |
+ {'absent', amqqueue:amqqueue(), rabbit_amqqueue:absent_reason()}.
declare(Q0, _Node) ->
%% The queue gets persisted such that routing to this
%% queue (via the topic exchange) works as usual.
@@ -84,29 +76,23 @@ declare(Q0, _Node) ->
{created, Q} ->
Opts = amqqueue:get_options(Q),
ActingUser = maps:get(user, Opts, ?UNKNOWN_USER),
- rabbit_event:notify(
- queue_created,
- [
- {name, amqqueue:get_name(Q0)},
- {durable, true},
- {auto_delete, false},
- {exclusive, true},
- {type, amqqueue:get_type(Q0)},
- {arguments, amqqueue:get_arguments(Q0)},
- {user_who_performed_action, ActingUser}
- ]
- ),
+ rabbit_event:notify(queue_created,
+ [{name, amqqueue:get_name(Q0)},
+ {durable, true},
+ {auto_delete, false},
+ {exclusive, true},
+ {type, amqqueue:get_type(Q0)},
+ {arguments, amqqueue:get_arguments(Q0)},
+ {user_who_performed_action, ActingUser}]),
{new, Q};
Other ->
Other
end.
--spec delete(
- amqqueue:amqqueue(),
- boolean(),
- boolean(),
- rabbit_types:username()
-) ->
+-spec delete(amqqueue:amqqueue(),
+ boolean(),
+ boolean(),
+ rabbit_types:username()) ->
rabbit_types:ok(non_neg_integer()).
delete(Q, _IfUnused, _IfEmpty, ActingUser) ->
QName = amqqueue:get_name(Q),
@@ -116,41 +102,35 @@ delete(Q, _IfUnused, _IfEmpty, ActingUser) ->
-spec deliver([{amqqueue:amqqueue(), stateless}], Delivery :: term()) ->
{[], rabbit_queue_type:actions()}.
-deliver(Qs, #delivery{
- message = BasicMessage,
- confirm = Confirm,
- msg_seq_no = SeqNo
-}) ->
- Msg =
- {queue_event, ?MODULE,
- {?MODULE, _QPid = none, _QMsgId = none, _Redelivered = false, BasicMessage}},
+deliver(Qs, #delivery{message = BasicMessage,
+ confirm = Confirm,
+ msg_seq_no = SeqNo}) ->
+ Msg = {queue_event, ?MODULE,
+ {?MODULE, _QPid = none, _QMsgId = none, _Redelivered = false, BasicMessage}},
{Pids, Actions} =
- case Confirm of
- false ->
- Pids0 = lists:map(fun({Q, stateless}) -> amqqueue:get_pid(Q) end, Qs),
- {Pids0, []};
- true ->
- %% We confirm the message directly here in the queue client.
- %% Alternatively, we could have the target MQTT connection process confirm the message.
- %% However, given that this message might be lost anyway between target MQTT connection
- %% process and MQTT subscriber, and we know that the MQTT subscriber wants to receive
- %% this message at most once, we confirm here directly.
- %% Benefits:
- %% 1. We do not block sending the confirmation back to the publishing client just because a single
- %% (at-most-once) target queue out of potentially many (e.g. million) queues might be unavailable.
- %% 2. Memory usage in this (publishing) process is kept lower because the target queue name can be
- %% directly removed from rabbit_mqtt_confirms and rabbit_confirms.
- %% 3. Reduced network traffic across RabbitMQ nodes.
- %% 4. Lower latency of sending publisher confirmation back to the publishing client.
- SeqNos = [SeqNo],
- lists:mapfoldl(
- fun({Q, stateless}, Actions) ->
- {amqqueue:get_pid(Q), [{settled, amqqueue:get_name(Q), SeqNos} | Actions]}
- end,
- [],
- Qs
- )
- end,
+ case Confirm of
+ false ->
+ Pids0 = lists:map(fun({Q, stateless}) -> amqqueue:get_pid(Q) end, Qs),
+ {Pids0, []};
+ true ->
+ %% We confirm the message directly here in the queue client.
+ %% Alternatively, we could have the target MQTT connection process confirm the message.
+ %% However, given that this message might be lost anyway between target MQTT connection
+ %% process and MQTT subscriber, and we know that the MQTT subscriber wants to receive
+ %% this message at most once, we confirm here directly.
+ %% Benefits:
+ %% 1. We do not block sending the confirmation back to the publishing client just because a single
+ %% (at-most-once) target queue out of potentially many (e.g. million) queues might be unavailable.
+ %% 2. Memory usage in this (publishing) process is kept lower because the target queue name can be
+ %% directly removed from rabbit_mqtt_confirms and rabbit_confirms.
+ %% 3. Reduced network traffic across RabbitMQ nodes.
+ %% 4. Lower latency of sending publisher confirmation back to the publishing client.
+ SeqNos = [SeqNo],
+ lists:mapfoldl(fun({Q, stateless}, Actions) ->
+ {amqqueue:get_pid(Q),
+ [{settled, amqqueue:get_name(Q), SeqNos} | Actions]}
+ end, [], Qs)
+ end,
delegate:invoke_no_result(Pids, {gen_server, cast, [Msg]}),
{[], Actions}.
@@ -172,8 +152,8 @@ is_recoverable(Q) ->
Pid = amqqueue:get_pid(Q),
OwnerPid = amqqueue:get_exclusive_owner(Q),
node() =:= node(Pid) andalso
- Pid =:= OwnerPid andalso
- not is_process_alive(Pid).
+ Pid =:= OwnerPid andalso
+ not is_process_alive(Pid).
%% We (mis)use the recover callback to clean up our exclusive queues
%% which otherwise do not get cleaned up after a node crash.
@@ -181,24 +161,20 @@ is_recoverable(Q) ->
{Recovered :: [amqqueue:amqqueue()], Failed :: [amqqueue:amqqueue()]}.
recover(_VHost, Queues) ->
lists:foreach(
- fun(Q) ->
- %% sanity check
- true = is_recoverable(Q),
- QName = amqqueue:get_name(Q),
- log_delete(QName, amqqueue:get_exclusive_owner(Q)),
- rabbit_amqqueue:internal_delete(QName, ?INTERNAL_USER)
- end,
- Queues
- ),
+ fun(Q) ->
+ %% sanity check
+ true = is_recoverable(Q),
+ QName = amqqueue:get_name(Q),
+ log_delete(QName, amqqueue:get_exclusive_owner(Q)),
+ rabbit_amqqueue:internal_delete(QName, ?INTERNAL_USER)
+ end, Queues),
%% We mark the queue recovery as failed because these queues are not really
%% recovered, but deleted.
{[], Queues}.
log_delete(QName, ConPid) ->
- rabbit_log_queue:debug(
- "Deleting ~s of type ~s because its declaring connection ~tp was closed",
- [rabbit_misc:rs(QName), ?MODULE, ConPid]
- ).
+ rabbit_log_queue:debug("Deleting ~s of type ~s because its declaring connection ~tp was closed",
+ [rabbit_misc:rs(QName), ?MODULE, ConPid]).
-spec purge(amqqueue:amqqueue()) ->
{ok, non_neg_integer()}.
@@ -227,13 +203,11 @@ capabilities() ->
-spec info(amqqueue:amqqueue(), all_keys | rabbit_types:info_keys()) ->
rabbit_types:infos().
-info(Q, all_keys) when
- ?is_amqqueue(Q)
-->
+info(Q, all_keys)
+ when ?is_amqqueue(Q) ->
info(Q, ?INFO_KEYS);
-info(Q, Items) when
- ?is_amqqueue(Q)
-->
+info(Q, Items)
+ when ?is_amqqueue(Q) ->
[{Item, i(Item, Q)} || Item <- Items].
i(type, _) ->
@@ -275,26 +249,26 @@ init(A1) ->
close(A1) ->
?UNSUPPORTED([A1]).
-update(A1, A2) ->
- ?UNSUPPORTED([A1, A2]).
+update(A1,A2) ->
+ ?UNSUPPORTED([A1,A2]).
-consume(A1, A2, A3) ->
- ?UNSUPPORTED([A1, A2, A3]).
+consume(A1,A2,A3) ->
+ ?UNSUPPORTED([A1,A2,A3]).
-cancel(A1, A2, A3, A4, A5) ->
- ?UNSUPPORTED([A1, A2, A3, A4, A5]).
+cancel(A1,A2,A3,A4,A5) ->
+ ?UNSUPPORTED([A1,A2,A3,A4,A5]).
-handle_event(A1, A2, A3) ->
- ?UNSUPPORTED([A1, A2, A3]).
+handle_event(A1,A2,A3) ->
+ ?UNSUPPORTED([A1,A2,A3]).
-settle(A1, A2, A3, A4, A5) ->
- ?UNSUPPORTED([A1, A2, A3, A4, A5]).
+settle(A1,A2,A3,A4,A5) ->
+ ?UNSUPPORTED([A1,A2,A3,A4,A5]).
-credit(A1, A2, A3, A4, A5) ->
- ?UNSUPPORTED([A1, A2, A3, A4, A5]).
+credit(A1,A2,A3,A4,A5) ->
+ ?UNSUPPORTED([A1,A2,A3,A4,A5]).
-dequeue(A1, A2, A3, A4, A5) ->
- ?UNSUPPORTED([A1, A2, A3, A4, A5]).
+dequeue(A1,A2,A3,A4,A5) ->
+ ?UNSUPPORTED([A1,A2,A3,A4,A5]).
state_info(A1) ->
?UNSUPPORTED([A1]).
diff --git a/deps/rabbitmq_mqtt/src/rabbit_mqtt_reader.erl b/deps/rabbitmq_mqtt/src/rabbit_mqtt_reader.erl
index 6f32816492..3949989230 100644
--- a/deps/rabbitmq_mqtt/src/rabbit_mqtt_reader.erl
+++ b/deps/rabbitmq_mqtt/src/rabbit_mqtt_reader.erl
@@ -14,20 +14,11 @@
-include_lib("rabbit_common/include/logging.hrl").
-export([start_link/3]).
--export([
- init/1,
- handle_call/3,
- handle_cast/2,
- handle_info/2,
- code_change/3,
- terminate/2,
- format_status/1
-]).
-
--export([
- conserve_resources/3,
- close_connection/2
-]).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ code_change/3, terminate/2, format_status/1]).
+
+-export([conserve_resources/3,
+ close_connection/2]).
-export([info/2]).
@@ -38,22 +29,22 @@
-define(HIBERNATE_AFTER, 1000).
-define(PROTO_FAMILY, 'MQTT').
--record(state, {
- socket :: rabbit_net:socket(),
- proxy_socket :: option({rabbit_proxy_socket, any(), any()}),
- await_recv :: boolean(),
- deferred_recv :: option(binary()),
- parse_state :: rabbit_mqtt_packet:state(),
- proc_state :: rabbit_mqtt_processor:state(),
- connection_state :: running | blocked,
- conserve :: boolean(),
- stats_timer :: option(rabbit_event:state()),
- keepalive = rabbit_mqtt_keepalive:init() :: rabbit_mqtt_keepalive:state(),
- conn_name :: binary(),
- received_connect_packet :: boolean()
-}).
-
--type state() :: #state{}.
+-record(state,
+ {socket :: rabbit_net:socket(),
+ proxy_socket :: option({rabbit_proxy_socket, any(), any()}),
+ await_recv :: boolean(),
+ deferred_recv :: option(binary()),
+ parse_state :: rabbit_mqtt_packet:state(),
+ proc_state :: rabbit_mqtt_processor:state(),
+ connection_state :: running | blocked,
+ conserve :: boolean(),
+ stats_timer :: option(rabbit_event:state()),
+ keepalive = rabbit_mqtt_keepalive:init() :: rabbit_mqtt_keepalive:state(),
+ conn_name :: binary(),
+ received_connect_packet :: boolean()
+ }).
+
+-type(state() :: #state{}).
%%----------------------------------------------------------------------------
@@ -61,11 +52,9 @@ start_link(Ref, _Transport, []) ->
Pid = proc_lib:spawn_link(?MODULE, init, [Ref]),
{ok, Pid}.
--spec conserve_resources(
- pid(),
- rabbit_alarm:resource_alarm_source(),
- rabbit_alarm:resource_alert()
-) -> ok.
+-spec conserve_resources(pid(),
+ rabbit_alarm:resource_alarm_source(),
+ rabbit_alarm:resource_alert()) -> ok.
conserve_resources(Pid, _, {_, Conserve, _}) ->
Pid ! {conserve_resources, Conserve},
ok.
@@ -84,10 +73,8 @@ close_connection(Pid, Reason) ->
init(Ref) ->
process_flag(trap_exit, true),
logger:set_process_metadata(#{domain => ?RMQLOG_DOMAIN_CONN ++ [mqtt]}),
- {ok, Sock} = rabbit_networking:handshake(
- Ref,
- application:get_env(?APP_NAME, proxy_protocol, false)
- ),
+ {ok, Sock} = rabbit_networking:handshake(Ref,
+ application:get_env(?APP_NAME, proxy_protocol, false)),
RealSocket = rabbit_net:unwrap_socket(Sock),
case rabbit_net:connection_string(Sock, inbound) of
{ok, ConnStr} ->
@@ -97,17 +84,15 @@ init(Ref) ->
LoginTimeout = application:get_env(?APP_NAME, login_timeout, 10_000),
erlang:send_after(LoginTimeout, self(), login_timeout),
ProcessorState = rabbit_mqtt_processor:initial_state(RealSocket, ConnName),
- State0 = #state{
- socket = RealSocket,
- proxy_socket = rabbit_net:maybe_get_proxy_socket(Sock),
- conn_name = ConnName,
- await_recv = false,
- connection_state = running,
- received_connect_packet = false,
- conserve = false,
- parse_state = rabbit_mqtt_packet:initial_state(),
- proc_state = ProcessorState
- },
+ State0 = #state{socket = RealSocket,
+ proxy_socket = rabbit_net:maybe_get_proxy_socket(Sock),
+ conn_name = ConnName,
+ await_recv = false,
+ connection_state = running,
+ received_connect_packet = false,
+ conserve = false,
+ parse_state = rabbit_mqtt_packet:initial_state(),
+ proc_state = ProcessorState},
State1 = control_throttle(State0),
State = rabbit_event:init_stats_timer(State1, #state.stats_timer),
gen_server:enter_loop(?MODULE, [], State);
@@ -123,67 +108,51 @@ init(Ref) ->
handle_call({info, InfoItems}, _From, State) ->
{reply, infos(InfoItems, State), State, ?HIBERNATE_AFTER};
+
handle_call(Msg, From, State) ->
{stop, {mqtt_unexpected_call, Msg, From}, State}.
-handle_cast(
- duplicate_id,
- State = #state{
- proc_state = PState,
- conn_name = ConnName
- }
-) ->
- ?LOG_WARNING(
- "MQTT disconnecting client ~tp with duplicate id '~ts'",
- [ConnName, rabbit_mqtt_processor:info(client_id, PState)]
- ),
+handle_cast(duplicate_id,
+ State = #state{ proc_state = PState,
+ conn_name = ConnName }) ->
+ ?LOG_WARNING("MQTT disconnecting client ~tp with duplicate id '~ts'",
+ [ConnName, rabbit_mqtt_processor:info(client_id, PState)]),
{stop, {shutdown, duplicate_id}, State};
-handle_cast(
- decommission_node,
- State = #state{
- proc_state = PState,
- conn_name = ConnName
- }
-) ->
- ?LOG_WARNING(
- "MQTT disconnecting client ~tp with client ID '~ts' as its node is about"
- " to be decommissioned",
- [ConnName, rabbit_mqtt_processor:info(client_id, PState)]
- ),
+
+handle_cast(decommission_node,
+ State = #state{ proc_state = PState,
+ conn_name = ConnName }) ->
+ ?LOG_WARNING("MQTT disconnecting client ~tp with client ID '~ts' as its node is about"
+ " to be decommissioned",
+ [ConnName, rabbit_mqtt_processor:info(client_id, PState)]),
{stop, {shutdown, decommission_node}, State};
-handle_cast(
- {close_connection, Reason},
- State = #state{conn_name = ConnName, proc_state = PState}
-) ->
- ?LOG_WARNING(
- "MQTT disconnecting client ~tp with client ID '~ts', reason: ~ts",
- [ConnName, rabbit_mqtt_processor:info(client_id, PState), Reason]
- ),
+
+handle_cast({close_connection, Reason},
+ State = #state{conn_name = ConnName, proc_state = PState}) ->
+ ?LOG_WARNING("MQTT disconnecting client ~tp with client ID '~ts', reason: ~ts",
+ [ConnName, rabbit_mqtt_processor:info(client_id, PState), Reason]),
{stop, {shutdown, server_initiated_close}, State};
-handle_cast(
- QueueEvent = {queue_event, _, _},
- State = #state{proc_state = PState0}
-) ->
+
+handle_cast(QueueEvent = {queue_event, _, _},
+ State = #state{proc_state = PState0}) ->
case rabbit_mqtt_processor:handle_queue_event(QueueEvent, PState0) of
{ok, PState} ->
maybe_process_deferred_recv(control_throttle(pstate(State, PState)));
{error, Reason, PState} ->
{stop, Reason, pstate(State, PState)}
end;
+
handle_cast({force_event_refresh, Ref}, State0) ->
Infos = infos(?CREATION_EVENT_KEYS, State0),
rabbit_event:notify(connection_created, Infos, Ref),
State = rabbit_event:init_stats_timer(State0, #state.stats_timer),
{noreply, State, ?HIBERNATE_AFTER};
-handle_cast(
- refresh_config,
- State = #state{
- proc_state = PState0,
- conn_name = ConnName
- }
-) ->
+
+handle_cast(refresh_config, State = #state{proc_state = PState0,
+ conn_name = ConnName}) ->
PState = rabbit_mqtt_processor:update_trace(ConnName, PState0),
{noreply, pstate(State, PState), ?HIBERNATE_AFTER};
+
handle_cast(Msg, State) ->
{stop, {mqtt_unexpected_cast, Msg}, State}.
@@ -192,53 +161,49 @@ handle_info(connection_created, State) ->
rabbit_core_metrics:connection_created(self(), Infos),
rabbit_event:notify(connection_created, Infos),
{noreply, State, ?HIBERNATE_AFTER};
+
handle_info(timeout, State) ->
rabbit_mqtt_processor:handle_pre_hibernate(),
{noreply, State, hibernate};
+
handle_info({'EXIT', _Conn, Reason}, State) ->
{stop, {connection_died, Reason}, State};
-handle_info(
- {Tag, Sock, Data},
- State = #state{socket = Sock, connection_state = blocked}
-) when
- Tag =:= tcp; Tag =:= ssl
-->
- {noreply, State#state{deferred_recv = Data}, ?HIBERNATE_AFTER};
-handle_info(
- {Tag, Sock, Data},
- State = #state{socket = Sock, connection_state = running}
-) when
- Tag =:= tcp; Tag =:= ssl
-->
+
+handle_info({Tag, Sock, Data},
+ State = #state{ socket = Sock, connection_state = blocked })
+ when Tag =:= tcp; Tag =:= ssl ->
+ {noreply, State#state{ deferred_recv = Data }, ?HIBERNATE_AFTER};
+
+handle_info({Tag, Sock, Data},
+ State = #state{ socket = Sock, connection_state = running })
+ when Tag =:= tcp; Tag =:= ssl ->
process_received_bytes(
- Data, control_throttle(State#state{await_recv = false})
- );
-handle_info({Tag, Sock}, State = #state{socket = Sock}) when
- Tag =:= tcp_closed; Tag =:= ssl_closed
-->
+ Data, control_throttle(State #state{ await_recv = false }));
+
+handle_info({Tag, Sock}, State = #state{socket = Sock})
+ when Tag =:= tcp_closed; Tag =:= ssl_closed ->
network_error(closed, State);
-handle_info({Tag, Sock, Reason}, State = #state{socket = Sock}) when
- Tag =:= tcp_error; Tag =:= ssl_error
-->
+
+handle_info({Tag, Sock, Reason}, State = #state{socket = Sock})
+ when Tag =:= tcp_error; Tag =:= ssl_error ->
network_error(Reason, State);
+
handle_info({inet_reply, Sock, ok}, State = #state{socket = Sock}) ->
{noreply, State, ?HIBERNATE_AFTER};
+
handle_info({inet_reply, Sock, {error, Reason}}, State = #state{socket = Sock}) ->
network_error(Reason, State);
+
handle_info({conserve_resources, Conserve}, State) ->
maybe_process_deferred_recv(
- control_throttle(State#state{conserve = Conserve})
- );
+ control_throttle(State #state{ conserve = Conserve }));
+
handle_info({bump_credit, Msg}, State) ->
credit_flow:handle_bump_msg(Msg),
maybe_process_deferred_recv(control_throttle(State));
-handle_info(
- {keepalive, Req},
- State = #state{
- keepalive = KState0,
- conn_name = ConnName
- }
-) ->
+
+handle_info({keepalive, Req}, State = #state{keepalive = KState0,
+ conn_name = ConnName}) ->
case rabbit_mqtt_keepalive:handle(Req, KState0) of
{ok, KState} ->
{noreply, State#state{keepalive = KState}, ?HIBERNATE_AFTER};
@@ -248,6 +213,7 @@ handle_info(
{error, Reason} ->
{stop, Reason, State}
end;
+
handle_info(login_timeout, State = #state{received_connect_packet = true}) ->
{noreply, State, ?HIBERNATE_AFTER};
handle_info(login_timeout, State = #state{conn_name = ConnName}) ->
@@ -258,47 +224,43 @@ handle_info(login_timeout, State = #state{conn_name = ConnName}) ->
%% and we don't want to skip closing the connection in that case.
?LOG_ERROR("closing MQTT connection ~tp (login timeout)", [ConnName]),
{stop, {shutdown, login_timeout}, State};
+
handle_info(emit_stats, State) ->
{noreply, emit_stats(State), ?HIBERNATE_AFTER};
-handle_info(
- {ra_event, _From, Evt},
- #state{proc_state = PState0} = State
-) ->
+
+handle_info({ra_event, _From, Evt},
+ #state{proc_state = PState0} = State) ->
%% handle applied event to ensure registration command actually got applied
%% handle not_leader notification in case we send the command to a non-leader
PState = rabbit_mqtt_processor:handle_ra_event(Evt, PState0),
{noreply, pstate(State, PState), ?HIBERNATE_AFTER};
-handle_info(
- {{'DOWN', _QName}, _MRef, process, _Pid, _Reason} = Evt,
- #state{proc_state = PState0} = State
-) ->
+
+handle_info({{'DOWN', _QName}, _MRef, process, _Pid, _Reason} = Evt,
+ #state{proc_state = PState0} = State) ->
case rabbit_mqtt_processor:handle_down(Evt, PState0) of
{ok, PState} ->
maybe_process_deferred_recv(control_throttle(pstate(State, PState)));
{error, Reason} ->
{stop, {shutdown, Reason, State}}
end;
+
handle_info({'DOWN', _MRef, process, QPid, _Reason}, State) ->
rabbit_amqqueue_common:notify_sent_queue_down(QPid),
{noreply, State, ?HIBERNATE_AFTER};
+
handle_info({shutdown, Explanation} = Reason, State = #state{conn_name = ConnName}) ->
%% rabbitmq_management plugin requests to close connection.
?LOG_INFO("MQTT closing connection ~tp: ~p", [ConnName, Explanation]),
{stop, Reason, State};
+
handle_info(Msg, State) ->
{stop, {mqtt_unexpected_msg, Msg}, State}.
terminate(Reason, State = #state{}) ->
terminate(Reason, {true, State});
-terminate(
- Reason,
- {SendWill,
- State = #state{
- conn_name = ConnName,
- keepalive = KState0,
- proc_state = PState
- }}
-) ->
+terminate(Reason, {SendWill, State = #state{conn_name = ConnName,
+ keepalive = KState0,
+ proc_state = PState}}) ->
KState = rabbit_mqtt_keepalive:cancel_timer(KState0),
maybe_emit_stats(State#state{keepalive = KState}),
_ = rabbit_mqtt_processor:terminate(SendWill, ConnName, ?PROTO_FAMILY, PState),
@@ -306,25 +268,36 @@ terminate(
log_terminate({network_error, {ssl_upgrade_error, closed}, ConnName}, _State) ->
?LOG_ERROR("MQTT detected TLS upgrade error on ~s: connection closed", [ConnName]);
-log_terminate(
- {network_error, {ssl_upgrade_error, {tls_alert, "handshake failure"}}, ConnName}, _State
-) ->
+
+log_terminate({network_error,
+ {ssl_upgrade_error,
+ {tls_alert, "handshake failure"}}, ConnName}, _State) ->
log_tls_alert(handshake_failure, ConnName);
-log_terminate({network_error, {ssl_upgrade_error, {tls_alert, "unknown ca"}}, ConnName}, _State) ->
+log_terminate({network_error,
+ {ssl_upgrade_error,
+ {tls_alert, "unknown ca"}}, ConnName}, _State) ->
log_tls_alert(unknown_ca, ConnName);
-log_terminate({network_error, {ssl_upgrade_error, {tls_alert, {Err, _}}}, ConnName}, _State) ->
+log_terminate({network_error,
+ {ssl_upgrade_error,
+ {tls_alert, {Err, _}}}, ConnName}, _State) ->
log_tls_alert(Err, ConnName);
-log_terminate({network_error, {ssl_upgrade_error, {tls_alert, Alert}}, ConnName}, _State) ->
+log_terminate({network_error,
+ {ssl_upgrade_error,
+ {tls_alert, Alert}}, ConnName}, _State) ->
log_tls_alert(Alert, ConnName);
log_terminate({network_error, {ssl_upgrade_error, Reason}, ConnName}, _State) ->
?LOG_ERROR("MQTT detected TLS upgrade error on ~s: ~p", [ConnName, Reason]);
+
log_terminate({network_error, Reason, ConnName}, _State) ->
?LOG_ERROR("MQTT detected network error on ~s: ~p", [ConnName, Reason]);
+
log_terminate({network_error, Reason}, _State) ->
?LOG_ERROR("MQTT detected network error: ~p", [Reason]);
-log_terminate(normal, #state{conn_name = ConnName}) ->
+
+log_terminate(normal, #state{conn_name = ConnName}) ->
?LOG_INFO("closing MQTT connection ~p (~s)", [self(), ConnName]),
ok;
+
log_terminate(_Reason, _State) ->
ok.
@@ -336,80 +309,54 @@ code_change(_OldVsn, State, _Extra) ->
log_tls_alert(handshake_failure, ConnName) ->
?LOG_ERROR("MQTT detected TLS upgrade error on ~ts: handshake failure", [ConnName]);
log_tls_alert(unknown_ca, ConnName) ->
- ?LOG_ERROR(
- "MQTT detected TLS certificate verification error on ~ts: alert 'unknown CA'",
- [ConnName]
- );
+ ?LOG_ERROR("MQTT detected TLS certificate verification error on ~ts: alert 'unknown CA'",
+ [ConnName]);
log_tls_alert(Alert, ConnName) ->
?LOG_ERROR("MQTT detected TLS upgrade error on ~ts: alert ~ts", [ConnName, Alert]).
-process_received_bytes(
- <<>>,
- State = #state{
- received_connect_packet = false,
- proc_state = PState,
- conn_name = ConnName
- }
-) ->
- ?LOG_INFO(
- "Accepted MQTT connection ~p (~s, client ID: ~s)",
- [self(), ConnName, rabbit_mqtt_processor:info(client_id, PState)]
- ),
+process_received_bytes(<<>>, State = #state{received_connect_packet = false,
+ proc_state = PState,
+ conn_name = ConnName}) ->
+ ?LOG_INFO("Accepted MQTT connection ~p (~s, client ID: ~s)",
+ [self(), ConnName, rabbit_mqtt_processor:info(client_id, PState)]),
{noreply, ensure_stats_timer(State#state{received_connect_packet = true}), ?HIBERNATE_AFTER};
process_received_bytes(<<>>, State) ->
{noreply, ensure_stats_timer(State), ?HIBERNATE_AFTER};
-process_received_bytes(
- Bytes,
- State = #state{
- parse_state = ParseState,
- proc_state = ProcState,
- conn_name = ConnName
- }
-) ->
+process_received_bytes(Bytes,
+ State = #state{ parse_state = ParseState,
+ proc_state = ProcState,
+ conn_name = ConnName }) ->
case parse(Bytes, ParseState) of
{more, ParseState1} ->
- {noreply, ensure_stats_timer(State#state{parse_state = ParseState1}), ?HIBERNATE_AFTER};
+ {noreply,
+ ensure_stats_timer( State #state{ parse_state = ParseState1 }),
+ ?HIBERNATE_AFTER};
{ok, Packet, Rest} ->
case rabbit_mqtt_processor:process_packet(Packet, ProcState) of
{ok, ProcState1} ->
process_received_bytes(
- Rest,
- State#state{
- parse_state = rabbit_mqtt_packet:initial_state(),
- proc_state = ProcState1
- }
- );
+ Rest,
+ State #state{parse_state = rabbit_mqtt_packet:initial_state(),
+ proc_state = ProcState1});
%% PUBLISH and more
{error, unauthorized = Reason, ProcState1} ->
- ?LOG_ERROR("MQTT connection ~ts is closing due to an authorization failure", [
- ConnName
- ]),
+ ?LOG_ERROR("MQTT connection ~ts is closing due to an authorization failure", [ConnName]),
{stop, {shutdown, Reason}, pstate(State, ProcState1)};
%% CONNECT packets only
{error, unauthenticated = Reason, ProcState1} ->
- ?LOG_ERROR("MQTT connection ~ts is closing due to an authentication failure", [
- ConnName
- ]),
+ ?LOG_ERROR("MQTT connection ~ts is closing due to an authentication failure", [ConnName]),
{stop, {shutdown, Reason}, pstate(State, ProcState1)};
%% CONNECT packets only
{error, invalid_client_id = Reason, ProcState1} ->
- ?LOG_ERROR("MQTT cannot accept connection ~ts: client uses an invalid ID", [
- ConnName
- ]),
+ ?LOG_ERROR("MQTT cannot accept connection ~ts: client uses an invalid ID", [ConnName]),
{stop, {shutdown, Reason}, pstate(State, ProcState1)};
%% CONNECT packets only
{error, unsupported_protocol_version = Reason, ProcState1} ->
- ?LOG_ERROR(
- "MQTT cannot accept connection ~ts: incompatible protocol version", [
- ConnName
- ]
- ),
+ ?LOG_ERROR("MQTT cannot accept connection ~ts: incompatible protocol version", [ConnName]),
{stop, {shutdown, Reason}, pstate(State, ProcState1)};
{error, unavailable = Reason, ProcState1} ->
- ?LOG_ERROR(
- "MQTT cannot accept connection ~ts due to an internal error or unavailable component",
- [ConnName]
- ),
+ ?LOG_ERROR("MQTT cannot accept connection ~ts due to an internal error or unavailable component",
+ [ConnName]),
{stop, {shutdown, Reason}, pstate(State, ProcState1)};
{error, Reason, ProcState1} ->
?LOG_ERROR("MQTT protocol error on connection ~ts: ~tp", [ConnName, Reason]),
@@ -418,11 +365,9 @@ process_received_bytes(
{stop, normal, {_SendWill = false, pstate(State, ProcState1)}}
end;
{error, {cannot_parse, Reason, Stacktrace}} ->
- ?LOG_ERROR(
- "MQTT cannot parse a packet on connection '~ts', reason: ~tp, "
- "stacktrace: ~tp, payload (first 100 bytes): ~tp",
- [ConnName, Reason, Stacktrace, rabbit_mqtt_util:truncate_binary(Bytes, 100)]
- ),
+ ?LOG_ERROR("MQTT cannot parse a packet on connection '~ts', reason: ~tp, "
+ "stacktrace: ~tp, payload (first 100 bytes): ~tp",
+ [ConnName, Reason, Stacktrace, rabbit_mqtt_util:truncate_binary(Bytes, 100)]),
{stop, {shutdown, Reason}, State};
{error, Error} ->
?LOG_ERROR("MQTT detected a framing error on connection ~ts: ~tp", [ConnName, Error]),
@@ -430,8 +375,8 @@ process_received_bytes(
end.
-spec pstate(state(), rabbit_mqtt_processor:state()) -> state().
-pstate(State = #state{}, PState) ->
- State#state{proc_state = PState}.
+pstate(State = #state {}, PState) ->
+ State #state{ proc_state = PState }.
%%----------------------------------------------------------------------------
parse(Bytes, ParseState) ->
@@ -442,13 +387,9 @@ parse(Bytes, ParseState) ->
{error, {cannot_parse, Reason, Stacktrace}}
end.
-network_error(
- closed,
- State = #state{
- conn_name = ConnName,
- received_connect_packet = Connected
- }
-) ->
+network_error(closed,
+ State = #state{conn_name = ConnName,
+ received_connect_packet = Connected}) ->
Fmt = "MQTT connection ~p will terminate because peer closed TCP connection",
Args = [ConnName],
case Connected of
@@ -456,77 +397,62 @@ network_error(
false -> ?LOG_DEBUG(Fmt, Args)
end,
{stop, {shutdown, conn_closed}, State};
-network_error(
- Reason,
- State = #state{conn_name = ConnName}
-) ->
+
+network_error(Reason,
+ State = #state{conn_name = ConnName}) ->
?LOG_INFO("MQTT detected network error for ~p: ~p", [ConnName, Reason]),
{stop, {shutdown, conn_closed}, State}.
-run_socket(State = #state{connection_state = blocked}) ->
+run_socket(State = #state{ connection_state = blocked }) ->
State;
-run_socket(State = #state{deferred_recv = Data}) when Data =/= undefined ->
+run_socket(State = #state{ deferred_recv = Data }) when Data =/= undefined ->
State;
-run_socket(State = #state{await_recv = true}) ->
+run_socket(State = #state{ await_recv = true }) ->
State;
-run_socket(State = #state{socket = Sock}) ->
+run_socket(State = #state{ socket = Sock }) ->
ok = rabbit_net:setopts(Sock, [{active, once}]),
- State#state{await_recv = true}.
-
-control_throttle(
- State = #state{
- connection_state = ConnState,
- conserve = Conserve,
- received_connect_packet = Connected,
- proc_state = PState,
- keepalive = KState
- }
-) ->
+ State#state{ await_recv = true }.
+
+control_throttle(State = #state{connection_state = ConnState,
+ conserve = Conserve,
+ received_connect_packet = Connected,
+ proc_state = PState,
+ keepalive = KState
+ }) ->
Throttle = rabbit_mqtt_processor:throttle(Conserve, Connected, PState),
case {ConnState, Throttle} of
{running, true} ->
- State#state{
- connection_state = blocked,
- keepalive = rabbit_mqtt_keepalive:cancel_timer(KState)
- };
+ State#state{connection_state = blocked,
+ keepalive = rabbit_mqtt_keepalive:cancel_timer(KState)};
{blocked, false} ->
- run_socket(State#state{
- connection_state = running,
- keepalive = rabbit_mqtt_keepalive:start_timer(KState)
- });
+ run_socket(State#state{connection_state = running,
+ keepalive = rabbit_mqtt_keepalive:start_timer(KState)});
{_, _} ->
run_socket(State)
end.
-maybe_process_deferred_recv(State = #state{deferred_recv = undefined}) ->
+maybe_process_deferred_recv(State = #state{ deferred_recv = undefined }) ->
{noreply, State, ?HIBERNATE_AFTER};
-maybe_process_deferred_recv(State = #state{deferred_recv = Data, socket = Sock}) ->
- handle_info(
- {tcp, Sock, Data},
- State#state{deferred_recv = undefined}
- ).
+maybe_process_deferred_recv(State = #state{ deferred_recv = Data, socket = Sock }) ->
+ handle_info({tcp, Sock, Data},
+ State#state{ deferred_recv = undefined }).
maybe_emit_stats(#state{stats_timer = undefined}) ->
ok;
maybe_emit_stats(State) ->
- rabbit_event:if_enabled(
- State,
- #state.stats_timer,
- fun() -> emit_stats(State) end
- ).
+ rabbit_event:if_enabled(State, #state.stats_timer,
+ fun() -> emit_stats(State) end).
-emit_stats(State = #state{received_connect_packet = false}) ->
+emit_stats(State=#state{received_connect_packet = false}) ->
%% Avoid emitting stats on terminate when the connection has not yet been
%% established, as this causes orphan entries on the stats database
State1 = rabbit_event:reset_stats_timer(State, #state.stats_timer),
ensure_stats_timer(State1);
emit_stats(State) ->
- [
- {_, Pid},
- {_, RecvOct},
- {_, SendOct},
- {_, Reductions}
- ] = infos(?SIMPLE_METRICS, State),
+ [{_, Pid},
+ {_, RecvOct},
+ {_, SendOct},
+ {_, Reductions}] = infos(?SIMPLE_METRICS, State),
Infos = infos(?OTHER_METRICS, State),
rabbit_core_metrics:connection_stats(Pid, Infos),
rabbit_core_metrics:connection_stats(Pid, RecvOct, SendOct, Reductions),
@@ -539,13 +465,12 @@ ensure_stats_timer(State = #state{}) ->
infos(Items, State) ->
[{Item, i(Item, State)} || Item <- Items].
-i(SockStat, #state{socket = Sock}) when
- SockStat =:= recv_oct;
- SockStat =:= recv_cnt;
- SockStat =:= send_oct;
- SockStat =:= send_cnt;
- SockStat =:= send_pend
-->
+i(SockStat, #state{socket = Sock})
+ when SockStat =:= recv_oct;
+ SockStat =:= recv_cnt;
+ SockStat =:= send_oct;
+ SockStat =:= send_cnt;
+ SockStat =:= send_pend ->
case rabbit_net:getstat(Sock, [SockStat]) of
{ok, [{_, N}]} when is_number(N) ->
N;
@@ -569,19 +494,17 @@ i(connection_state, #state{connection_state = Val}) ->
Val;
i(pid, _) ->
self();
-i(SSL, #state{socket = Sock, proxy_socket = ProxySock}) when
- SSL =:= ssl;
- SSL =:= ssl_protocol;
- SSL =:= ssl_key_exchange;
- SSL =:= ssl_cipher;
- SSL =:= ssl_hash
-->
+i(SSL, #state{socket = Sock, proxy_socket = ProxySock})
+ when SSL =:= ssl;
+ SSL =:= ssl_protocol;
+ SSL =:= ssl_key_exchange;
+ SSL =:= ssl_cipher;
+ SSL =:= ssl_hash ->
rabbit_ssl:info(SSL, {Sock, ProxySock});
-i(Cert, #state{socket = Sock}) when
- Cert =:= peer_cert_issuer;
- Cert =:= peer_cert_subject;
- Cert =:= peer_cert_validity
-->
+i(Cert, #state{socket = Sock})
+ when Cert =:= peer_cert_issuer;
+ Cert =:= peer_cert_subject;
+ Cert =:= peer_cert_validity ->
rabbit_ssl:cert_info(Cert, Sock);
i(timeout, #state{keepalive = KState}) ->
rabbit_mqtt_keepalive:interval_secs(KState);
@@ -591,48 +514,40 @@ i(Key, #state{proc_state = ProcState}) ->
rabbit_mqtt_processor:info(Key, ProcState).
-spec format_status(Status) -> Status when
- Status :: #{
- state => term(),
- message => term(),
- reason => term(),
- log => [sys:system_event()]
- }.
+ Status :: #{state => term(),
+ message => term(),
+ reason => term(),
+ log => [sys:system_event()]}.
format_status(Status) ->
maps:map(
- fun
- (state, State) ->
- format_state(State);
- (_, Value) ->
- Value
- end,
- Status
- ).
+ fun(state, State) ->
+ format_state(State);
+ (_, Value) ->
+ Value
+ end, Status).
-spec format_state(state()) -> map().
-format_state(#state{
- socket = Socket,
- proxy_socket = ProxySock,
- await_recv = AwaitRecv,
- deferred_recv = DeferredRecv,
- parse_state = _,
- proc_state = PState,
- connection_state = ConnectionState,
- conserve = Conserve,
- stats_timer = StatsTimer,
- keepalive = Keepalive,
- conn_name = ConnName,
- received_connect_packet = ReceivedConnectPacket
-}) ->
- #{
- socket => Socket,
- proxy_socket => ProxySock,
- await_recv => AwaitRecv,
- deferred_recv => DeferredRecv =/= undefined,
- proc_state => rabbit_mqtt_processor:format_status(PState),
- connection_state => ConnectionState,
- conserve => Conserve,
- stats_timer => StatsTimer,
- keepalive => Keepalive,
- conn_name => ConnName,
- received_connect_packet => ReceivedConnectPacket
- }.
+format_state(#state{socket = Socket,
+ proxy_socket = ProxySock,
+ await_recv = AwaitRecv,
+ deferred_recv = DeferredRecv,
+ parse_state = _,
+ proc_state = PState,
+ connection_state = ConnectionState,
+ conserve = Conserve,
+ stats_timer = StatsTimer,
+ keepalive = Keepalive,
+ conn_name = ConnName,
+ received_connect_packet = ReceivedConnectPacket
+ }) ->
+ #{socket => Socket,
+ proxy_socket => ProxySock,
+ await_recv => AwaitRecv,
+ deferred_recv => DeferredRecv =/= undefined,
+ proc_state => rabbit_mqtt_processor:format_status(PState),
+ connection_state => ConnectionState,
+ conserve => Conserve,
+ stats_timer => StatsTimer,
+ keepalive => Keepalive,
+ conn_name => ConnName,
+ received_connect_packet => ReceivedConnectPacket}.
diff --git a/deps/rabbitmq_mqtt/src/rabbit_mqtt_retained_msg_store_dets.erl b/deps/rabbitmq_mqtt/src/rabbit_mqtt_retained_msg_store_dets.erl
index bfaa0cd146..8dbd06a440 100644
--- a/deps/rabbitmq_mqtt/src/rabbit_mqtt_retained_msg_store_dets.erl
+++ b/deps/rabbitmq_mqtt/src/rabbit_mqtt_retained_msg_store_dets.erl
@@ -13,57 +13,53 @@
-export([new/2, recover/2, insert/3, lookup/2, delete/2, terminate/1]).
-record(store_state, {
- %% DETS table name
- table
+ %% DETS table name
+ table
}).
-type store_state() :: #store_state{}.
-spec new(file:name_all(), rabbit_types:vhost()) -> store_state().
new(Dir, VHost) ->
- Tid = open_table(Dir, VHost),
- #store_state{table = Tid}.
+ Tid = open_table(Dir, VHost),
+ #store_state{table = Tid}.
-spec recover(file:name_all(), rabbit_types:vhost()) ->
- {error, uninitialized} | {ok, store_state()}.
+ {error, uninitialized} | {ok, store_state()}.
recover(Dir, VHost) ->
- case open_table(Dir, VHost) of
- {error, _} -> {error, uninitialized};
- {ok, Tid} -> {ok, #store_state{table = Tid}}
- end.
+ case open_table(Dir, VHost) of
+ {error, _} -> {error, uninitialized};
+ {ok, Tid} -> {ok, #store_state{table = Tid}}
+ end.
-spec insert(binary(), mqtt_msg(), store_state()) -> ok.
insert(Topic, Msg, #store_state{table = T}) ->
- ok = dets:insert(T, #retained_message{topic = Topic, mqtt_msg = Msg}).
+ ok = dets:insert(T, #retained_message{topic = Topic, mqtt_msg = Msg}).
-spec lookup(binary(), store_state()) -> retained_message() | not_found.
lookup(Topic, #store_state{table = T}) ->
- case dets:lookup(T, Topic) of
- [] -> not_found;
- [Entry] -> Entry
- end.
+ case dets:lookup(T, Topic) of
+ [] -> not_found;
+ [Entry] -> Entry
+ end.
-spec delete(binary(), store_state()) -> ok.
delete(Topic, #store_state{table = T}) ->
- ok = dets:delete(T, Topic).
+ ok = dets:delete(T, Topic).
-spec terminate(store_state()) -> ok.
terminate(#store_state{table = T}) ->
- ok = dets:close(T).
+ ok = dets:close(T).
open_table(Dir, VHost) ->
- dets:open_file(
- rabbit_mqtt_util:vhost_name_to_table_name(VHost),
- table_options(rabbit_mqtt_util:path_for(Dir, VHost, ".dets"))
- ).
+ dets:open_file(rabbit_mqtt_util:vhost_name_to_table_name(VHost),
+ table_options(rabbit_mqtt_util:path_for(Dir, VHost, ".dets"))).
table_options(Path) ->
- [
- {type, set},
- {keypos, #retained_message.topic},
- {file, Path},
- {ram_file, true},
- {repair, true},
- {auto_save,
- rabbit_misc:get_env(rabbit_mqtt, retained_message_store_dets_sync_interval, 2000)}
+ [{type, set},
+ {keypos, #retained_message.topic},
+ {file, Path},
+ {ram_file, true},
+ {repair, true},
+ {auto_save, rabbit_misc:get_env(rabbit_mqtt, retained_message_store_dets_sync_interval, 2000)}
].
diff --git a/deps/rabbitmq_mqtt/src/rabbit_mqtt_retained_msg_store_ets.erl b/deps/rabbitmq_mqtt/src/rabbit_mqtt_retained_msg_store_ets.erl
index bbc7a77390..3a0a7384db 100644
--- a/deps/rabbitmq_mqtt/src/rabbit_mqtt_retained_msg_store_ets.erl
+++ b/deps/rabbitmq_mqtt/src/rabbit_mqtt_retained_msg_store_ets.erl
@@ -13,51 +13,49 @@
-export([new/2, recover/2, insert/3, lookup/2, delete/2, terminate/1]).
-record(store_state, {
- %% ETS table ID
- table,
- %% where the table is stored on disk
- filename
+ %% ETS table ID
+ table,
+ %% where the table is stored on disk
+ filename
}).
-type store_state() :: #store_state{}.
-spec new(file:name_all(), rabbit_types:vhost()) -> store_state().
new(Dir, VHost) ->
- Path = rabbit_mqtt_util:path_for(Dir, VHost),
- TableName = rabbit_mqtt_util:vhost_name_to_table_name(VHost),
- _ = file:delete(Path),
- Tid = ets:new(TableName, [set, public, {keypos, #retained_message.topic}]),
- #store_state{table = Tid, filename = Path}.
+ Path = rabbit_mqtt_util:path_for(Dir, VHost),
+ TableName = rabbit_mqtt_util:vhost_name_to_table_name(VHost),
+ _ = file:delete(Path),
+ Tid = ets:new(TableName, [set, public, {keypos, #retained_message.topic}]),
+ #store_state{table = Tid, filename = Path}.
-spec recover(file:name_all(), rabbit_types:vhost()) ->
- {error, uninitialized} | {ok, store_state()}.
+ {error, uninitialized} | {ok, store_state()}.
recover(Dir, VHost) ->
- Path = rabbit_mqtt_util:path_for(Dir, VHost),
- case ets:file2tab(Path) of
- {ok, Tid} ->
- _ = file:delete(Path),
- {ok, #store_state{table = Tid, filename = Path}};
- {error, _} ->
- {error, uninitialized}
- end.
+ Path = rabbit_mqtt_util:path_for(Dir, VHost),
+ case ets:file2tab(Path) of
+ {ok, Tid} -> _ = file:delete(Path),
+ {ok, #store_state{table = Tid, filename = Path}};
+ {error, _} -> {error, uninitialized}
+ end.
-spec insert(binary(), mqtt_msg(), store_state()) -> ok.
insert(Topic, Msg, #store_state{table = T}) ->
- true = ets:insert(T, #retained_message{topic = Topic, mqtt_msg = Msg}),
- ok.
+ true = ets:insert(T, #retained_message{topic = Topic, mqtt_msg = Msg}),
+ ok.
-spec lookup(binary(), store_state()) -> retained_message() | not_found.
lookup(Topic, #store_state{table = T}) ->
- case ets:lookup(T, Topic) of
- [] -> not_found;
- [Entry] -> Entry
- end.
+ case ets:lookup(T, Topic) of
+ [] -> not_found;
+ [Entry] -> Entry
+ end.
-spec delete(binary(), store_state()) -> ok.
delete(Topic, #store_state{table = T}) ->
- true = ets:delete(T, Topic),
- ok.
+ true = ets:delete(T, Topic),
+ ok.
-spec terminate(store_state()) -> ok.
terminate(#store_state{table = T, filename = Path}) ->
- ok = ets:tab2file(T, Path, [{extended_info, [object_count]}]).
+ ok = ets:tab2file(T, Path, [{extended_info, [object_count]}]).
diff --git a/deps/rabbitmq_mqtt/src/rabbit_mqtt_retained_msg_store_noop.erl b/deps/rabbitmq_mqtt/src/rabbit_mqtt_retained_msg_store_noop.erl
index 5f6f0ef56b..1e62ed5abe 100644
--- a/deps/rabbitmq_mqtt/src/rabbit_mqtt_retained_msg_store_noop.erl
+++ b/deps/rabbitmq_mqtt/src/rabbit_mqtt_retained_msg_store_noop.erl
@@ -12,19 +12,19 @@
-export([new/2, recover/2, insert/3, lookup/2, delete/2, terminate/1]).
new(_Dir, _VHost) ->
- ok.
+ ok.
recover(_Dir, _VHost) ->
- {ok, ok}.
+ {ok, ok}.
insert(_Topic, _Msg, _State) ->
- ok.
+ ok.
lookup(_Topic, _State) ->
- not_found.
+ not_found.
delete(_Topic, _State) ->
- ok.
+ ok.
terminate(_State) ->
- ok.
+ ok.
diff --git a/deps/rabbitmq_mqtt/src/rabbit_mqtt_retainer.erl b/deps/rabbitmq_mqtt/src/rabbit_mqtt_retainer.erl
index 8df5d80ff7..1c632eb597 100644
--- a/deps/rabbitmq_mqtt/src/rabbit_mqtt_retainer.erl
+++ b/deps/rabbitmq_mqtt/src/rabbit_mqtt_retainer.erl
@@ -12,23 +12,15 @@
-behaviour(gen_server).
--export([
- init/1,
- handle_call/3,
- handle_cast/2,
- handle_info/2,
- terminate/2,
- start_link/2
-]).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, start_link/2]).
-export([retain/3, fetch/2, clear/2, store_module/0]).
-define(TIMEOUT, 30_000).
--record(retainer_state, {
- store_mod,
- store
-}).
+-record(retainer_state, {store_mod,
+ store}).
%%----------------------------------------------------------------------------
@@ -54,19 +46,12 @@ clear(Pid, Topic) ->
init([StoreMod, VHost]) ->
process_flag(trap_exit, true),
- State =
- case StoreMod:recover(store_dir(), VHost) of
- {ok, Store} ->
- #retainer_state{
- store = Store,
- store_mod = StoreMod
- };
- {error, _} ->
- #retainer_state{
- store = StoreMod:new(store_dir(), VHost),
- store_mod = StoreMod
- }
- end,
+ State = case StoreMod:recover(store_dir(), VHost) of
+ {ok, Store} -> #retainer_state{store = Store,
+ store_mod = StoreMod};
+ {error, _} -> #retainer_state{store = StoreMod:new(store_dir(), VHost),
+ store_mod = StoreMod}
+ end,
{ok, State}.
-spec store_module() -> undefined | module().
@@ -78,33 +63,26 @@ store_module() ->
%%----------------------------------------------------------------------------
-handle_cast(
- {retain, Topic, Msg},
- State = #retainer_state{store = Store, store_mod = Mod}
-) ->
+handle_cast({retain, Topic, Msg},
+ State = #retainer_state{store = Store, store_mod = Mod}) ->
ok = Mod:insert(Topic, Msg, Store),
{noreply, State};
-handle_cast(
- {clear, Topic},
- State = #retainer_state{store = Store, store_mod = Mod}
-) ->
+handle_cast({clear, Topic},
+ State = #retainer_state{store = Store, store_mod = Mod}) ->
ok = Mod:delete(Topic, Store),
{noreply, State}.
-handle_call(
- {fetch, Topic},
- _From,
- State = #retainer_state{store = Store, store_mod = Mod}
-) ->
- Reply =
- case Mod:lookup(Topic, Store) of
- #retained_message{mqtt_msg = Msg} -> Msg;
- not_found -> undefined
- end,
+handle_call({fetch, Topic}, _From,
+ State = #retainer_state{store = Store, store_mod = Mod}) ->
+ Reply = case Mod:lookup(Topic, Store) of
+ #retained_message{mqtt_msg = Msg} -> Msg;
+ not_found -> undefined
+ end,
{reply, Reply, State}.
handle_info(stop, State) ->
{stop, normal, State};
+
handle_info(Info, State) ->
{stop, {unknown_info, Info}, State}.
diff --git a/deps/rabbitmq_mqtt/src/rabbit_mqtt_retainer_sup.erl b/deps/rabbitmq_mqtt/src/rabbit_mqtt_retainer_sup.erl
index f2b2a38867..eadaab7ca2 100644
--- a/deps/rabbitmq_mqtt/src/rabbit_mqtt_retainer_sup.erl
+++ b/deps/rabbitmq_mqtt/src/rabbit_mqtt_retainer_sup.erl
@@ -8,13 +8,8 @@
-module(rabbit_mqtt_retainer_sup).
-behaviour(supervisor).
--export([
- start_link/1,
- init/1,
- start_child/2, start_child/1,
- child_for_vhost/1,
- delete_child/1
-]).
+-export([start_link/1, init/1, start_child/2,start_child/1, child_for_vhost/1,
+ delete_child/1]).
-spec start_child(binary()) -> supervisor:startchild_ret().
-spec start_child(term(), binary()) -> supervisor:startchild_ret().
@@ -24,13 +19,13 @@ start_link(SupName) ->
-spec child_for_vhost(rabbit_types:vhost()) -> pid().
child_for_vhost(VHost) when is_binary(VHost) ->
- case rabbit_mqtt_retainer_sup:start_child(VHost) of
- {ok, Pid} -> Pid;
- {error, {already_started, Pid}} -> Pid
- end.
+ case rabbit_mqtt_retainer_sup:start_child(VHost) of
+ {ok, Pid} -> Pid;
+ {error, {already_started, Pid}} -> Pid
+ end.
start_child(VHost) when is_binary(VHost) ->
- start_child(rabbit_mqtt_retainer:store_module(), VHost).
+ start_child(rabbit_mqtt_retainer:store_module(), VHost).
start_child(RetainStoreMod, VHost) ->
supervisor:start_child(
@@ -46,20 +41,18 @@ start_child(RetainStoreMod, VHost) ->
).
delete_child(VHost) ->
- Id = vhost_to_atom(VHost),
- ok = supervisor:terminate_child(?MODULE, Id),
- ok = supervisor:delete_child(?MODULE, Id).
+ Id = vhost_to_atom(VHost),
+ ok = supervisor:terminate_child(?MODULE, Id),
+ ok = supervisor:delete_child(?MODULE, Id).
init([]) ->
- Mod = rabbit_mqtt_retainer:store_module(),
- rabbit_log:info(
- "MQTT retained message store: ~tp",
- [Mod]
- ),
- {ok, {
- #{strategy => one_for_one, intensity => 5, period => 5},
- child_specs(Mod, rabbit_vhost:list_names())
- }}.
+ Mod = rabbit_mqtt_retainer:store_module(),
+ rabbit_log:info("MQTT retained message store: ~tp",
+ [Mod]),
+ {ok, {
+ #{strategy => one_for_one, intensity => 5, period => 5},
+ child_specs(Mod, rabbit_vhost:list_names())
+ }}.
child_specs(Mod, VHosts) ->
%% see start_child/2
diff --git a/deps/rabbitmq_mqtt/src/rabbit_mqtt_sup.erl b/deps/rabbitmq_mqtt/src/rabbit_mqtt_sup.erl
index 5aef65bc2d..a04ef73cb9 100644
--- a/deps/rabbitmq_mqtt/src/rabbit_mqtt_sup.erl
+++ b/deps/rabbitmq_mqtt/src/rabbit_mqtt_sup.erl
@@ -23,61 +23,52 @@ init([{Listeners, SslListeners0}]) ->
NumTcpAcceptors = application:get_env(?APP_NAME, num_tcp_acceptors, 10),
ConcurrentConnsSups = application:get_env(?APP_NAME, num_conns_sups, 1),
{ok, SocketOpts} = application:get_env(?APP_NAME, tcp_listen_options),
- {SslOpts, NumSslAcceptors, SslListeners} =
- case SslListeners0 of
- [] ->
- {none, 0, []};
- _ ->
- {
- rabbit_networking:ensure_ssl(),
- application:get_env(?APP_NAME, num_ssl_acceptors, 10),
- case rabbit_networking:poodle_check('MQTT') of
- ok -> SslListeners0;
- danger -> []
- end
- }
- end,
+ {SslOpts, NumSslAcceptors, SslListeners}
+ = case SslListeners0 of
+ [] -> {none, 0, []};
+ _ -> {rabbit_networking:ensure_ssl(),
+ application:get_env(?APP_NAME, num_ssl_acceptors, 10),
+ case rabbit_networking:poodle_check('MQTT') of
+ ok -> SslListeners0;
+ danger -> []
+ end}
+ end,
%% Use separate process group scope per RabbitMQ node. This achieves a local-only
%% process group which requires less memory with millions of connections.
PgScope = list_to_atom(io_lib:format("~s_~s", [?PG_SCOPE, node()])),
persistent_term:put(?PG_SCOPE, PgScope),
{ok,
- {
- #{
- strategy => one_for_all,
- intensity => 10,
- period => 10
- },
- [
- #{
- id => PgScope,
- start => {pg, start_link, [PgScope]},
- restart => transient,
- shutdown => ?WORKER_WAIT,
- type => worker,
- modules => [pg]
- },
- #{
- id => rabbit_mqtt_retainer_sup,
- start =>
- {rabbit_mqtt_retainer_sup, start_link, [{local, rabbit_mqtt_retainer_sup}]},
- restart => transient,
- shutdown => ?SUPERVISOR_WAIT,
- type => supervisor,
- modules => [rabbit_mqtt_retainer_sup]
- }
- | listener_specs(
- fun tcp_listener_spec/1,
- [SocketOpts, NumTcpAcceptors, ConcurrentConnsSups],
- Listeners
- ) ++
- listener_specs(
- fun ssl_listener_spec/1,
- [SocketOpts, SslOpts, NumSslAcceptors, ConcurrentConnsSups],
- SslListeners
- )
- ]
- }}.
+ {#{strategy => one_for_all,
+ intensity => 10,
+ period => 10},
+ [
+ #{id => PgScope,
+ start => {pg, start_link, [PgScope]},
+ restart => transient,
+ shutdown => ?WORKER_WAIT,
+ type => worker,
+ modules => [pg]
+ },
+ #{
+ id => rabbit_mqtt_retainer_sup,
+ start => {rabbit_mqtt_retainer_sup, start_link,
+ [{local, rabbit_mqtt_retainer_sup}]},
+ restart => transient,
+ shutdown => ?SUPERVISOR_WAIT,
+ type => supervisor,
+ modules => [rabbit_mqtt_retainer_sup]
+ }
+ | listener_specs(
+ fun tcp_listener_spec/1,
+ [SocketOpts, NumTcpAcceptors, ConcurrentConnsSups],
+ Listeners
+ ) ++
+ listener_specs(
+ fun ssl_listener_spec/1,
+ [SocketOpts, SslOpts, NumSslAcceptors, ConcurrentConnsSups],
+ SslListeners
+ )
+ ]}}.
-spec stop_listeners() -> ok.
stop_listeners() ->
@@ -98,33 +89,33 @@ listener_specs(Fun, Args, Listeners) ->
tcp_listener_spec([Address, SocketOpts, NumAcceptors, ConcurrentConnsSups]) ->
rabbit_networking:tcp_listener_spec(
- rabbit_mqtt_listener_sup,
- Address,
- SocketOpts,
- transport(?TCP_PROTOCOL),
- rabbit_mqtt_reader,
- [],
- mqtt,
- NumAcceptors,
- ConcurrentConnsSups,
- worker,
- "MQTT TCP listener"
- ).
+ rabbit_mqtt_listener_sup,
+ Address,
+ SocketOpts,
+ transport(?TCP_PROTOCOL),
+ rabbit_mqtt_reader,
+ [],
+ mqtt,
+ NumAcceptors,
+ ConcurrentConnsSups,
+ worker,
+ "MQTT TCP listener"
+ ).
ssl_listener_spec([Address, SocketOpts, SslOpts, NumAcceptors, ConcurrentConnsSups]) ->
rabbit_networking:tcp_listener_spec(
- rabbit_mqtt_listener_sup,
- Address,
- SocketOpts ++ SslOpts,
- transport(?TLS_PROTOCOL),
- rabbit_mqtt_reader,
- [],
- 'mqtt/ssl',
- NumAcceptors,
- ConcurrentConnsSups,
- worker,
- "MQTT TLS listener"
- ).
+ rabbit_mqtt_listener_sup,
+ Address,
+ SocketOpts ++ SslOpts,
+ transport(?TLS_PROTOCOL),
+ rabbit_mqtt_reader,
+ [],
+ 'mqtt/ssl',
+ NumAcceptors,
+ ConcurrentConnsSups,
+ worker,
+ "MQTT TLS listener"
+ ).
transport(?TCP_PROTOCOL) ->
ranch_tcp;
diff --git a/deps/rabbitmq_mqtt/src/rabbit_mqtt_util.erl b/deps/rabbitmq_mqtt/src/rabbit_mqtt_util.erl
index 89428c5965..d098d3ff93 100644
--- a/deps/rabbitmq_mqtt/src/rabbit_mqtt_util.erl
+++ b/deps/rabbitmq_mqtt/src/rabbit_mqtt_util.erl
@@ -11,21 +11,20 @@
-include("rabbit_mqtt.hrl").
-include("rabbit_mqtt_packet.hrl").
--export([
- queue_name_bin/2,
- qos_from_queue_name/2,
- env/1,
- table_lookup/2,
- path_for/2,
- path_for/3,
- vhost_name_to_table_name/1,
- register_clientid/2,
- remove_duplicate_clientid_connections/2,
- init_sparkplug/0,
- mqtt_to_amqp/1,
- amqp_to_mqtt/1,
- truncate_binary/2
-]).
+-export([queue_name_bin/2,
+ qos_from_queue_name/2,
+ env/1,
+ table_lookup/2,
+ path_for/2,
+ path_for/3,
+ vhost_name_to_table_name/1,
+ register_clientid/2,
+ remove_duplicate_clientid_connections/2,
+ init_sparkplug/0,
+ mqtt_to_amqp/1,
+ amqp_to_mqtt/1,
+ truncate_binary/2
+ ]).
-define(MAX_TOPIC_TRANSLATION_CACHE_SIZE, 12).
-define(SPARKPLUG_MP_MQTT_TO_AMQP, sparkplug_mp_mqtt_to_amqp).
@@ -73,8 +72,7 @@ init_sparkplug() ->
-spec mqtt_to_amqp(binary()) -> binary().
mqtt_to_amqp(Topic) ->
- T =
- case persistent_term:get(?SPARKPLUG_MP_MQTT_TO_AMQP, no_sparkplug) of
+ T = case persistent_term:get(?SPARKPLUG_MP_MQTT_TO_AMQP, no_sparkplug) of
no_sparkplug ->
Topic;
M2A_SpRe ->
@@ -104,13 +102,12 @@ amqp_to_mqtt(Topic) ->
end.
cached(CacheName, Fun, Arg) ->
- Cache =
- case get(CacheName) of
- undefined ->
- [];
- Other ->
- Other
- end,
+ Cache = case get(CacheName) of
+ undefined ->
+ [];
+ Other ->
+ Other
+ end,
case lists:keyfind(Arg, 1, Cache) of
{_, V} ->
V;
@@ -145,11 +142,11 @@ env(Key) ->
coerce_env_value(default_pass, Val) -> rabbit_data_coercion:to_binary(Val);
coerce_env_value(default_user, Val) -> rabbit_data_coercion:to_binary(Val);
-coerce_env_value(exchange, Val) -> rabbit_data_coercion:to_binary(Val);
-coerce_env_value(vhost, Val) -> rabbit_data_coercion:to_binary(Val);
-coerce_env_value(_, Val) -> Val.
+coerce_env_value(exchange, Val) -> rabbit_data_coercion:to_binary(Val);
+coerce_env_value(vhost, Val) -> rabbit_data_coercion:to_binary(Val);
+coerce_env_value(_, Val) -> Val.
--spec table_lookup(rabbit_framing:amqp_table() | undefined, binary()) ->
+-spec table_lookup(rabbit_framing:amqp_table() | undefined, binary()) ->
tuple() | undefined.
table_lookup(undefined, _Key) ->
undefined;
@@ -164,11 +161,11 @@ vhost_name_to_dir_name(VHost, Suffix) ->
-spec path_for(file:name_all(), rabbit_types:vhost()) -> file:filename_all().
path_for(Dir, VHost) ->
- filename:join(Dir, vhost_name_to_dir_name(VHost)).
+ filename:join(Dir, vhost_name_to_dir_name(VHost)).
-spec path_for(file:name_all(), rabbit_types:vhost(), string()) -> file:filename_all().
path_for(Dir, VHost, Suffix) ->
- filename:join(Dir, vhost_name_to_dir_name(VHost, Suffix)).
+ filename:join(Dir, vhost_name_to_dir_name(VHost, Suffix)).
-spec vhost_name_to_table_name(rabbit_types:vhost()) ->
atom().
@@ -177,9 +174,8 @@ vhost_name_to_table_name(VHost) ->
list_to_atom("rabbit_mqtt_retained_" ++ rabbit_misc:format("~36.16.0b", [Num])).
-spec register_clientid(rabbit_types:vhost(), binary()) -> ok.
-register_clientid(Vhost, ClientId) when
- is_binary(Vhost), is_binary(ClientId)
-->
+register_clientid(Vhost, ClientId)
+ when is_binary(Vhost), is_binary(ClientId) ->
PgGroup = {Vhost, ClientId},
ok = pg:join(persistent_term:get(?PG_SCOPE), PgGroup, self()),
case rabbit_mqtt_ff:track_client_id_in_ra() of
@@ -187,12 +183,10 @@ register_clientid(Vhost, ClientId) when
%% Ra node takes care of removing duplicate client ID connections.
ok;
false ->
- ok = erpc:multicast(
- [node() | nodes()],
- ?MODULE,
- remove_duplicate_clientid_connections,
- [PgGroup, self()]
- )
+ ok = erpc:multicast([node() | nodes()],
+ ?MODULE,
+ remove_duplicate_clientid_connections,
+ [PgGroup, self()])
end.
-spec remove_duplicate_clientid_connections({rabbit_types:vhost(), binary()}, pid()) -> ok.
@@ -200,24 +194,18 @@ remove_duplicate_clientid_connections(PgGroup, PidToKeep) ->
try persistent_term:get(?PG_SCOPE) of
PgScope ->
Pids = pg:get_local_members(PgScope, PgGroup),
- lists:foreach(
- fun(Pid) ->
- gen_server:cast(Pid, duplicate_id)
- end,
- Pids -- [PidToKeep]
- )
- catch
- _:badarg ->
- %% MQTT supervision tree on this node not fully started
- ok
+ lists:foreach(fun(Pid) ->
+ gen_server:cast(Pid, duplicate_id)
+ end, Pids -- [PidToKeep])
+ catch _:badarg ->
+ %% MQTT supervision tree on this node not fully started
+ ok
end.
-spec truncate_binary(binary(), non_neg_integer()) -> binary().
-truncate_binary(Bin, Size) when
- is_binary(Bin) andalso byte_size(Bin) =< Size
-->
+truncate_binary(Bin, Size)
+ when is_binary(Bin) andalso byte_size(Bin) =< Size ->
Bin;
-truncate_binary(Bin, Size) when
- is_binary(Bin)
-->
+truncate_binary(Bin, Size)
+ when is_binary(Bin) ->
binary:part(Bin, 0, Size).
diff --git a/deps/rabbitmq_mqtt/test/auth_SUITE.erl b/deps/rabbitmq_mqtt/test/auth_SUITE.erl
index f2ad72f857..63ac362842 100644
--- a/deps/rabbitmq_mqtt/test/auth_SUITE.erl
+++ b/deps/rabbitmq_mqtt/test/auth_SUITE.erl
@@ -5,10 +5,8 @@
%% Copyright (c) 2007-2023 VMware, Inc. or its affiliates. All rights reserved.
%%
-module(auth_SUITE).
--compile([
- export_all,
- nowarn_export_all
-]).
+-compile([export_all,
+ nowarn_export_all]).
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
@@ -16,78 +14,79 @@
%% defined in MQTT v4 and v5 (not in v3)
-define(SUBACK_FAILURE, 16#80).
--define(FAIL_IF_CRASH_LOG, {["Generic server.*terminating"], fun() -> ct:fail(crash_detected) end}).
+-define(FAIL_IF_CRASH_LOG, {["Generic server.*terminating"],
+ fun () -> ct:fail(crash_detected) end}).
-import(rabbit_ct_broker_helpers, [rpc/5]).
all() ->
- [
- {group, anonymous_no_ssl_user},
- {group, anonymous_ssl_user},
- {group, no_ssl_user},
- {group, ssl_user},
- {group, client_id_propagation},
- {group, authz},
- {group, limit}
- ].
+ [{group, anonymous_no_ssl_user},
+ {group, anonymous_ssl_user},
+ {group, no_ssl_user},
+ {group, ssl_user},
+ {group, client_id_propagation},
+ {group, authz},
+ {group, limit}].
groups() ->
- [
- {anonymous_ssl_user, [], [
- anonymous_auth_success,
- user_credentials_auth,
- ssl_user_auth_success,
- ssl_user_vhost_not_allowed,
- ssl_user_vhost_parameter_mapping_success,
- ssl_user_vhost_parameter_mapping_not_allowed,
- ssl_user_vhost_parameter_mapping_vhost_does_not_exist,
- ssl_user_port_vhost_mapping_takes_precedence_over_cert_vhost_mapping
- ]},
- {anonymous_no_ssl_user, [], [
- anonymous_auth_success,
- user_credentials_auth,
- port_vhost_mapping_success,
- port_vhost_mapping_success_no_mapping,
- port_vhost_mapping_not_allowed,
- port_vhost_mapping_vhost_does_not_exist
- %% SSL auth will succeed, because we cannot ignore anonymous
- ]},
- {ssl_user, [], [
- anonymous_auth_failure,
- user_credentials_auth,
- ssl_user_auth_success,
- ssl_user_vhost_not_allowed,
- ssl_user_vhost_parameter_mapping_success,
- ssl_user_vhost_parameter_mapping_not_allowed,
- ssl_user_vhost_parameter_mapping_vhost_does_not_exist,
- ssl_user_port_vhost_mapping_takes_precedence_over_cert_vhost_mapping
- ]},
- {no_ssl_user, [], [
- anonymous_auth_failure,
- user_credentials_auth,
- ssl_user_auth_failure,
- port_vhost_mapping_success,
- port_vhost_mapping_success_no_mapping,
- port_vhost_mapping_not_allowed,
- port_vhost_mapping_vhost_does_not_exist
- ]},
- {client_id_propagation, [], [client_id_propagation]},
- {authz, [], [
- no_queue_bind_permission,
- no_queue_unbind_permission,
- no_queue_consume_permission,
- no_queue_consume_permission_on_connect,
- no_queue_delete_permission,
- no_queue_declare_permission,
- no_publish_permission,
- no_topic_read_permission,
- no_topic_write_permission,
- loopback_user_connects_from_remote_host
- ]},
- {limit, [], [
- vhost_connection_limit,
- vhost_queue_limit,
- user_connection_limit
- ]}
+ [{anonymous_ssl_user, [],
+ [anonymous_auth_success,
+ user_credentials_auth,
+ ssl_user_auth_success,
+ ssl_user_vhost_not_allowed,
+ ssl_user_vhost_parameter_mapping_success,
+ ssl_user_vhost_parameter_mapping_not_allowed,
+ ssl_user_vhost_parameter_mapping_vhost_does_not_exist,
+ ssl_user_port_vhost_mapping_takes_precedence_over_cert_vhost_mapping
+ ]},
+ {anonymous_no_ssl_user, [],
+ [anonymous_auth_success,
+ user_credentials_auth,
+ port_vhost_mapping_success,
+ port_vhost_mapping_success_no_mapping,
+ port_vhost_mapping_not_allowed,
+ port_vhost_mapping_vhost_does_not_exist
+ %% SSL auth will succeed, because we cannot ignore anonymous
+ ]},
+ {ssl_user, [],
+ [anonymous_auth_failure,
+ user_credentials_auth,
+ ssl_user_auth_success,
+ ssl_user_vhost_not_allowed,
+ ssl_user_vhost_parameter_mapping_success,
+ ssl_user_vhost_parameter_mapping_not_allowed,
+ ssl_user_vhost_parameter_mapping_vhost_does_not_exist,
+ ssl_user_port_vhost_mapping_takes_precedence_over_cert_vhost_mapping
+ ]},
+ {no_ssl_user, [],
+ [anonymous_auth_failure,
+ user_credentials_auth,
+ ssl_user_auth_failure,
+ port_vhost_mapping_success,
+ port_vhost_mapping_success_no_mapping,
+ port_vhost_mapping_not_allowed,
+ port_vhost_mapping_vhost_does_not_exist
+ ]},
+ {client_id_propagation, [],
+ [client_id_propagation]
+ },
+ {authz, [],
+ [no_queue_bind_permission,
+ no_queue_unbind_permission,
+ no_queue_consume_permission,
+ no_queue_consume_permission_on_connect,
+ no_queue_delete_permission,
+ no_queue_declare_permission,
+ no_publish_permission,
+ no_topic_read_permission,
+ no_topic_write_permission,
+ loopback_user_connects_from_remote_host
+ ]
+ },
+ {limit, [],
+ [vhost_connection_limit,
+ vhost_queue_limit,
+ user_connection_limit
+ ]}
].
init_per_suite(Config) ->
@@ -101,29 +100,19 @@ init_per_group(authz, Config0) ->
User = <<"mqtt-user">>,
Password = <<"mqtt-password">>,
VHost = <<"mqtt-vhost">>,
- MqttConfig =
- {rabbitmq_mqtt, [
- {default_user, User},
- {default_pass, Password},
- {allow_anonymous, true},
- {vhost, VHost},
- {exchange, <<"amq.topic">>}
- ]},
- Config1 = rabbit_ct_helpers:run_setup_steps(
- rabbit_ct_helpers:merge_app_env(Config0, MqttConfig),
- rabbit_ct_broker_helpers:setup_steps() ++
- rabbit_ct_client_helpers:setup_steps()
- ),
+ MqttConfig = {rabbitmq_mqtt, [{default_user, User}
+ ,{default_pass, Password}
+ ,{allow_anonymous, true}
+ ,{vhost, VHost}
+ ,{exchange, <<"amq.topic">>}
+ ]},
+ Config1 = rabbit_ct_helpers:run_setup_steps(rabbit_ct_helpers:merge_app_env(Config0, MqttConfig),
+ rabbit_ct_broker_helpers:setup_steps() ++
+ rabbit_ct_client_helpers:setup_steps()),
rabbit_ct_broker_helpers:add_user(Config1, User, Password),
rabbit_ct_broker_helpers:add_vhost(Config1, VHost),
- [Log | _] = rpc(Config1, 0, rabbit, log_locations, []),
- [
- {mqtt_user, User},
- {mqtt_vhost, VHost},
- {mqtt_password, Password},
- {log_location, Log}
- | Config1
- ];
+ [Log|_] = rpc(Config1, 0, rabbit, log_locations, []),
+ [{mqtt_user, User}, {mqtt_vhost, VHost}, {mqtt_password, Password}, {log_location, Log}|Config1];
init_per_group(Group, Config) ->
Suffix = rabbit_ct_helpers:testcase_absname(Config, "", "-"),
Config1 = rabbit_ct_helpers:set_config(Config, [
@@ -132,77 +121,56 @@ init_per_group(Group, Config) ->
]),
MqttConfig = mqtt_config(Group),
AuthConfig = auth_config(Group),
- rabbit_ct_helpers:run_setup_steps(
- Config1,
- [
- fun(Conf) ->
- case MqttConfig of
- undefined -> Conf;
- _ -> merge_app_env(MqttConfig, Conf)
- end
- end
- ] ++
- [
- fun(Conf) ->
- case AuthConfig of
- undefined -> Conf;
- _ -> merge_app_env(AuthConfig, Conf)
- end
- end
- ] ++
- rabbit_ct_broker_helpers:setup_steps() ++
- rabbit_ct_client_helpers:setup_steps()
- ).
+ rabbit_ct_helpers:run_setup_steps(Config1,
+ [ fun(Conf) -> case MqttConfig of
+ undefined -> Conf;
+ _ -> merge_app_env(MqttConfig, Conf)
+ end
+ end] ++
+ [ fun(Conf) -> case AuthConfig of
+ undefined -> Conf;
+ _ -> merge_app_env(AuthConfig, Conf)
+ end
+ end ] ++
+ rabbit_ct_broker_helpers:setup_steps() ++
+ rabbit_ct_client_helpers:setup_steps()).
end_per_group(_, Config) ->
- rabbit_ct_helpers:run_teardown_steps(
- Config,
- rabbit_ct_client_helpers:teardown_steps() ++
- rabbit_ct_broker_helpers:teardown_steps()
- ).
+ rabbit_ct_helpers:run_teardown_steps(Config,
+ rabbit_ct_client_helpers:teardown_steps() ++
+ rabbit_ct_broker_helpers:teardown_steps()).
merge_app_env(MqttConfig, Config) ->
rabbit_ct_helpers:merge_app_env(Config, MqttConfig).
mqtt_config(anonymous_ssl_user) ->
- {rabbitmq_mqtt, [
- {ssl_cert_login, true},
- {allow_anonymous, true}
- ]};
+ {rabbitmq_mqtt, [{ssl_cert_login, true},
+ {allow_anonymous, true}]};
mqtt_config(anonymous_no_ssl_user) ->
- {rabbitmq_mqtt, [
- {ssl_cert_login, false},
- {allow_anonymous, true}
- ]};
+ {rabbitmq_mqtt, [{ssl_cert_login, false},
+ {allow_anonymous, true}]};
mqtt_config(ssl_user) ->
- {rabbitmq_mqtt, [
- {ssl_cert_login, true},
- {allow_anonymous, false}
- ]};
+ {rabbitmq_mqtt, [{ssl_cert_login, true},
+ {allow_anonymous, false}]};
mqtt_config(no_ssl_user) ->
- {rabbitmq_mqtt, [
- {ssl_cert_login, false},
- {allow_anonymous, false}
- ]};
+ {rabbitmq_mqtt, [{ssl_cert_login, false},
+ {allow_anonymous, false}]};
mqtt_config(client_id_propagation) ->
- {rabbitmq_mqtt, [
- {ssl_cert_login, true},
- {allow_anonymous, true}
- ]};
+ {rabbitmq_mqtt, [{ssl_cert_login, true},
+ {allow_anonymous, true}]};
mqtt_config(_) ->
undefined.
auth_config(client_id_propagation) ->
{rabbit, [
- {auth_backends, [rabbit_auth_backend_mqtt_mock]}
- ]};
+ {auth_backends, [rabbit_auth_backend_mqtt_mock]}
+ ]
+ };
auth_config(_) ->
undefined.
-init_per_testcase(Testcase, Config) when
- Testcase == ssl_user_auth_success;
- Testcase == ssl_user_auth_failure
-->
+init_per_testcase(Testcase, Config) when Testcase == ssl_user_auth_success;
+ Testcase == ssl_user_auth_failure ->
Config1 = set_cert_user_on_default_vhost(Config),
rabbit_ct_helpers:testcase_started(Config1, Testcase);
init_per_testcase(ssl_user_vhost_parameter_mapping_success, Config) ->
@@ -223,10 +191,8 @@ init_per_testcase(user_credentials_auth, Config) ->
Pass = <<"new-user-pass">>,
ok = rabbit_ct_broker_helpers:add_user(Config, 0, User, Pass),
ok = rabbit_ct_broker_helpers:set_full_permissions(Config, User, <<"/">>),
- Config1 = rabbit_ct_helpers:set_config(Config, [
- {new_user, User},
- {new_user_pass, Pass}
- ]),
+ Config1 = rabbit_ct_helpers:set_config(Config, [{new_user, User},
+ {new_user_pass, Pass}]),
rabbit_ct_helpers:testcase_started(Config1, user_credentials_auth);
init_per_testcase(ssl_user_vhost_not_allowed, Config) ->
Config1 = set_cert_user_on_default_vhost(Config),
@@ -239,9 +205,7 @@ init_per_testcase(ssl_user_vhost_parameter_mapping_vhost_does_not_exist, Config)
Config2 = set_vhost_for_cert_user(Config1, User),
VhostForCertUser = ?config(temp_vhost_for_ssl_user, Config2),
ok = rabbit_ct_broker_helpers:delete_vhost(Config, VhostForCertUser),
- rabbit_ct_helpers:testcase_started(
- Config1, ssl_user_vhost_parameter_mapping_vhost_does_not_exist
- );
+ rabbit_ct_helpers:testcase_started(Config1, ssl_user_vhost_parameter_mapping_vhost_does_not_exist);
init_per_testcase(port_vhost_mapping_success, Config) ->
User = <<"guest">>,
Config1 = set_vhost_for_port_vhost_mapping_user(Config, User),
@@ -251,12 +215,9 @@ init_per_testcase(port_vhost_mapping_success_no_mapping, Config) ->
User = <<"guest">>,
Config1 = set_vhost_for_port_vhost_mapping_user(Config, User),
PortToVHostMappingParameter = [
- {<<"1">>, <<"unlikely to exist">>},
- {<<"2">>, <<"unlikely to exist">>}
- ],
- ok = rabbit_ct_broker_helpers:set_global_parameter(
- Config, mqtt_port_to_vhost_mapping, PortToVHostMappingParameter
- ),
+ {<<"1">>, <<"unlikely to exist">>},
+ {<<"2">>, <<"unlikely to exist">>}],
+ ok = rabbit_ct_broker_helpers:set_global_parameter(Config, mqtt_port_to_vhost_mapping, PortToVHostMappingParameter),
VHost = ?config(temp_vhost_for_port_mapping, Config1),
rabbit_ct_broker_helpers:clear_permissions(Config1, User, VHost),
rabbit_ct_helpers:testcase_started(Config1, port_vhost_mapping_success_no_mapping);
@@ -284,9 +245,7 @@ init_per_testcase(ssl_user_port_vhost_mapping_takes_precedence_over_cert_vhost_m
rabbit_ct_broker_helpers:clear_permissions(Config3, User, VhostForPortMapping),
rabbit_ct_broker_helpers:clear_permissions(Config3, User, <<"/">>),
- rabbit_ct_helpers:testcase_started(
- Config3, ssl_user_port_vhost_mapping_takes_precedence_over_cert_vhost_mapping
- );
+ rabbit_ct_helpers:testcase_started(Config3, ssl_user_port_vhost_mapping_takes_precedence_over_cert_vhost_mapping);
init_per_testcase(Testcase, Config) ->
rabbit_ct_helpers:testcase_started(Config, Testcase).
@@ -309,9 +268,7 @@ set_vhost_for_cert_user(Config, User) ->
],
ok = rabbit_ct_broker_helpers:add_vhost(Config, VhostForCertUser),
ok = rabbit_ct_broker_helpers:set_full_permissions(Config, User, VhostForCertUser),
- ok = rabbit_ct_broker_helpers:set_global_parameter(
- Config, mqtt_default_vhosts, UserToVHostMappingParameter
- ),
+ ok = rabbit_ct_broker_helpers:set_global_parameter(Config, mqtt_default_vhosts, UserToVHostMappingParameter),
rabbit_ct_helpers:set_config(Config, [{temp_vhost_for_ssl_user, VhostForCertUser}]).
set_vhost_for_port_vhost_mapping_user(Config, User) ->
@@ -319,29 +276,24 @@ set_vhost_for_port_vhost_mapping_user(Config, User) ->
Port = rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_mqtt),
TlsPort = rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_mqtt_tls),
PortToVHostMappingParameter = [
- {integer_to_binary(Port), VhostForPortMapping},
- {<<"1884">>, <<"vhost2">>},
+ {integer_to_binary(Port), VhostForPortMapping},
+ {<<"1884">>, <<"vhost2">>},
{integer_to_binary(TlsPort), VhostForPortMapping},
- {<<"8884">>, <<"vhost2">>}
+ {<<"8884">>, <<"vhost2">>}
+
],
ok = rabbit_ct_broker_helpers:add_vhost(Config, VhostForPortMapping),
ok = rabbit_ct_broker_helpers:set_full_permissions(Config, User, VhostForPortMapping),
- ok = rabbit_ct_broker_helpers:set_global_parameter(
- Config, mqtt_port_to_vhost_mapping, PortToVHostMappingParameter
- ),
+ ok = rabbit_ct_broker_helpers:set_global_parameter(Config, mqtt_port_to_vhost_mapping, PortToVHostMappingParameter),
rabbit_ct_helpers:set_config(Config, [{temp_vhost_for_port_mapping, VhostForPortMapping}]).
-end_per_testcase(Testcase, Config) when
- Testcase == ssl_user_auth_success;
- Testcase == ssl_user_auth_failure;
- Testcase == ssl_user_vhost_not_allowed
-->
+end_per_testcase(Testcase, Config) when Testcase == ssl_user_auth_success;
+ Testcase == ssl_user_auth_failure;
+ Testcase == ssl_user_vhost_not_allowed ->
delete_cert_user(Config),
rabbit_ct_helpers:testcase_finished(Config, Testcase);
-end_per_testcase(TestCase, Config) when
- TestCase == ssl_user_vhost_parameter_mapping_success;
- TestCase == ssl_user_vhost_parameter_mapping_not_allowed
-->
+end_per_testcase(TestCase, Config) when TestCase == ssl_user_vhost_parameter_mapping_success;
+ TestCase == ssl_user_vhost_parameter_mapping_not_allowed ->
delete_cert_user(Config),
VhostForCertUser = ?config(temp_vhost_for_ssl_user, Config),
ok = rabbit_ct_broker_helpers:delete_vhost(Config, VhostForCertUser),
@@ -349,19 +301,15 @@ end_per_testcase(TestCase, Config) when
rabbit_ct_helpers:testcase_finished(Config, TestCase);
end_per_testcase(user_credentials_auth, Config) ->
User = ?config(new_user, Config),
- {ok, _} = rabbit_ct_broker_helpers:rabbitmqctl(Config, 0, ["delete_user", User]),
+ {ok,_} = rabbit_ct_broker_helpers:rabbitmqctl(Config, 0, ["delete_user", User]),
rabbit_ct_helpers:testcase_finished(Config, user_credentials_auth);
end_per_testcase(ssl_user_vhost_parameter_mapping_vhost_does_not_exist, Config) ->
delete_cert_user(Config),
ok = rabbit_ct_broker_helpers:clear_global_parameter(Config, mqtt_default_vhosts),
- rabbit_ct_helpers:testcase_finished(
- Config, ssl_user_vhost_parameter_mapping_vhost_does_not_exist
- );
-end_per_testcase(Testcase, Config) when
- Testcase == port_vhost_mapping_success;
- Testcase == port_vhost_mapping_not_allowed;
- Testcase == port_vhost_mapping_success_no_mapping
-->
+ rabbit_ct_helpers:testcase_finished(Config, ssl_user_vhost_parameter_mapping_vhost_does_not_exist);
+end_per_testcase(Testcase, Config) when Testcase == port_vhost_mapping_success;
+ Testcase == port_vhost_mapping_not_allowed;
+ Testcase == port_vhost_mapping_success_no_mapping ->
User = <<"guest">>,
rabbit_ct_broker_helpers:set_full_permissions(Config, User, <<"/">>),
VHost = ?config(temp_vhost_for_port_mapping, Config),
@@ -382,31 +330,24 @@ end_per_testcase(ssl_user_port_vhost_mapping_takes_precedence_over_cert_vhost_ma
VHostForPortVHostMapping = ?config(temp_vhost_for_port_mapping, Config),
ok = rabbit_ct_broker_helpers:delete_vhost(Config, VHostForPortVHostMapping),
ok = rabbit_ct_broker_helpers:clear_global_parameter(Config, mqtt_port_to_vhost_mapping),
- rabbit_ct_helpers:testcase_finished(
- Config, ssl_user_port_vhost_mapping_takes_precedence_over_cert_vhost_mapping
- );
-end_per_testcase(Testcase, Config) when
- Testcase == no_queue_bind_permission;
- Testcase == no_queue_unbind_permission;
- Testcase == no_queue_consume_permission;
- Testcase == no_queue_consume_permission_on_connect;
- Testcase == no_queue_delete_permission;
- Testcase == no_queue_declare_permission;
- Testcase == no_publish_permission;
- Testcase == no_topic_read_permission;
- Testcase == no_topic_write_permission;
- Testcase == loopback_user_connects_from_remote_host
-->
+ rabbit_ct_helpers:testcase_finished(Config, ssl_user_port_vhost_mapping_takes_precedence_over_cert_vhost_mapping);
+end_per_testcase(Testcase, Config) when Testcase == no_queue_bind_permission;
+ Testcase == no_queue_unbind_permission;
+ Testcase == no_queue_consume_permission;
+ Testcase == no_queue_consume_permission_on_connect;
+ Testcase == no_queue_delete_permission;
+ Testcase == no_queue_declare_permission;
+ Testcase == no_publish_permission;
+ Testcase == no_topic_read_permission;
+ Testcase == no_topic_write_permission;
+ Testcase == loopback_user_connects_from_remote_host ->
%% So let's wait before logs are surely flushed
Marker = "MQTT_AUTH_SUITE_MARKER",
rpc(Config, 0, rabbit_log, error, [Marker]),
- wait_log(Config, [{[Marker], fun() -> stop end}]),
+ wait_log(Config, [{[Marker], fun () -> stop end}]),
%% Preserve file contents in case some investigation is needed, before truncating.
- file:copy(
- ?config(log_location, Config),
- iolist_to_binary([?config(log_location, Config), ".", atom_to_binary(Testcase)])
- ),
+ file:copy(?config(log_location, Config), iolist_to_binary([?config(log_location, Config), ".", atom_to_binary(Testcase)])),
%% And provide an empty log file for the next test in this group
file:write_file(?config(log_location, Config), <<>>),
@@ -417,7 +358,7 @@ end_per_testcase(Testcase, Config) ->
delete_cert_user(Config) ->
User = ?config(temp_ssl_user, Config),
- {ok, _} = rabbit_ct_broker_helpers:rabbitmqctl(Config, 0, ["delete_user", User]).
+ {ok,_} = rabbit_ct_broker_helpers:rabbitmqctl(Config, 0, ["delete_user", User]).
anonymous_auth_success(Config) ->
expect_successful_connection(fun connect_anonymous/1, Config).
@@ -425,6 +366,7 @@ anonymous_auth_success(Config) ->
anonymous_auth_failure(Config) ->
expect_authentication_failure(fun connect_anonymous/1, Config).
+
ssl_user_auth_success(Config) ->
expect_successful_connection(fun connect_ssl/1, Config).
@@ -437,38 +379,31 @@ user_credentials_auth(Config) ->
expect_successful_connection(
fun(Conf) -> connect_user(NewUser, NewUserPass, Conf) end,
- Config
- ),
+ Config),
expect_successful_connection(
fun(Conf) -> connect_user(<<"guest">>, <<"guest">>, Conf) end,
- Config
- ),
+ Config),
expect_successful_connection(
fun(Conf) -> connect_user(<<"/:guest">>, <<"guest">>, Conf) end,
- Config
- ),
+ Config),
expect_authentication_failure(
fun(Conf) -> connect_user(NewUser, <<"invalid_pass">>, Conf) end,
- Config
- ),
+ Config),
expect_authentication_failure(
fun(Conf) -> connect_user(undefined, <<"pass">>, Conf) end,
- Config
- ),
+ Config),
expect_authentication_failure(
fun(Conf) -> connect_user(NewUser, undefined, Conf) end,
- Config
- ),
+ Config),
expect_authentication_failure(
fun(Conf) -> connect_user(<<"non-existing-vhost:guest">>, <<"guest">>, Conf) end,
- Config
- ).
+ Config).
ssl_user_vhost_parameter_mapping_success(Config) ->
expect_successful_connection(fun connect_ssl/1, Config).
@@ -485,8 +420,7 @@ ssl_user_vhost_parameter_mapping_vhost_does_not_exist(Config) ->
port_vhost_mapping_success(Config) ->
expect_successful_connection(
fun(Conf) -> connect_user(<<"guest">>, <<"guest">>, Conf) end,
- Config
- ).
+ Config).
port_vhost_mapping_success_no_mapping(Config) ->
%% no vhost mapping for the port, falling back to default vhost
@@ -516,92 +450,68 @@ connect_anonymous(Config) ->
connect_anonymous(Config, ClientId) ->
P = rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_mqtt),
- emqtt:start_link([
- {host, "localhost"},
- {port, P},
- {clientid, ClientId},
- {proto_ver, v4}
- ]).
+ emqtt:start_link([{host, "localhost"},
+ {port, P},
+ {clientid, ClientId},
+ {proto_ver, v4}]).
connect_ssl(Config) ->
CertsDir = ?config(rmq_certsdir, Config),
- SSLConfig = [
- {cacertfile, filename:join([CertsDir, "testca", "cacert.pem"])},
- {certfile, filename:join([CertsDir, "client", "cert.pem"])},
- {keyfile, filename:join([CertsDir, "client", "key.pem"])}
- ],
+ SSLConfig = [{cacertfile, filename:join([CertsDir, "testca", "cacert.pem"])},
+ {certfile, filename:join([CertsDir, "client", "cert.pem"])},
+ {keyfile, filename:join([CertsDir, "client", "key.pem"])}],
P = rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_mqtt_tls),
- emqtt:start_link([
- {host, "localhost"},
- {port, P},
- {clientid, <<"simpleClient">>},
- {proto_ver, v4},
- {ssl, true},
- {ssl_opts, SSLConfig}
- ]).
+ emqtt:start_link([{host, "localhost"},
+ {port, P},
+ {clientid, <<"simpleClient">>},
+ {proto_ver, v4},
+ {ssl, true},
+ {ssl_opts, SSLConfig}]).
client_id_propagation(Config) ->
- ok = rabbit_ct_broker_helpers:add_code_path_to_all_nodes(
- Config,
- rabbit_auth_backend_mqtt_mock
- ),
+ ok = rabbit_ct_broker_helpers:add_code_path_to_all_nodes(Config,
+ rabbit_auth_backend_mqtt_mock),
%% setup creates the ETS table required for the mqtt auth mock
%% it blocks indefinitely so we need to spawn
Self = self(),
_ = spawn(
- fun() ->
- rpc(Config, 0, rabbit_auth_backend_mqtt_mock, setup, [Self])
- end
- ),
+ fun () ->
+ rpc(Config, 0, rabbit_auth_backend_mqtt_mock, setup, [Self])
+ end),
%% the setup process will notify us
receive
ok -> ok
- after 3000 -> ct:fail("timeout waiting for rabbit_auth_backend_mqtt_mock:setup/1")
+ after
+ 3000 -> ct:fail("timeout waiting for rabbit_auth_backend_mqtt_mock:setup/1")
end,
ClientId = <<"client-id-propagation">>,
- {ok, C} = connect_user(
- <<"fake-user">>,
- <<"fake-password">>,
- Config,
- ClientId
- ),
+ {ok, C} = connect_user(<<"fake-user">>, <<"fake-password">>,
+ Config, ClientId),
{ok, _} = emqtt:connect(C),
{ok, _, _} = emqtt:subscribe(C, <<"TopicA">>),
- [{authentication, AuthProps}] = rpc(
- Config,
- 0,
- rabbit_auth_backend_mqtt_mock,
- get,
- [authentication]
- ),
+ [{authentication, AuthProps}] = rpc(Config, 0,
+ rabbit_auth_backend_mqtt_mock,
+ get,
+ [authentication]),
?assertEqual(ClientId, proplists:get_value(client_id, AuthProps)),
- [{vhost_access, AuthzData}] = rpc(
- Config,
- 0,
- rabbit_auth_backend_mqtt_mock,
- get,
- [vhost_access]
- ),
+ [{vhost_access, AuthzData}] = rpc(Config, 0,
+ rabbit_auth_backend_mqtt_mock,
+ get,
+ [vhost_access]),
?assertEqual(ClientId, maps:get(<<"client_id">>, AuthzData)),
- [{resource_access, AuthzContext}] = rpc(
- Config,
- 0,
- rabbit_auth_backend_mqtt_mock,
- get,
- [resource_access]
- ),
+ [{resource_access, AuthzContext}] = rpc(Config, 0,
+ rabbit_auth_backend_mqtt_mock,
+ get,
+ [resource_access]),
?assertEqual(true, maps:size(AuthzContext) > 0),
?assertEqual(ClientId, maps:get(<<"client_id">>, AuthzContext)),
- [{topic_access, TopicContext}] = rpc(
- Config,
- 0,
- rabbit_auth_backend_mqtt_mock,
- get,
- [topic_access]
- ),
+ [{topic_access, TopicContext}] = rpc(Config, 0,
+ rabbit_auth_backend_mqtt_mock,
+ get,
+ [topic_access]),
VariableMap = maps:get(variable_map, TopicContext),
?assertEqual(ClientId, maps:get(<<"client_id">>, VariableMap)),
@@ -621,13 +531,12 @@ client_id_propagation(Config) ->
%% flushed, and won't contaminate following tests from this group.
no_queue_bind_permission(Config) ->
ExpectedLogs =
- [
- "MQTT resource access refused: write access to queue "
- "'mqtt-subscription-mqtt-userqos0' in vhost 'mqtt-vhost' "
- "refused for user 'mqtt-user'",
- "Failed to bind queue 'mqtt-subscription-mqtt-userqos0' "
- "in vhost 'mqtt-vhost' with topic test/topic: access_refused"
- ],
+ ["MQTT resource access refused: write access to queue "
+ "'mqtt-subscription-mqtt-userqos0' in vhost 'mqtt-vhost' "
+ "refused for user 'mqtt-user'",
+ "Failed to bind queue 'mqtt-subscription-mqtt-userqos0' "
+ "in vhost 'mqtt-vhost' with topic test/topic: access_refused"
+ ],
test_subscribe_permissions_combination(<<".*">>, <<"">>, <<".*">>, Config, ExpectedLogs).
no_queue_unbind_permission(Config) ->
@@ -635,45 +544,36 @@ no_queue_unbind_permission(Config) ->
Vhost = ?config(mqtt_vhost, Config),
rabbit_ct_broker_helpers:set_permissions(Config, User, Vhost, <<".*">>, <<".*">>, <<".*">>),
P = rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_mqtt),
- Opts = [
- {host, "localhost"},
- {port, P},
- {proto_ver, v4},
- {clientid, User},
- {username, User},
- {password, ?config(mqtt_password, Config)}
- ],
+ Opts = [{host, "localhost"},
+ {port, P},
+ {proto_ver, v4},
+ {clientid, User},
+ {username, User},
+ {password, ?config(mqtt_password, Config)}],
{ok, C1} = emqtt:start_link([{clean_start, false} | Opts]),
{ok, _} = emqtt:connect(C1),
Topic = <<"my/topic">>,
- ?assertMatch(
- {ok, _Properties, [1]},
- emqtt:subscribe(C1, Topic, qos1)
- ),
+ ?assertMatch({ok, _Properties, [1]},
+ emqtt:subscribe(C1, Topic, qos1)),
ok = emqtt:disconnect(C1),
%% Revoke read access to amq.topic exchange.
- rabbit_ct_broker_helpers:set_permissions(
- Config, User, Vhost, <<".*">>, <<".*">>, <<"^(?!amq\.topic$)">>
- ),
+ rabbit_ct_broker_helpers:set_permissions(Config, User, Vhost, <<".*">>, <<".*">>, <<"^(?!amq\.topic$)">>),
{ok, C2} = emqtt:start_link([{clean_start, false} | Opts]),
{ok, _} = emqtt:connect(C2),
process_flag(trap_exit, true),
%% We subscribe with the same client ID to the same topic again, but this time with QoS 0.
%% Therefore we trigger the qos1 queue to be unbound (and the qos0 queue to be bound).
%% However, unbinding requires read access to the exchange, which we don't have anymore.
- ?assertMatch(
- {ok, _Properties, [?SUBACK_FAILURE]},
- emqtt:subscribe(C2, Topic, qos0)
- ),
+ ?assertMatch({ok, _Properties, [?SUBACK_FAILURE]},
+ emqtt:subscribe(C2, Topic, qos0)),
ok = assert_connection_closed(C2),
ExpectedLogs =
- [
- "MQTT resource access refused: read access to exchange 'amq.topic' in vhost 'mqtt-vhost' refused for user 'mqtt-user'",
- "Failed to unbind queue 'mqtt-subscription-mqtt-userqos1' in vhost 'mqtt-vhost' with topic 'my/topic': access_refused",
- "MQTT protocol error on connection.*: subscribe_error"
- ],
- wait_log(Config, [?FAIL_IF_CRASH_LOG, {ExpectedLogs, fun() -> stop end}]),
+ ["MQTT resource access refused: read access to exchange 'amq.topic' in vhost 'mqtt-vhost' refused for user 'mqtt-user'",
+ "Failed to unbind queue 'mqtt-subscription-mqtt-userqos1' in vhost 'mqtt-vhost' with topic 'my/topic': access_refused",
+ "MQTT protocol error on connection.*: subscribe_error"
+ ],
+ wait_log(Config, [?FAIL_IF_CRASH_LOG, {ExpectedLogs, fun () -> stop end}]),
%% Clean up the qos1 queue by connecting with clean session.
rabbit_ct_broker_helpers:set_permissions(Config, User, Vhost, <<".*">>, <<".*">>, <<".*">>),
@@ -683,25 +583,20 @@ no_queue_unbind_permission(Config) ->
no_queue_consume_permission(Config) ->
ExpectedLogs =
- [
- "MQTT resource access refused: read access to queue "
- "'mqtt-subscription-mqtt-userqos0' in vhost 'mqtt-vhost' "
- "refused for user 'mqtt-user'"
- ],
- test_subscribe_permissions_combination(
- <<".*">>, <<".*">>, <<"^amq\\.topic">>, Config, ExpectedLogs
- ).
+ ["MQTT resource access refused: read access to queue "
+ "'mqtt-subscription-mqtt-userqos0' in vhost 'mqtt-vhost' "
+ "refused for user 'mqtt-user'"],
+ test_subscribe_permissions_combination(<<".*">>, <<".*">>, <<"^amq\\.topic">>, Config, ExpectedLogs).
no_queue_delete_permission(Config) ->
set_permissions(".*", ".*", ".*", Config),
ClientId = <<"no_queue_delete_permission">>,
{ok, C1} = connect_user(
- ?config(mqtt_user, Config),
- ?config(mqtt_password, Config),
- Config,
- ClientId,
- [{clean_start, false}]
- ),
+ ?config(mqtt_user, Config),
+ ?config(mqtt_password, Config),
+ Config,
+ ClientId,
+ [{clean_start, false}]),
{ok, _} = emqtt:connect(C1),
{ok, _, _} = emqtt:subscribe(C1, {<<"test/topic">>, qos1}),
ok = emqtt:disconnect(C1),
@@ -710,114 +605,82 @@ no_queue_delete_permission(Config) ->
%% Now we have a durable queue that user doesn't have permission to delete.
%% Attempt to establish clean session should fail.
{ok, C2} = connect_user(
- ?config(mqtt_user, Config),
- ?config(mqtt_password, Config),
- Config,
- ClientId,
- [{clean_start, true}]
- ),
+ ?config(mqtt_user, Config),
+ ?config(mqtt_password, Config),
+ Config,
+ ClientId,
+ [{clean_start, true}]),
unlink(C2),
- ?assertMatch(
- {error, _},
- emqtt:connect(C2)
- ),
+ ?assertMatch({error, _},
+ emqtt:connect(C2)),
wait_log(
- Config,
- [
- ?FAIL_IF_CRASH_LOG,
- {
- [
- io_lib:format(
- "MQTT resource access refused: configure access to queue "
+ Config,
+ [?FAIL_IF_CRASH_LOG
+ ,{[io_lib:format("MQTT resource access refused: configure access to queue "
"'mqtt-subscription-~sqos1' in vhost 'mqtt-vhost' refused for user 'mqtt-user'",
- [ClientId]
- ),
- "MQTT connection .* is closing due to an authorization failure"
- ],
- fun() -> stop end
- }
- ]
- ),
+ [ClientId]),
+ "MQTT connection .* is closing due to an authorization failure"],
+ fun() -> stop end}
+ ]),
ok.
no_queue_consume_permission_on_connect(Config) ->
set_permissions(".*", ".*", ".*", Config),
ClientId = <<"no_queue_consume_permission_on_connect">>,
{ok, C1} = connect_user(
- ?config(mqtt_user, Config),
- ?config(mqtt_password, Config),
- Config,
- ClientId,
- [{clean_start, false}]
- ),
+ ?config(mqtt_user, Config),
+ ?config(mqtt_password, Config),
+ Config,
+ ClientId,
+ [{clean_start, false}]),
{ok, _} = emqtt:connect(C1),
{ok, _, _} = emqtt:subscribe(C1, {<<"test/topic">>, qos1}),
ok = emqtt:disconnect(C1),
set_permissions(".*", ".*", "^amq\\.topic", Config),
{ok, C2} = connect_user(
- ?config(mqtt_user, Config),
- ?config(mqtt_password, Config),
- Config,
- ClientId,
- [{clean_start, false}]
- ),
+ ?config(mqtt_user, Config),
+ ?config(mqtt_password, Config),
+ Config,
+ ClientId,
+ [{clean_start, false}]),
unlink(C2),
- ?assertMatch(
- {error, _},
- emqtt:connect(C2)
- ),
+ ?assertMatch({error, _},
+ emqtt:connect(C2)),
wait_log(
- Config,
- [
- ?FAIL_IF_CRASH_LOG,
- {
- [
- io_lib:format(
- "MQTT resource access refused: read access to queue "
+ Config,
+ [?FAIL_IF_CRASH_LOG
+ ,{[io_lib:format("MQTT resource access refused: read access to queue "
"'mqtt-subscription-~sqos1' in vhost 'mqtt-vhost' refused for user 'mqtt-user'",
- [ClientId]
- ),
- "MQTT connection .* is closing due to an authorization failure"
- ],
- fun() -> stop end
- }
- ]
- ),
+ [ClientId]),
+ "MQTT connection .* is closing due to an authorization failure"],
+ fun () -> stop end}
+ ]),
ok.
no_queue_declare_permission(Config) ->
set_permissions("", ".*", ".*", Config),
ClientId = <<"no_queue_declare_permission">>,
{ok, C} = connect_user(
- ?config(mqtt_user, Config),
- ?config(mqtt_password, Config),
- Config,
- ClientId,
- [{clean_start, true}]
- ),
+ ?config(mqtt_user, Config),
+ ?config(mqtt_password, Config),
+ Config,
+ ClientId,
+ [{clean_start, true}]),
{ok, _} = emqtt:connect(C),
process_flag(trap_exit, true),
{ok, _, [?SUBACK_FAILURE]} = emqtt:subscribe(C, <<"test/topic">>, qos0),
ok = assert_connection_closed(C),
wait_log(
- Config,
- [
- ?FAIL_IF_CRASH_LOG,
- {
- [
- io_lib:format(
- "MQTT resource access refused: configure access to queue "
+ Config,
+ [?FAIL_IF_CRASH_LOG
+ ,{[io_lib:format("MQTT resource access refused: configure access to queue "
"'mqtt-subscription-~sqos0' in vhost 'mqtt-vhost' refused for user 'mqtt-user'",
- [ClientId]
- ),
- "MQTT protocol error on connection .*: subscribe_error"
- ],
- fun() -> stop end
- }
- ]
- ),
+ [ClientId]),
+ "MQTT protocol error on connection .*: subscribe_error"],
+ fun () -> stop end}
+ ]),
ok.
no_publish_permission(Config) ->
@@ -826,20 +689,13 @@ no_publish_permission(Config) ->
process_flag(trap_exit, true),
ok = emqtt:publish(C, <<"some/topic">>, <<"payload">>),
assert_connection_closed(C),
- wait_log(
- Config,
- [
- ?FAIL_IF_CRASH_LOG,
- {
- [
- "MQTT resource access refused: write access to exchange "
- "'amq.topic' in vhost 'mqtt-vhost' refused for user 'mqtt-user'",
- "MQTT connection .* is closing due to an authorization failure"
- ],
- fun() -> stop end
- }
- ]
- ),
+ wait_log(Config,
+ [?FAIL_IF_CRASH_LOG
+ ,{["MQTT resource access refused: write access to exchange "
+ "'amq.topic' in vhost 'mqtt-vhost' refused for user 'mqtt-user'",
+ "MQTT connection .* is closing due to an authorization failure"],
+ fun () -> stop end}
+ ]),
ok.
no_topic_read_permission(Config) ->
@@ -853,21 +709,15 @@ no_topic_read_permission(Config) ->
process_flag(trap_exit, true),
{ok, _, [?SUBACK_FAILURE]} = emqtt:subscribe(C, <<"test/topic">>),
ok = assert_connection_closed(C),
- wait_log(
- Config,
- [
- ?FAIL_IF_CRASH_LOG,
- {
- [
- "MQTT topic access refused: read access to topic 'test.topic' in exchange "
- "'amq.topic' in vhost 'mqtt-vhost' refused for user 'mqtt-user'",
- "Failed to bind queue 'mqtt-subscription-mqtt-userqos0' "
- "in vhost 'mqtt-vhost' with topic test/topic: access_refused"
- ],
- fun() -> stop end
- }
- ]
- ),
+ wait_log(Config,
+ [?FAIL_IF_CRASH_LOG,
+ {["MQTT topic access refused: read access to topic 'test.topic' in exchange "
+ "'amq.topic' in vhost 'mqtt-vhost' refused for user 'mqtt-user'",
+ "Failed to bind queue 'mqtt-subscription-mqtt-userqos0' "
+ "in vhost 'mqtt-vhost' with topic test/topic: access_refused"
+ ],
+ fun () -> stop end}
+ ]),
ok.
no_topic_write_permission(Config) ->
@@ -879,24 +729,15 @@ no_topic_write_permission(Config) ->
{ok, _} = emqtt:publish(C, <<"allow-write/some/topic">>, <<"payload">>, qos1),
process_flag(trap_exit, true),
- ?assertMatch(
- {error, _},
- emqtt:publish(C, <<"some/other/topic">>, <<"payload">>, qos1)
- ),
- wait_log(
- Config,
- [
- ?FAIL_IF_CRASH_LOG,
- {
- [
- "MQTT topic access refused: write access to topic 'some.other.topic' in "
- "exchange 'amq.topic' in vhost 'mqtt-vhost' refused for user 'mqtt-user'",
- "MQTT connection .* is closing due to an authorization failure"
- ],
- fun() -> stop end
- }
- ]
- ),
+ ?assertMatch({error, _},
+ emqtt:publish(C, <<"some/other/topic">>, <<"payload">>, qos1)),
+ wait_log(Config,
+ [?FAIL_IF_CRASH_LOG
+ ,{["MQTT topic access refused: write access to topic 'some.other.topic' in "
+ "exchange 'amq.topic' in vhost 'mqtt-vhost' refused for user 'mqtt-user'",
+ "MQTT connection .* is closing due to an authorization failure"],
+ fun () -> stop end}
+ ]),
ok.
loopback_user_connects_from_remote_host(Config) ->
@@ -913,107 +754,65 @@ loopback_user_connects_from_remote_host(Config) ->
process_flag(trap_exit, true),
?assertMatch({error, _}, emqtt:connect(C)),
- wait_log(
- Config,
- [
- ?FAIL_IF_CRASH_LOG,
- {
- [
- "MQTT login failed: user 'mqtt-user' can only connect via localhost",
- "MQTT connection .* is closing due to an authorization failure"
- ],
- fun() -> stop end
- }
- ]
- ),
+ wait_log(Config,
+ [?FAIL_IF_CRASH_LOG,
+ {["MQTT login failed: user 'mqtt-user' can only connect via localhost",
+ "MQTT connection .* is closing due to an authorization failure"],
+ fun () -> stop end}
+ ]),
true = rpc(Config, 0, meck, validate, [Mod]),
ok = rpc(Config, 0, meck, unload, [Mod]).
set_topic_permissions(WritePat, ReadPat, Config) ->
- rpc(
- Config,
- 0,
- rabbit_auth_backend_internal,
- set_topic_permissions,
- [
- ?config(mqtt_user, Config),
- ?config(mqtt_vhost, Config),
- <<"amq.topic">>,
- WritePat,
- ReadPat,
- <<"acting-user">>
- ]
- ).
+ rpc(Config, 0,
+ rabbit_auth_backend_internal, set_topic_permissions,
+ [?config(mqtt_user, Config), ?config(mqtt_vhost, Config),
+ <<"amq.topic">>, WritePat, ReadPat, <<"acting-user">>]).
set_permissions(PermConf, PermWrite, PermRead, Config) ->
- rabbit_ct_broker_helpers:set_permissions(
- Config,
- ?config(mqtt_user, Config),
- ?config(mqtt_vhost, Config),
- iolist_to_binary(PermConf),
- iolist_to_binary(PermWrite),
- iolist_to_binary(PermRead)
- ).
+ rabbit_ct_broker_helpers:set_permissions(Config, ?config(mqtt_user, Config), ?config(mqtt_vhost, Config),
+ iolist_to_binary(PermConf),
+ iolist_to_binary(PermWrite),
+ iolist_to_binary(PermRead)).
open_mqtt_connection(Config) ->
open_mqtt_connection(Config, []).
open_mqtt_connection(Config, Opts) ->
- {ok, C} = connect_user(
- ?config(mqtt_user, Config),
- ?config(mqtt_password, Config),
- Config,
- ?config(mqtt_user, Config),
- Opts
- ),
+ {ok, C} = connect_user(?config(mqtt_user, Config), ?config(mqtt_password, Config), Config, ?config(mqtt_user, Config), Opts),
{ok, _} = emqtt:connect(C),
C.
test_subscribe_permissions_combination(PermConf, PermWrite, PermRead, Config, ExtraLogChecks) ->
- rabbit_ct_broker_helpers:set_permissions(
- Config,
- ?config(mqtt_user, Config),
- ?config(mqtt_vhost, Config),
- PermConf,
- PermWrite,
- PermRead
- ),
+ rabbit_ct_broker_helpers:set_permissions(Config,
+ ?config(mqtt_user, Config),
+ ?config(mqtt_vhost, Config),
+ PermConf, PermWrite, PermRead),
P = rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_mqtt),
User = ?config(mqtt_user, Config),
- Opts = [
- {host, "localhost"},
- {port, P},
- {clientid, User},
- {username, User},
- {password, ?config(mqtt_password, Config)}
- ],
+ Opts = [{host, "localhost"},
+ {port, P},
+ {clientid, User},
+ {username, User},
+ {password, ?config(mqtt_password, Config)}],
{ok, C1} = emqtt:start_link([{proto_ver, v4} | Opts]),
{ok, _} = emqtt:connect(C1),
process_flag(trap_exit, true),
%% In v4, we expect to receive a failure return code for our subscription in the SUBACK packet.
- ?assertMatch(
- {ok, _Properties, [?SUBACK_FAILURE]},
- emqtt:subscribe(C1, <<"test/topic">>)
- ),
+ ?assertMatch({ok, _Properties, [?SUBACK_FAILURE]},
+ emqtt:subscribe(C1, <<"test/topic">>)),
ok = assert_connection_closed(C1),
- wait_log(
- Config,
- [
- ?FAIL_IF_CRASH_LOG,
- {["MQTT protocol error on connection.*: subscribe_error" | ExtraLogChecks], fun() ->
- stop
- end}
- ]
- ),
+ wait_log(Config,
+ [?FAIL_IF_CRASH_LOG
+ ,{["MQTT protocol error on connection.*: subscribe_error"|ExtraLogChecks], fun () -> stop end}
+ ]),
{ok, C2} = emqtt:start_link([{proto_ver, v3} | Opts]),
{ok, _} = emqtt:connect(C2),
%% In v3, there is no failure return code in the SUBACK packet.
- ?assertMatch(
- {ok, _Properties, [0]},
- emqtt:subscribe(C2, <<"test/topic">>)
- ),
+ ?assertMatch({ok, _Properties, [0]},
+ emqtt:subscribe(C2, <<"test/topic">>)),
ok = assert_connection_closed(C2).
connect_user(User, Pass, Config) ->
@@ -1021,25 +820,20 @@ connect_user(User, Pass, Config) ->
connect_user(User, Pass, Config, ClientID) ->
connect_user(User, Pass, Config, ClientID, []).
connect_user(User, Pass, Config, ClientID0, Opts) ->
- Creds =
- case User of
- undefined -> [];
- _ -> [{username, User}]
- end ++
- case Pass of
- undefined -> [];
- _ -> [{password, Pass}]
- end,
- ClientID =
- case ClientID0 of
- undefined -> [];
- ID -> [{clientid, ID}]
- end,
+ Creds = case User of
+ undefined -> [];
+ _ -> [{username, User}]
+ end ++ case Pass of
+ undefined -> [];
+ _ -> [{password, Pass}]
+ end,
+ ClientID = case ClientID0 of
+ undefined -> [];
+ ID -> [{clientid, ID}]
+ end,
P = rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_mqtt),
- emqtt:start_link(
- Opts ++ Creds ++ ClientID ++
- [{host, "localhost"}, {port, P}, {proto_ver, v4}]
- ).
+ emqtt:start_link(Opts ++ Creds ++ ClientID ++
+ [{host, "localhost"}, {port, P}, {proto_ver, v4}]).
expect_successful_connection(ConnectFun, Config) ->
rpc(Config, 0, rabbit_core_metrics, reset_auth_attempt_metrics, []),
@@ -1087,14 +881,10 @@ vhost_queue_limit(Config) ->
process_flag(trap_exit, true),
%% qos0 queue can be created, qos1 queue fails to be created.
%% (RabbitMQ creates subscriptions in the reverse order of the SUBSCRIBE packet.)
- ?assertMatch(
- {ok, _Properties, [?SUBACK_FAILURE, ?SUBACK_FAILURE, 0]},
- emqtt:subscribe(C, [
- {<<"topic1">>, qos1},
- {<<"topic2">>, qos1},
- {<<"topic3">>, qos0}
- ])
- ),
+ ?assertMatch({ok, _Properties, [?SUBACK_FAILURE, ?SUBACK_FAILURE, 0]},
+ emqtt:subscribe(C, [{<<"topic1">>, qos1},
+ {<<"topic2">>, qos1},
+ {<<"topic3">>, qos0}])),
ok = assert_connection_closed(C).
user_connection_limit(Config) ->
@@ -1116,47 +906,42 @@ wait_log(Config, Clauses, Deadline) ->
case erlang:monotonic_time(millisecond) of
T when T =< Deadline ->
case wait_log_check_clauses(Content, Clauses) of
- stop ->
- ok;
+ stop -> ok;
continue ->
timer:sleep(50),
wait_log(Config, Clauses, Deadline)
end;
_ ->
lists:foreach(
- fun({REs, _}) ->
- Matches = [
- io_lib:format("~p - ~s~n", [RE, re:run(Content, RE, [{capture, none}])])
- || RE <- REs
- ],
- ct:pal("Wait log clause status: ~s", [Matches])
- end,
- Clauses
- ),
+ fun
+ ({REs, _}) ->
+ Matches = [ io_lib:format("~p - ~s~n", [RE, re:run(Content, RE, [{capture, none}])]) || RE <- REs ],
+ ct:pal("Wait log clause status: ~s", [Matches])
+ end, Clauses),
ct:fail(expected_logs_not_found)
end,
ok.
wait_log_check_clauses(_, []) ->
continue;
-wait_log_check_clauses(Content, [{REs, Fun} | Rest]) ->
+wait_log_check_clauses(Content, [{REs, Fun}|Rest]) ->
case multiple_re_match(Content, REs) of
true -> Fun();
- _ -> wait_log_check_clauses(Content, Rest)
+ _ ->
+ wait_log_check_clauses(Content, Rest)
end.
multiple_re_match(Content, REs) ->
lists:all(
- fun(RE) ->
- match == re:run(Content, RE, [{capture, none}])
- end,
- REs
- ).
+ fun (RE) ->
+ match == re:run(Content, RE, [{capture, none}])
+ end, REs).
assert_connection_closed(ClientPid) ->
receive
{'EXIT', ClientPid, {shutdown, tcp_closed}} ->
ok
- after 2000 ->
- ct:fail("timed out waiting for exit message")
+ after
+ 2000 ->
+ ct:fail("timed out waiting for exit message")
end.
diff --git a/deps/rabbitmq_mqtt/test/cluster_SUITE.erl b/deps/rabbitmq_mqtt/test/cluster_SUITE.erl
index 15f4e92ddc..0ac2434ea2 100644
--- a/deps/rabbitmq_mqtt/test/cluster_SUITE.erl
+++ b/deps/rabbitmq_mqtt/test/cluster_SUITE.erl
@@ -9,42 +9,36 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
--import(util, [
- expect_publishes/3,
- connect/3,
- connect/4,
- await_exit/1
-]).
-
--import(
- rabbit_ct_broker_helpers,
- [
- setup_steps/0,
- teardown_steps/0,
- get_node_config/3,
- rabbitmqctl/3,
- rpc/4,
- stop_node/2
- ]
-).
-
--define(OPTS, [
- {connect_timeout, 1},
- {ack_timeout, 1}
-]).
+-import(util, [expect_publishes/3,
+ connect/3,
+ connect/4,
+ await_exit/1]).
+
+-import(rabbit_ct_broker_helpers,
+ [setup_steps/0,
+ teardown_steps/0,
+ get_node_config/3,
+ rabbitmqctl/3,
+ rpc/4,
+ stop_node/2
+ ]).
+
+-define(OPTS, [{connect_timeout, 1},
+ {ack_timeout, 1}]).
all() ->
[
- {group, cluster_size_5}
+ {group, cluster_size_5}
].
groups() ->
[
- {cluster_size_5, [], [
- connection_id_tracking,
- connection_id_tracking_on_nodedown,
- connection_id_tracking_with_decommissioned_node
- ]}
+ {cluster_size_5, [],
+ [
+ connection_id_tracking,
+ connection_id_tracking_on_nodedown,
+ connection_id_tracking_with_decommissioned_node
+ ]}
].
suite() ->
@@ -56,12 +50,11 @@ suite() ->
merge_app_env(Config) ->
rabbit_ct_helpers:merge_app_env(
- Config,
- {rabbit, [
- {collect_statistics, basic},
- {collect_statistics_interval, 100}
- ]}
- ).
+ Config,
+ {rabbit, [
+ {collect_statistics, basic},
+ {collect_statistics_interval, 100}
+ ]}).
init_per_suite(Config) ->
rabbit_ct_helpers:log_environment(),
@@ -72,8 +65,7 @@ end_per_suite(Config) ->
init_per_group(cluster_size_5, Config) ->
rabbit_ct_helpers:set_config(
- Config, [{rmq_nodes_count, 5}]
- ).
+ Config, [{rmq_nodes_count, 5}]).
end_per_group(_, Config) ->
Config.
@@ -83,25 +75,19 @@ init_per_testcase(Testcase, Config) ->
rabbit_ct_helpers:log_environment(),
Config1 = rabbit_ct_helpers:set_config(Config, [
{rmq_nodename_suffix, Testcase},
- {rmq_extra_tcp_ports, [
- tcp_port_mqtt_extra,
- tcp_port_mqtt_tls_extra
- ]},
+ {rmq_extra_tcp_ports, [tcp_port_mqtt_extra,
+ tcp_port_mqtt_tls_extra]},
{rmq_nodes_clustered, true}
- ]),
- rabbit_ct_helpers:run_setup_steps(
- Config1,
- [fun merge_app_env/1] ++
- setup_steps() ++
- rabbit_ct_client_helpers:setup_steps()
- ).
+ ]),
+ rabbit_ct_helpers:run_setup_steps(Config1,
+ [ fun merge_app_env/1 ] ++
+ setup_steps() ++
+ rabbit_ct_client_helpers:setup_steps()).
end_per_testcase(Testcase, Config) ->
- rabbit_ct_helpers:run_teardown_steps(
- Config,
- rabbit_ct_client_helpers:teardown_steps() ++
- teardown_steps()
- ),
+ rabbit_ct_helpers:run_teardown_steps(Config,
+ rabbit_ct_client_helpers:teardown_steps() ++
+ teardown_steps()),
rabbit_ct_helpers:testcase_finished(Config, Testcase).
%% -------------------------------------------------------------------
@@ -179,15 +165,14 @@ connection_id_tracking_with_decommissioned_node(Config) ->
%% Helpers
%%
-assert_connection_count(_Config, 0, _, NumElements) ->
+assert_connection_count(_Config, 0, _, NumElements) ->
ct:fail("failed to match connection count ~b", [NumElements]);
assert_connection_count(Config, Retries, NodeId, NumElements) ->
case util:all_connection_pids(Config) of
- Pids when
- length(Pids) =:= NumElements
- ->
+ Pids
+ when length(Pids) =:= NumElements ->
ok;
_ ->
timer:sleep(500),
- assert_connection_count(Config, Retries - 1, NodeId, NumElements)
+ assert_connection_count(Config, Retries-1, NodeId, NumElements)
end.
diff --git a/deps/rabbitmq_mqtt/test/command_SUITE.erl b/deps/rabbitmq_mqtt/test/command_SUITE.erl
index 1f3831f94e..76421287d3 100644
--- a/deps/rabbitmq_mqtt/test/command_SUITE.erl
+++ b/deps/rabbitmq_mqtt/test/command_SUITE.erl
@@ -4,6 +4,7 @@
%%
%% Copyright (c) 2007-2023 VMware, Inc. or its affiliates. All rights reserved.
+
-module(command_SUITE).
-compile([export_all, nowarn_export_all]).
@@ -16,45 +17,39 @@
all() ->
[
- {group, non_parallel_tests}
+ {group, non_parallel_tests}
].
groups() ->
[
- {non_parallel_tests, [], [
- merge_defaults,
- run
- ]}
+ {non_parallel_tests, [], [
+ merge_defaults,
+ run
+ ]}
].
suite() ->
[
- {timetrap, {minutes, 3}}
+ {timetrap, {minutes, 3}}
].
init_per_suite(Config) ->
rabbit_ct_helpers:log_environment(),
Config1 = rabbit_ct_helpers:set_config(Config, [
{rmq_nodename_suffix, ?MODULE},
- {rmq_extra_tcp_ports, [
- tcp_port_mqtt_extra,
- tcp_port_mqtt_tls_extra
- ]},
+ {rmq_extra_tcp_ports, [tcp_port_mqtt_extra,
+ tcp_port_mqtt_tls_extra]},
{rmq_nodes_clustered, true},
{rmq_nodes_count, 3}
- ]),
- rabbit_ct_helpers:run_setup_steps(
- Config1,
- rabbit_ct_broker_helpers:setup_steps() ++
- rabbit_ct_client_helpers:setup_steps()
- ).
+ ]),
+ rabbit_ct_helpers:run_setup_steps(Config1,
+ rabbit_ct_broker_helpers:setup_steps() ++
+ rabbit_ct_client_helpers:setup_steps()).
end_per_suite(Config) ->
- rabbit_ct_helpers:run_teardown_steps(
- Config,
- rabbit_ct_client_helpers:teardown_steps() ++
- rabbit_ct_broker_helpers:teardown_steps()
- ).
+ rabbit_ct_helpers:run_teardown_steps(Config,
+ rabbit_ct_client_helpers:teardown_steps() ++
+ rabbit_ct_broker_helpers:teardown_steps()).
init_per_group(_, Config) ->
Config.
@@ -78,6 +73,7 @@ merge_defaults(_Config) ->
{[<<"other_key">>], #{verbose := false}} =
?COMMAND:merge_defaults([<<"other_key">>], #{verbose => false}).
+
run(Config) ->
Node = rabbit_ct_broker_helpers:get_node_config(Config, 0, nodename),
Opts = #{node => Node, timeout => 10_000, verbose => false},
@@ -95,27 +91,18 @@ run(Config) ->
C2 = connect(<<"simpleClient1">>, Config, [{ack_timeout, 1}]),
timer:sleep(200),
- [
- [{client_id, <<"simpleClient">>}, {user, <<"guest">>}],
- [{client_id, <<"simpleClient1">>}, {user, <<"guest">>}]
- ] =
+ [[{client_id, <<"simpleClient">>}, {user, <<"guest">>}],
+ [{client_id, <<"simpleClient1">>}, {user, <<"guest">>}]] =
lists:sort(
- 'Elixir.Enum':to_list(
- ?COMMAND:run(
- [<<"client_id">>, <<"user">>],
- Opts
- )
- )
- ),
+ 'Elixir.Enum':to_list(?COMMAND:run([<<"client_id">>, <<"user">>],
+ Opts))),
Port = rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_amqp),
start_amqp_connection(network, Node, Port),
%% There are still just two MQTT connections
- [
- [{client_id, <<"simpleClient">>}],
- [{client_id, <<"simpleClient1">>}]
- ] =
+ [[{client_id, <<"simpleClient">>}],
+ [{client_id, <<"simpleClient1">>}]] =
lists:sort('Elixir.Enum':to_list(?COMMAND:run([<<"client_id">>], Opts))),
start_amqp_connection(direct, Node, Port),
@@ -123,19 +110,14 @@ run(Config) ->
%% Still two MQTT connections
?assertEqual(
- [
- [{client_id, <<"simpleClient">>}],
- [{client_id, <<"simpleClient1">>}]
- ],
- lists:sort('Elixir.Enum':to_list(?COMMAND:run([<<"client_id">>], Opts)))
- ),
+ [[{client_id, <<"simpleClient">>}],
+ [{client_id, <<"simpleClient1">>}]],
+ lists:sort('Elixir.Enum':to_list(?COMMAND:run([<<"client_id">>], Opts)))),
%% Verbose returns all keys
AllKeys = lists:map(fun(I) -> atom_to_binary(I) end, ?INFO_ITEMS),
[AllInfos1Con1, _AllInfos1Con2] = 'Elixir.Enum':to_list(?COMMAND:run(AllKeys, Opts)),
- [AllInfos2Con1, _AllInfos2Con2] = 'Elixir.Enum':to_list(
- ?COMMAND:run([], Opts#{verbose => true})
- ),
+ [AllInfos2Con1, _AllInfos2Con2] = 'Elixir.Enum':to_list(?COMMAND:run([], Opts#{verbose => true})),
%% Keys are INFO_ITEMS
InfoItemsSorted = lists:sort(?INFO_ITEMS),
diff --git a/deps/rabbitmq_mqtt/test/config_SUITE.erl b/deps/rabbitmq_mqtt/test/config_SUITE.erl
index 37cb23f43a..b2b04b52e2 100644
--- a/deps/rabbitmq_mqtt/test/config_SUITE.erl
+++ b/deps/rabbitmq_mqtt/test/config_SUITE.erl
@@ -5,10 +5,8 @@
%% Copyright (c) 2007-2023 VMware, Inc. or its affiliates. All rights reserved.
-module(config_SUITE).
--compile([
- export_all,
- nowarn_export_all
-]).
+-compile([export_all,
+ nowarn_export_all]).
-include_lib("eunit/include/eunit.hrl").
@@ -16,16 +14,17 @@
all() ->
[
- {group, mnesia}
+ {group, mnesia}
].
groups() ->
[
- {mnesia, [shuffle], [
- rabbitmq_default,
- environment_set,
- flag_set
- ]}
+ {mnesia, [shuffle],
+ [
+ rabbitmq_default,
+ environment_set,
+ flag_set
+ ]}
].
suite() ->
@@ -46,12 +45,8 @@ init_per_testcase(rabbitmq_default = Test, Config) ->
init_per_testcase0(Test, Config);
init_per_testcase(environment_set = Test, Config0) ->
Config = rabbit_ct_helpers:merge_app_env(
- Config0,
- {mnesia, [
- {dump_log_write_threshold, 25000},
- {dump_log_time_threshold, 60000}
- ]}
- ),
+ Config0, {mnesia, [{dump_log_write_threshold, 25000},
+ {dump_log_time_threshold, 60000}]}),
init_per_testcase0(Test, Config);
init_per_testcase(flag_set = Test, Config0) ->
Config = [{additional_erl_args, "-mnesia dump_log_write_threshold 15000"} | Config0],
@@ -60,19 +55,17 @@ init_per_testcase(flag_set = Test, Config0) ->
init_per_testcase0(Testcase, Config0) ->
Config1 = rabbit_ct_helpers:set_config(Config0, {rmq_nodename_suffix, Testcase}),
Config = rabbit_ct_helpers:run_steps(
- Config1,
- rabbit_ct_broker_helpers:setup_steps() ++
- rabbit_ct_client_helpers:setup_steps()
- ),
+ Config1,
+ rabbit_ct_broker_helpers:setup_steps() ++
+ rabbit_ct_client_helpers:setup_steps()),
rabbit_ct_helpers:testcase_started(Config, Testcase).
end_per_testcase(Testcase, Config0) ->
Config = rabbit_ct_helpers:testcase_finished(Config0, Testcase),
rabbit_ct_helpers:run_teardown_steps(
- Config,
- rabbit_ct_client_helpers:teardown_steps() ++
- rabbit_ct_broker_helpers:teardown_steps()
- ).
+ Config,
+ rabbit_ct_client_helpers:teardown_steps() ++
+ rabbit_ct_broker_helpers:teardown_steps()).
%% -------------------------------------------------------------------
%% Testsuite cases
@@ -81,33 +74,21 @@ end_per_testcase(Testcase, Config0) ->
%% The MQTT plugin expects Mnesia dump_log_write_threshold to be increased
%% from 1000 (Mnesia default) to 5000 (RabbitMQ default).
rabbitmq_default(Config) ->
- ?assertEqual(
- 5_000,
- rpc(Config, 0, mnesia, system_info, [dump_log_write_threshold])
- ),
- ?assertEqual(
- 90_000,
- rpc(Config, 0, mnesia, system_info, [dump_log_time_threshold])
- ).
+ ?assertEqual(5_000,
+ rpc(Config, 0, mnesia, system_info, [dump_log_write_threshold])),
+ ?assertEqual(90_000,
+ rpc(Config, 0, mnesia, system_info, [dump_log_time_threshold])).
%% User configured setting in advanced.config should be respected.
environment_set(Config) ->
- ?assertEqual(
- 25_000,
- rpc(Config, 0, mnesia, system_info, [dump_log_write_threshold])
- ),
- ?assertEqual(
- 60_000,
- rpc(Config, 0, mnesia, system_info, [dump_log_time_threshold])
- ).
+ ?assertEqual(25_000,
+ rpc(Config, 0, mnesia, system_info, [dump_log_write_threshold])),
+ ?assertEqual(60_000,
+ rpc(Config, 0, mnesia, system_info, [dump_log_time_threshold])).
%% User configured setting in RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS should be respected.
flag_set(Config) ->
- ?assertEqual(
- 15_000,
- rpc(Config, 0, mnesia, system_info, [dump_log_write_threshold])
- ),
- ?assertEqual(
- 90_000,
- rpc(Config, 0, mnesia, system_info, [dump_log_time_threshold])
- ).
+ ?assertEqual(15_000,
+ rpc(Config, 0, mnesia, system_info, [dump_log_write_threshold])),
+ ?assertEqual(90_000,
+ rpc(Config, 0, mnesia, system_info, [dump_log_time_threshold])).
diff --git a/deps/rabbitmq_mqtt/test/config_schema_SUITE.erl b/deps/rabbitmq_mqtt/test/config_schema_SUITE.erl
index b62ca26185..c3f3d867c4 100644
--- a/deps/rabbitmq_mqtt/test/config_schema_SUITE.erl
+++ b/deps/rabbitmq_mqtt/test/config_schema_SUITE.erl
@@ -23,6 +23,7 @@ init_per_suite(Config) ->
Config1 = rabbit_ct_helpers:run_setup_steps(Config),
rabbit_ct_config_schema:init_schemas(rabbitmq_mqtt, Config1).
+
end_per_suite(Config) ->
rabbit_ct_helpers:run_teardown_steps(Config).
@@ -30,19 +31,15 @@ init_per_testcase(Testcase, Config) ->
rabbit_ct_helpers:testcase_started(Config, Testcase),
Config1 = rabbit_ct_helpers:set_config(Config, [
{rmq_nodename_suffix, Testcase}
- ]),
- rabbit_ct_helpers:run_steps(
- Config1,
- rabbit_ct_broker_helpers:setup_steps() ++
- rabbit_ct_client_helpers:setup_steps()
- ).
+ ]),
+ rabbit_ct_helpers:run_steps(Config1,
+ rabbit_ct_broker_helpers:setup_steps() ++
+ rabbit_ct_client_helpers:setup_steps()).
end_per_testcase(Testcase, Config) ->
- Config1 = rabbit_ct_helpers:run_steps(
- Config,
- rabbit_ct_client_helpers:teardown_steps() ++
- rabbit_ct_broker_helpers:teardown_steps()
- ),
+ Config1 = rabbit_ct_helpers:run_steps(Config,
+ rabbit_ct_client_helpers:teardown_steps() ++
+ rabbit_ct_broker_helpers:teardown_steps()),
rabbit_ct_helpers:testcase_finished(Config1, Testcase).
%% -------------------------------------------------------------------
@@ -50,13 +47,9 @@ end_per_testcase(Testcase, Config) ->
%% -------------------------------------------------------------------
run_snippets(Config) ->
- ok = rabbit_ct_broker_helpers:rpc(
- Config,
- 0,
- ?MODULE,
- run_snippets1,
- [Config]
- ).
+ ok = rabbit_ct_broker_helpers:rpc(Config, 0,
+ ?MODULE, run_snippets1, [Config]).
run_snippets1(Config) ->
rabbit_ct_config_schema:run_snippets(Config).
+
diff --git a/deps/rabbitmq_mqtt/test/event_recorder.erl b/deps/rabbitmq_mqtt/test/event_recorder.erl
index 4c2af35437..cd495f9427 100644
--- a/deps/rabbitmq_mqtt/test/event_recorder.erl
+++ b/deps/rabbitmq_mqtt/test/event_recorder.erl
@@ -15,11 +15,10 @@
init(_) ->
{ok, ?INIT_STATE}.
-handle_event(#event{type = T}, State) when
- T =:= node_stats orelse
- T =:= node_node_stats orelse
- T =:= node_node_deleted
-->
+handle_event(#event{type = T}, State)
+ when T =:= node_stats orelse
+ T =:= node_node_stats orelse
+ T =:= node_node_deleted ->
{ok, State};
handle_event(Event, State) ->
{ok, [Event | State]}.
diff --git a/deps/rabbitmq_mqtt/test/ff_SUITE.erl b/deps/rabbitmq_mqtt/test/ff_SUITE.erl
index 5e002f808f..a7c528c640 100644
--- a/deps/rabbitmq_mqtt/test/ff_SUITE.erl
+++ b/deps/rabbitmq_mqtt/test/ff_SUITE.erl
@@ -13,31 +13,27 @@
-import(rabbit_ct_broker_helpers, [rpc/5]).
-import(rabbit_ct_helpers, [eventually/1]).
--import(util, [
- expect_publishes/3,
- get_global_counters/4,
- connect/2,
- connect/4
-]).
+-import(util, [expect_publishes/3,
+ get_global_counters/4,
+ connect/2,
+ connect/4]).
-define(PROTO_VER, v4).
all() ->
[
- {group, cluster_size_3}
+ {group, cluster_size_3}
].
groups() ->
[
- {cluster_size_3, [], [
- delete_ra_cluster_mqtt_node,
- rabbit_mqtt_qos0_queue
- ]}
+ {cluster_size_3, [], [delete_ra_cluster_mqtt_node,
+ rabbit_mqtt_qos0_queue]}
].
suite() ->
[
- {timetrap, {minutes, 2}}
+ {timetrap, {minutes, 2}}
].
init_per_suite(Config) ->
@@ -48,36 +44,26 @@ end_per_suite(Config) ->
rabbit_ct_helpers:run_teardown_steps(Config).
init_per_group(Group = cluster_size_3, Config0) ->
- Config1 = rabbit_ct_helpers:set_config(Config0, [
- {rmq_nodes_count, 3},
- {rmq_nodename_suffix, Group}
- ]),
+ Config1 = rabbit_ct_helpers:set_config(Config0, [{rmq_nodes_count, 3},
+ {rmq_nodename_suffix, Group}]),
Config = rabbit_ct_helpers:merge_app_env(
- Config1, {rabbit, [{forced_feature_flags_on_init, []}]}
- ),
- rabbit_ct_helpers:run_steps(
- Config,
- rabbit_ct_broker_helpers:setup_steps() ++
- rabbit_ct_client_helpers:setup_steps()
- ).
+ Config1, {rabbit, [{forced_feature_flags_on_init, []}]}),
+ rabbit_ct_helpers:run_steps(Config,
+ rabbit_ct_broker_helpers:setup_steps() ++
+ rabbit_ct_client_helpers:setup_steps()).
end_per_group(_Group, Config) ->
- rabbit_ct_helpers:run_steps(
- Config,
- rabbit_ct_client_helpers:teardown_steps() ++
- rabbit_ct_broker_helpers:teardown_steps()
- ).
+ rabbit_ct_helpers:run_steps(Config,
+ rabbit_ct_client_helpers:teardown_steps() ++
+ rabbit_ct_broker_helpers:teardown_steps()).
init_per_testcase(TestCase, Config) ->
case rabbit_ct_broker_helpers:is_feature_flag_supported(Config, TestCase) of
true ->
Config;
false ->
- {skip,
- io_lib:format(
- "feature flag ~s is unsupported",
- [TestCase]
- )}
+ {skip, io_lib:format("feature flag ~s is unsupported",
+ [TestCase])}
end.
end_per_testcase(_TestCase, Config) ->
@@ -90,27 +76,16 @@ delete_ra_cluster_mqtt_node(Config) ->
%% old client ID tracking works
?assertEqual(1, length(util:all_connection_pids(Config))),
%% Ra processes are alive
- ?assert(
- lists:all(
- fun erlang:is_pid/1,
- rabbit_ct_broker_helpers:rpc_all(Config, erlang, whereis, [mqtt_node])
- )
- ),
-
- ?assertEqual(
- ok,
- rabbit_ct_broker_helpers:enable_feature_flag(Config, FeatureFlag)
- ),
+ ?assert(lists:all(fun erlang:is_pid/1,
+ rabbit_ct_broker_helpers:rpc_all(Config, erlang, whereis, [mqtt_node]))),
+
+ ?assertEqual(ok,
+ rabbit_ct_broker_helpers:enable_feature_flag(Config, FeatureFlag)),
%% Ra processes should be gone
rabbit_ct_helpers:eventually(
- ?_assert(
- lists:all(
- fun(Pid) -> Pid =:= undefined end,
- rabbit_ct_broker_helpers:rpc_all(Config, erlang, whereis, [mqtt_node])
- )
- )
- ),
+ ?_assert(lists:all(fun(Pid) -> Pid =:= undefined end,
+ rabbit_ct_broker_helpers:rpc_all(Config, erlang, whereis, [mqtt_node])))),
%% new client ID tracking works
?assertEqual(1, length(util:all_connection_pids(Config))),
?assert(erlang:is_process_alive(C)),
@@ -124,30 +99,20 @@ rabbit_mqtt_qos0_queue(Config) ->
{ok, _, [0]} = emqtt:subscribe(C1, Topic, qos0),
ok = emqtt:publish(C1, Topic, Msg, qos0),
ok = expect_publishes(C1, Topic, [Msg]),
- ?assertEqual(
- 1,
- length(rpc(Config, 0, rabbit_amqqueue, list_by_type, [rabbit_classic_queue]))
- ),
+ ?assertEqual(1,
+ length(rpc(Config, 0, rabbit_amqqueue, list_by_type, [rabbit_classic_queue]))),
- ?assertEqual(
- ok,
- rabbit_ct_broker_helpers:enable_feature_flag(Config, FeatureFlag)
- ),
+ ?assertEqual(ok,
+ rabbit_ct_broker_helpers:enable_feature_flag(Config, FeatureFlag)),
%% Queue type does not chanage for existing connection.
- ?assertEqual(
- 1,
- length(rpc(Config, 0, rabbit_amqqueue, list_by_type, [rabbit_classic_queue]))
- ),
+ ?assertEqual(1,
+ length(rpc(Config, 0, rabbit_amqqueue, list_by_type, [rabbit_classic_queue]))),
ok = emqtt:publish(C1, Topic, Msg, qos0),
ok = expect_publishes(C1, Topic, [Msg]),
- ?assertMatch(
- #{
- messages_delivered_total := 2,
- messages_delivered_consume_auto_ack_total := 2
- },
- get_global_counters(Config, ?PROTO_VER, 0, [{queue_type, rabbit_classic_queue}])
- ),
+ ?assertMatch(#{messages_delivered_total := 2,
+ messages_delivered_consume_auto_ack_total := 2},
+ get_global_counters(Config, ?PROTO_VER, 0, [{queue_type, rabbit_classic_queue}])),
%% Reconnecting with the same client ID will terminate the old connection.
true = unlink(C1),
@@ -155,22 +120,13 @@ rabbit_mqtt_qos0_queue(Config) ->
{ok, _, [0]} = emqtt:subscribe(C2, Topic, qos0),
%% This time, we get the new queue type.
eventually(
- ?_assertEqual(
- 0,
- length(rpc(Config, 0, rabbit_amqqueue, list_by_type, [rabbit_classic_queue]))
- )
- ),
- ?assertEqual(
- 1,
- length(rpc(Config, 0, rabbit_amqqueue, list_by_type, [FeatureFlag]))
- ),
+ ?_assertEqual(0,
+ length(rpc(Config, 0, rabbit_amqqueue, list_by_type, [rabbit_classic_queue])))),
+ ?assertEqual(1,
+ length(rpc(Config, 0, rabbit_amqqueue, list_by_type, [FeatureFlag]))),
ok = emqtt:publish(C2, Topic, Msg, qos0),
ok = expect_publishes(C2, Topic, [Msg]),
- ?assertMatch(
- #{
- messages_delivered_total := 1,
- messages_delivered_consume_auto_ack_total := 1
- },
- get_global_counters(Config, ?PROTO_VER, 0, [{queue_type, FeatureFlag}])
- ),
+ ?assertMatch(#{messages_delivered_total := 1,
+ messages_delivered_consume_auto_ack_total := 1},
+ get_global_counters(Config, ?PROTO_VER, 0, [{queue_type, FeatureFlag}])),
ok = emqtt:disconnect(C2).
diff --git a/deps/rabbitmq_mqtt/test/java_SUITE.erl b/deps/rabbitmq_mqtt/test/java_SUITE.erl
index 4e3fdeed29..5155f1ba77 100644
--- a/deps/rabbitmq_mqtt/test/java_SUITE.erl
+++ b/deps/rabbitmq_mqtt/test/java_SUITE.erl
@@ -12,25 +12,24 @@
-include_lib("eunit/include/eunit.hrl").
-define(BASE_CONF_MQTT,
- {rabbitmq_mqtt, [
- {ssl_cert_login, true},
- {allow_anonymous, false},
- {sparkplug, true},
- {tcp_listeners, []},
- {ssl_listeners, []}
- ]}
-).
+ {rabbitmq_mqtt, [
+ {ssl_cert_login, true},
+ {allow_anonymous, false},
+ {sparkplug, true},
+ {tcp_listeners, []},
+ {ssl_listeners, []}
+ ]}).
all() ->
[
- {group, non_parallel_tests}
+ {group, non_parallel_tests}
].
groups() ->
[
- {non_parallel_tests, [], [
- java
- ]}
+ {non_parallel_tests, [], [
+ java
+ ]}
].
suite() ->
@@ -53,20 +52,16 @@ init_per_suite(Config) ->
{rmq_certspwd, "bunnychow"},
{rmq_nodes_clustered, true},
{rmq_nodes_count, 3}
- ]),
- rabbit_ct_helpers:run_setup_steps(
- Config1,
- [fun merge_app_env/1] ++
- rabbit_ct_broker_helpers:setup_steps() ++
- rabbit_ct_client_helpers:setup_steps()
- ).
+ ]),
+ rabbit_ct_helpers:run_setup_steps(Config1,
+ [ fun merge_app_env/1 ] ++
+ rabbit_ct_broker_helpers:setup_steps() ++
+ rabbit_ct_client_helpers:setup_steps()).
end_per_suite(Config) ->
- rabbit_ct_helpers:run_teardown_steps(
- Config,
- rabbit_ct_client_helpers:teardown_steps() ++
- rabbit_ct_broker_helpers:teardown_steps()
- ).
+ rabbit_ct_helpers:run_teardown_steps(Config,
+ rabbit_ct_client_helpers:teardown_steps() ++
+ rabbit_ct_broker_helpers:teardown_steps()).
init_per_group(_, Config) ->
Config.
@@ -79,38 +74,25 @@ init_per_testcase(Testcase, Config) ->
CertFile = filename:join([CertsDir, "client", "cert.pem"]),
{ok, CertBin} = file:read_file(CertFile),
[{'Certificate', Cert, not_encrypted}] = public_key:pem_decode(CertBin),
- UserBin = rabbit_ct_broker_helpers:rpc(
- Config,
- 0,
- rabbit_ssl,
- peer_cert_auth_name,
- [Cert]
- ),
+ UserBin = rabbit_ct_broker_helpers:rpc(Config, 0,
+ rabbit_ssl,
+ peer_cert_auth_name,
+ [Cert]),
User = binary_to_list(UserBin),
- {ok, _} = rabbit_ct_broker_helpers:rabbitmqctl(Config, 0, ["add_user", User, ""]),
- {ok, _} = rabbit_ct_broker_helpers:rabbitmqctl(Config, 0, [
- "set_permissions", "-p", "/", User, ".*", ".*", ".*"
- ]),
- {ok, _} = rabbit_ct_broker_helpers:rabbitmqctl(
- Config,
- 0,
- [
- "set_topic_permissions",
- "-p",
- "/",
- "guest",
- "amq.topic",
+ {ok,_} = rabbit_ct_broker_helpers:rabbitmqctl(Config, 0, ["add_user", User, ""]),
+ {ok, _} = rabbit_ct_broker_helpers:rabbitmqctl(Config, 0, ["set_permissions", "-p", "/", User, ".*", ".*", ".*"]),
+ {ok, _} = rabbit_ct_broker_helpers:rabbitmqctl(Config, 0,
+ ["set_topic_permissions", "-p", "/", "guest", "amq.topic",
% Write permission
"test-topic|test-retained-topic|{username}.{client_id}.a|^sp[AB]v\\d+___\\d+",
% Read permission
- "test-topic|test-retained-topic|last-will|{username}.{client_id}.a|^sp[AB]v\\d+___\\d+"
- ]
- ),
+ "test-topic|test-retained-topic|last-will|{username}.{client_id}.a|^sp[AB]v\\d+___\\d+"]),
rabbit_ct_helpers:testcase_started(Config, Testcase).
end_per_testcase(Testcase, Config) ->
rabbit_ct_helpers:testcase_finished(Config, Testcase).
+
%% -------------------------------------------------------------------
%% Testsuite cases
%% -------------------------------------------------------------------
@@ -140,5 +122,5 @@ q(P, [K | Rem]) ->
undefined -> undefined;
V -> q(V, Rem)
end;
-q(P, []) ->
- {ok, P}.
+q(P, []) -> {ok, P}.
+
diff --git a/deps/rabbitmq_mqtt/test/mqtt_machine_SUITE.erl b/deps/rabbitmq_mqtt/test/mqtt_machine_SUITE.erl
index ebf773aa44..274877cdc8 100644
--- a/deps/rabbitmq_mqtt/test/mqtt_machine_SUITE.erl
+++ b/deps/rabbitmq_mqtt/test/mqtt_machine_SUITE.erl
@@ -12,19 +12,20 @@
all() ->
[
- {group, tests}
+ {group, tests}
].
+
all_tests() ->
[
- basics,
- machine_upgrade,
- many_downs
+ basics,
+ machine_upgrade,
+ many_downs
].
groups() ->
[
- {tests, [], all_tests()}
+ {tests, [], all_tests()}
].
init_per_suite(Config) ->
@@ -52,16 +53,13 @@ end_per_testcase(_TestCase, _Config) ->
basics(_Config) ->
S0 = mqtt_machine:init(#{}),
ClientId = <<"id1">>,
- OthPid = spawn(fun() -> ok end),
+ OthPid = spawn(fun () -> ok end),
{S1, ok, _} = mqtt_machine:apply(meta(1), {register, ClientId, self()}, S0),
?assertMatch(#machine_state{client_ids = Ids} when map_size(Ids) == 1, S1),
?assertMatch(#machine_state{pids = Pids} when map_size(Pids) == 1, S1),
{S2, ok, _} = mqtt_machine:apply(meta(2), {register, ClientId, OthPid}, S1),
- ?assertMatch(
- #machine_state{client_ids = #{ClientId := OthPid} = Ids} when
- map_size(Ids) == 1,
- S2
- ),
+ ?assertMatch(#machine_state{client_ids = #{ClientId := OthPid} = Ids}
+ when map_size(Ids) == 1, S2),
{S3, ok, _} = mqtt_machine:apply(meta(3), {down, OthPid, noproc}, S2),
?assertMatch(#machine_state{client_ids = Ids} when map_size(Ids) == 0, S3),
{S4, ok, _} = mqtt_machine:apply(meta(3), {unregister, ClientId, OthPid}, S2),
@@ -76,63 +74,41 @@ machine_upgrade(_Config) ->
{S1, ok, _} = mqtt_machine_v0:apply(meta(1), {register, ClientId, self()}, S0),
?assertMatch({machine_state, Ids} when map_size(Ids) == 1, S1),
{S2, ok, _} = mqtt_machine:apply(meta(2), {machine_version, 0, 1}, S1),
- ?assertMatch(
- #machine_state{
- client_ids = #{ClientId := Self},
- pids = #{Self := [ClientId]} = Pids
- } when
- map_size(Pids) == 1,
- S2
- ),
+ ?assertMatch(#machine_state{client_ids = #{ClientId := Self},
+ pids = #{Self := [ClientId]} = Pids}
+ when map_size(Pids) == 1, S2),
{S3, ok, _} = mqtt_machine:apply(meta(3), {down, self(), noproc}, S2),
- ?assertMatch(
- #machine_state{
- client_ids = Ids,
- pids = Pids
- } when
- map_size(Ids) == 0 andalso map_size(Pids) == 0,
- S3
- ),
+ ?assertMatch(#machine_state{client_ids = Ids,
+ pids = Pids}
+ when map_size(Ids) == 0 andalso map_size(Pids) == 0, S3),
ok.
many_downs(_Config) ->
S0 = mqtt_machine:init(#{}),
- Clients = [
- {list_to_binary(integer_to_list(I)), spawn(fun() -> ok end)}
- || I <- lists:seq(1, 10000)
- ],
+ Clients = [{list_to_binary(integer_to_list(I)), spawn(fun() -> ok end)}
+ || I <- lists:seq(1, 10000)],
S1 = lists:foldl(
- fun({ClientId, Pid}, Acc0) ->
- {Acc, ok, _} = mqtt_machine:apply(meta(1), {register, ClientId, Pid}, Acc0),
- Acc
- end,
- S0,
- Clients
- ),
+ fun ({ClientId, Pid}, Acc0) ->
+ {Acc, ok, _} = mqtt_machine:apply(meta(1), {register, ClientId, Pid}, Acc0),
+ Acc
+ end, S0, Clients),
_ = lists:foldl(
- fun({_ClientId, Pid}, Acc0) ->
- {Acc, ok, _} = mqtt_machine:apply(meta(1), {down, Pid, noproc}, Acc0),
- Acc
- end,
- S1,
- Clients
- ),
+ fun ({_ClientId, Pid}, Acc0) ->
+ {Acc, ok, _} = mqtt_machine:apply(meta(1), {down, Pid, noproc}, Acc0),
+ Acc
+ end, S1, Clients),
_ = lists:foldl(
- fun({ClientId, Pid}, Acc0) ->
- {Acc, ok, _} = mqtt_machine:apply(meta(1), {unregister, ClientId, Pid}, Acc0),
- Acc
- end,
- S0,
- Clients
- ),
+ fun ({ClientId, Pid}, Acc0) ->
+ {Acc, ok, _} = mqtt_machine:apply(meta(1), {unregister, ClientId,
+ Pid}, Acc0),
+ Acc
+ end, S0, Clients),
ok.
%% Utility
meta(Idx) ->
- #{
- index => Idx,
- term => 1,
- ts => erlang:system_time(millisecond)
- }.
+ #{index => Idx,
+ term => 1,
+ ts => erlang:system_time(millisecond)}.
diff --git a/deps/rabbitmq_mqtt/test/processor_SUITE.erl b/deps/rabbitmq_mqtt/test/processor_SUITE.erl
index 1078462ad8..15ae0dd537 100644
--- a/deps/rabbitmq_mqtt/test/processor_SUITE.erl
+++ b/deps/rabbitmq_mqtt/test/processor_SUITE.erl
@@ -4,6 +4,7 @@
%%
%% Copyright (c) 2007-2023 VMware, Inc. or its affiliates. All rights reserved.
+
-module(processor_SUITE).
-compile([export_all, nowarn_export_all]).
@@ -13,17 +14,17 @@
all() ->
[
- {group, non_parallel_tests}
+ {group, non_parallel_tests}
].
groups() ->
[
- {non_parallel_tests, [], [
- ignores_colons_in_username_if_option_set,
- interprets_colons_in_username_if_option_not_set,
- get_vhosts_from_global_runtime_parameter,
- get_vhost
- ]}
+ {non_parallel_tests, [], [
+ ignores_colons_in_username_if_option_set,
+ interprets_colons_in_username_if_option_not_set,
+ get_vhosts_from_global_runtime_parameter,
+ get_vhost
+ ]}
].
suite() ->
@@ -41,50 +42,35 @@ init_per_testcase(get_vhost, Config) ->
mnesia:start(),
mnesia:create_table(rabbit_runtime_parameters, [
{attributes, record_info(fields, runtime_parameters)},
- {record_name, runtime_parameters}
- ]),
+ {record_name, runtime_parameters}]),
Config;
-init_per_testcase(_, Config) ->
- Config.
+init_per_testcase(_, Config) -> Config.
end_per_testcase(get_vhost, Config) ->
mnesia:stop(),
Config;
-end_per_testcase(_, Config) ->
- Config.
+end_per_testcase(_, Config) -> Config.
ignore_colons(B) -> application:set_env(rabbitmq_mqtt, ignore_colons_in_username, B).
ignores_colons_in_username_if_option_set(_Config) ->
ignore_colons(true),
- ?assertEqual(
- {rabbit_mqtt_util:env(vhost), <<"a:b:c">>},
- rabbit_mqtt_processor:get_vhost_username(<<"a:b:c">>)
- ).
+ ?assertEqual({rabbit_mqtt_util:env(vhost), <<"a:b:c">>},
+ rabbit_mqtt_processor:get_vhost_username(<<"a:b:c">>)).
interprets_colons_in_username_if_option_not_set(_Config) ->
- ignore_colons(false),
- ?assertEqual(
- {<<"a:b">>, <<"c">>},
- rabbit_mqtt_processor:get_vhost_username(<<"a:b:c">>)
- ).
+ ignore_colons(false),
+ ?assertEqual({<<"a:b">>, <<"c">>},
+ rabbit_mqtt_processor:get_vhost_username(<<"a:b:c">>)).
get_vhosts_from_global_runtime_parameter(_Config) ->
MappingParameter = [
{<<"O=client,CN=dummy1">>, <<"vhost1">>},
{<<"O=client,CN=dummy2">>, <<"vhost2">>}
],
- <<"vhost1">> = rabbit_mqtt_processor:get_vhost_from_user_mapping(
- <<"O=client,CN=dummy1">>, MappingParameter
- ),
- <<"vhost2">> = rabbit_mqtt_processor:get_vhost_from_user_mapping(
- <<"O=client,CN=dummy2">>, MappingParameter
- ),
- undefined = rabbit_mqtt_processor:get_vhost_from_user_mapping(
- <<"O=client,CN=dummy3">>, MappingParameter
- ),
- undefined = rabbit_mqtt_processor:get_vhost_from_user_mapping(
- <<"O=client,CN=dummy3">>, not_found
- ).
+ <<"vhost1">> = rabbit_mqtt_processor:get_vhost_from_user_mapping(<<"O=client,CN=dummy1">>, MappingParameter),
+ <<"vhost2">> = rabbit_mqtt_processor:get_vhost_from_user_mapping(<<"O=client,CN=dummy2">>, MappingParameter),
+ undefined = rabbit_mqtt_processor:get_vhost_from_user_mapping(<<"O=client,CN=dummy3">>, MappingParameter),
+ undefined = rabbit_mqtt_processor:get_vhost_from_user_mapping(<<"O=client,CN=dummy3">>, not_found).
get_vhost(_Config) ->
clear_vhost_global_parameters(),
@@ -97,35 +83,27 @@ get_vhost(_Config) ->
%% not a certificate user, no cert/vhost mapping, vhost in user
%% should use vhost in user
- {_, {<<"somevhost">>, <<"guest">>}} = rabbit_mqtt_processor:get_vhost(
- <<"somevhost:guest">>, none, 1883
- ),
+ {_, {<<"somevhost">>, <<"guest">>}} = rabbit_mqtt_processor:get_vhost(<<"somevhost:guest">>, none, 1883),
clear_vhost_global_parameters(),
%% certificate user, no cert/vhost mapping
%% should use default vhost
- {_, {<<"/">>, <<"guest">>}} = rabbit_mqtt_processor:get_vhost(
- <<"guest">>, <<"O=client,CN=dummy">>, 1883
- ),
+ {_, {<<"/">>, <<"guest">>}} = rabbit_mqtt_processor:get_vhost(<<"guest">>, <<"O=client,CN=dummy">>, 1883),
clear_vhost_global_parameters(),
%% certificate user, cert/vhost mapping with global runtime parameter
%% should use mapping
set_global_parameter(mqtt_default_vhosts, [
- {<<"O=client,CN=dummy">>, <<"somevhost">>},
+ {<<"O=client,CN=dummy">>, <<"somevhost">>},
{<<"O=client,CN=otheruser">>, <<"othervhost">>}
]),
- {_, {<<"somevhost">>, <<"guest">>}} = rabbit_mqtt_processor:get_vhost(
- <<"guest">>, <<"O=client,CN=dummy">>, 1883
- ),
+ {_, {<<"somevhost">>, <<"guest">>}} = rabbit_mqtt_processor:get_vhost(<<"guest">>, <<"O=client,CN=dummy">>, 1883),
clear_vhost_global_parameters(),
%% certificate user, cert/vhost mapping with global runtime parameter, but no key for the user
%% should use default vhost
set_global_parameter(mqtt_default_vhosts, [{<<"O=client,CN=otheruser">>, <<"somevhost">>}]),
- {_, {<<"/">>, <<"guest">>}} = rabbit_mqtt_processor:get_vhost(
- <<"guest">>, <<"O=client,CN=dummy">>, 1883
- ),
+ {_, {<<"/">>, <<"guest">>}} = rabbit_mqtt_processor:get_vhost(<<"guest">>, <<"O=client,CN=dummy">>, 1883),
clear_vhost_global_parameters(),
%% not a certificate user, port/vhost mapping
@@ -143,9 +121,7 @@ get_vhost(_Config) ->
{<<"1883">>, <<"somevhost">>},
{<<"1884">>, <<"othervhost">>}
]),
- {_, {<<"vhostinusername">>, <<"guest">>}} = rabbit_mqtt_processor:get_vhost(
- <<"vhostinusername:guest">>, none, 1883
- ),
+ {_, {<<"vhostinusername">>, <<"guest">>}} = rabbit_mqtt_processor:get_vhost(<<"vhostinusername:guest">>, none, 1883),
clear_vhost_global_parameters(),
%% not a certificate user, port/vhost mapping, but no mapping for this port
@@ -162,50 +138,42 @@ get_vhost(_Config) ->
{<<"1883">>, <<"somevhost">>},
{<<"1884">>, <<"othervhost">>}
]),
- {_, {<<"somevhost">>, <<"guest">>}} = rabbit_mqtt_processor:get_vhost(
- <<"guest">>, <<"O=client,CN=dummy">>, 1883
- ),
+ {_, {<<"somevhost">>, <<"guest">>}} = rabbit_mqtt_processor:get_vhost(<<"guest">>, <<"O=client,CN=dummy">>, 1883),
clear_vhost_global_parameters(),
%% certificate user, port/vhost parameter but no mapping, cert/vhost mapping
%% should use cert/vhost mapping
set_global_parameter(mqtt_default_vhosts, [
- {<<"O=client,CN=dummy">>, <<"somevhost">>},
+ {<<"O=client,CN=dummy">>, <<"somevhost">>},
{<<"O=client,CN=otheruser">>, <<"othervhost">>}
]),
set_global_parameter(mqtt_port_to_vhost_mapping, [
{<<"1884">>, <<"othervhost">>}
]),
- {_, {<<"somevhost">>, <<"guest">>}} = rabbit_mqtt_processor:get_vhost(
- <<"guest">>, <<"O=client,CN=dummy">>, 1883
- ),
+ {_, {<<"somevhost">>, <<"guest">>}} = rabbit_mqtt_processor:get_vhost(<<"guest">>, <<"O=client,CN=dummy">>, 1883),
clear_vhost_global_parameters(),
%% certificate user, port/vhost parameter, cert/vhost parameter
%% cert/vhost parameter takes precedence
set_global_parameter(mqtt_default_vhosts, [
- {<<"O=client,CN=dummy">>, <<"cert-somevhost">>},
+ {<<"O=client,CN=dummy">>, <<"cert-somevhost">>},
{<<"O=client,CN=otheruser">>, <<"othervhost">>}
]),
set_global_parameter(mqtt_port_to_vhost_mapping, [
{<<"1883">>, <<"port-vhost">>},
{<<"1884">>, <<"othervhost">>}
]),
- {_, {<<"cert-somevhost">>, <<"guest">>}} = rabbit_mqtt_processor:get_vhost(
- <<"guest">>, <<"O=client,CN=dummy">>, 1883
- ),
+ {_, {<<"cert-somevhost">>, <<"guest">>}} = rabbit_mqtt_processor:get_vhost(<<"guest">>, <<"O=client,CN=dummy">>, 1883),
clear_vhost_global_parameters(),
%% certificate user, no port/vhost or cert/vhost mapping, vhost in username
%% should use vhost in username
- {_, {<<"vhostinusername">>, <<"guest">>}} = rabbit_mqtt_processor:get_vhost(
- <<"vhostinusername:guest">>, <<"O=client,CN=dummy">>, 1883
- ),
+ {_, {<<"vhostinusername">>, <<"guest">>}} = rabbit_mqtt_processor:get_vhost(<<"vhostinusername:guest">>, <<"O=client,CN=dummy">>, 1883),
%% not a certificate user, port/vhost parameter, cert/vhost parameter
%% port/vhost mapping is used, as cert/vhost should not be used
set_global_parameter(mqtt_default_vhosts, [
- {<<"O=cert">>, <<"cert-somevhost">>},
+ {<<"O=cert">>, <<"cert-somevhost">>},
{<<"O=client,CN=otheruser">>, <<"othervhost">>}
]),
set_global_parameter(mqtt_port_to_vhost_mapping, [
@@ -217,15 +185,15 @@ get_vhost(_Config) ->
ok.
set_global_parameter(Key, Term) ->
- InsertParameterFun = fun() ->
+ InsertParameterFun = fun () ->
mnesia:write(rabbit_runtime_parameters, #runtime_parameters{key = Key, value = Term}, write)
- end,
+ end,
{atomic, ok} = mnesia:transaction(InsertParameterFun).
clear_vhost_global_parameters() ->
- DeleteParameterFun = fun() ->
+ DeleteParameterFun = fun () ->
ok = mnesia:delete(rabbit_runtime_parameters, mqtt_default_vhosts, write),
ok = mnesia:delete(rabbit_runtime_parameters, mqtt_port_to_vhost_mapping, write)
- end,
+ end,
{atomic, ok} = mnesia:transaction(DeleteParameterFun).
diff --git a/deps/rabbitmq_mqtt/test/proxy_protocol_SUITE.erl b/deps/rabbitmq_mqtt/test/proxy_protocol_SUITE.erl
index 6499b9aaea..551b14c865 100644
--- a/deps/rabbitmq_mqtt/test/proxy_protocol_SUITE.erl
+++ b/deps/rabbitmq_mqtt/test/proxy_protocol_SUITE.erl
@@ -34,26 +34,21 @@ init_per_suite(Config) ->
{rabbitmq_ct_tls_verify, verify_none}
]),
MqttConfig = mqtt_config(),
- rabbit_ct_helpers:run_setup_steps(
- Config1,
- [fun(Conf) -> merge_app_env(MqttConfig, Conf) end] ++
+ rabbit_ct_helpers:run_setup_steps(Config1,
+ [ fun(Conf) -> merge_app_env(MqttConfig, Conf) end ] ++
rabbit_ct_broker_helpers:setup_steps() ++
- rabbit_ct_client_helpers:setup_steps()
- ).
+ rabbit_ct_client_helpers:setup_steps()).
mqtt_config() ->
{rabbitmq_mqtt, [
- {proxy_protocol, true},
- {ssl_cert_login, true},
- {allow_anonymous, true}
- ]}.
+ {proxy_protocol, true},
+ {ssl_cert_login, true},
+ {allow_anonymous, true}]}.
end_per_suite(Config) ->
- rabbit_ct_helpers:run_teardown_steps(
- Config,
+ rabbit_ct_helpers:run_teardown_steps(Config,
rabbit_ct_client_helpers:teardown_steps() ++
- rabbit_ct_broker_helpers:teardown_steps()
- ).
+ rabbit_ct_broker_helpers:teardown_steps()).
init_per_group(_, Config) -> Config.
end_per_group(_, Config) -> Config.
@@ -66,11 +61,8 @@ end_per_testcase(Testcase, Config) ->
proxy_protocol(Config) ->
Port = rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_mqtt),
- {ok, Socket} = gen_tcp:connect(
- {127, 0, 0, 1},
- Port,
- [binary, {active, false}, {packet, raw}]
- ),
+ {ok, Socket} = gen_tcp:connect({127,0,0,1}, Port,
+ [binary, {active, false}, {packet, raw}]),
ok = inet:send(Socket, "PROXY TCP4 192.168.1.1 192.168.1.2 80 81\r\n"),
ok = inet:send(Socket, mqtt_3_1_1_connect_packet()),
{ok, _Packet} = gen_tcp:recv(Socket, 0, ?TIMEOUT),
@@ -83,11 +75,8 @@ proxy_protocol(Config) ->
proxy_protocol_tls(Config) ->
app_utils:start_applications([asn1, crypto, public_key, ssl]),
Port = rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_mqtt_tls),
- {ok, Socket} = gen_tcp:connect(
- {127, 0, 0, 1},
- Port,
- [binary, {active, false}, {packet, raw}]
- ),
+ {ok, Socket} = gen_tcp:connect({127,0,0,1}, Port,
+ [binary, {active, false}, {packet, raw}]),
ok = inet:send(Socket, "PROXY TCP4 192.168.1.1 192.168.1.2 80 81\r\n"),
{ok, SslSocket} = ssl:connect(Socket, [], ?TIMEOUT),
ok = ssl:send(SslSocket, mqtt_3_1_1_connect_packet()),
@@ -107,5 +96,29 @@ merge_app_env(MqttConfig, Config) ->
rabbit_ct_helpers:merge_app_env(Config, MqttConfig).
mqtt_3_1_1_connect_packet() ->
- <<16, 24, 0, 4, 77, 81, 84, 84, 4, 2, 0, 60, 0, 12, 84, 101, 115, 116, 67, 111, 110, 115, 117,
- 109, 101, 114>>.
+ <<16,
+ 24,
+ 0,
+ 4,
+ 77,
+ 81,
+ 84,
+ 84,
+ 4,
+ 2,
+ 0,
+ 60,
+ 0,
+ 12,
+ 84,
+ 101,
+ 115,
+ 116,
+ 67,
+ 111,
+ 110,
+ 115,
+ 117,
+ 109,
+ 101,
+ 114>>.
diff --git a/deps/rabbitmq_mqtt/test/rabbit_auth_backend_mqtt_mock.erl b/deps/rabbitmq_mqtt/test/rabbit_auth_backend_mqtt_mock.erl
index ad1bfe1e58..69fea6c221 100644
--- a/deps/rabbitmq_mqtt/test/rabbit_auth_backend_mqtt_mock.erl
+++ b/deps/rabbitmq_mqtt/test/rabbit_auth_backend_mqtt_mock.erl
@@ -13,16 +13,11 @@
-behaviour(rabbit_authn_backend).
-behaviour(rabbit_authz_backend).
--export([
- setup/1,
- user_login_authentication/2,
- user_login_authorization/2,
- check_vhost_access/3,
- check_resource_access/4,
- check_topic_access/4,
- state_can_expire/0,
- get/1
-]).
+-export([setup/1,
+ user_login_authentication/2, user_login_authorization/2,
+ check_vhost_access/3, check_resource_access/4, check_topic_access/4,
+ state_can_expire/0,
+ get/1]).
setup(CallerPid) ->
ets:new(?MODULE, [set, public, named_table]),
@@ -31,13 +26,12 @@ setup(CallerPid) ->
stop -> ok
end.
+
user_login_authentication(_, AuthProps) ->
ets:insert(?MODULE, {authentication, AuthProps}),
- {ok, #auth_user{
- username = <<"dummy">>,
- tags = [],
- impl = none
- }}.
+ {ok, #auth_user{username = <<"dummy">>,
+ tags = [],
+ impl = none}}.
user_login_authorization(_, _) ->
io:format("login authorization"),
diff --git a/deps/rabbitmq_mqtt/test/reader_SUITE.erl b/deps/rabbitmq_mqtt/test/reader_SUITE.erl
index 5a96612231..4c65e20e47 100644
--- a/deps/rabbitmq_mqtt/test/reader_SUITE.erl
+++ b/deps/rabbitmq_mqtt/test/reader_SUITE.erl
@@ -5,45 +5,42 @@
%% Copyright (c) 2007-2023 VMware, Inc. or its affiliates. All rights reserved.
%%
-module(reader_SUITE).
--compile([
- export_all,
- nowarn_export_all
-]).
+-compile([export_all,
+ nowarn_export_all]).
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
-import(rabbit_ct_broker_helpers, [rpc/4]).
-import(rabbit_ct_helpers, [eventually/3]).
--import(util, [
- all_connection_pids/1,
- publish_qos1_timeout/4,
- expect_publishes/3,
- connect/2,
- connect/3,
- await_exit/1
-]).
+-import(util, [all_connection_pids/1,
+ publish_qos1_timeout/4,
+ expect_publishes/3,
+ connect/2,
+ connect/3,
+ await_exit/1]).
all() ->
[
- {group, tests}
+ {group, tests}
].
groups() ->
[
- {tests, [], [
- block_connack_timeout,
- handle_invalid_packets,
- login_timeout,
- stats,
- quorum_clean_session_false,
- quorum_clean_session_true,
- classic_clean_session_true,
- classic_clean_session_false,
- non_clean_sess_empty_client_id,
- event_authentication_failure,
- rabbit_mqtt_qos0_queue_overflow
- ]}
+ {tests, [],
+ [
+ block_connack_timeout,
+ handle_invalid_packets,
+ login_timeout,
+ stats,
+ quorum_clean_session_false,
+ quorum_clean_session_true,
+ classic_clean_session_true,
+ classic_clean_session_false,
+ non_clean_sess_empty_client_id,
+ event_authentication_failure,
+ rabbit_mqtt_qos0_queue_overflow
+ ]}
].
suite() ->
@@ -54,36 +51,28 @@ suite() ->
%% -------------------------------------------------------------------
merge_app_env(Config) ->
- rabbit_ct_helpers:merge_app_env(
- Config,
- {rabbit, [
- {collect_statistics, basic},
- {collect_statistics_interval, 100}
- ]}
- ).
+ rabbit_ct_helpers:merge_app_env(Config,
+ {rabbit, [
+ {collect_statistics, basic},
+ {collect_statistics_interval, 100}
+ ]}).
init_per_suite(Config) ->
rabbit_ct_helpers:log_environment(),
Config1 = rabbit_ct_helpers:set_config(Config, [
{rmq_nodename_suffix, ?MODULE},
- {rmq_extra_tcp_ports, [
- tcp_port_mqtt_extra,
- tcp_port_mqtt_tls_extra
- ]}
- ]),
- rabbit_ct_helpers:run_setup_steps(
- Config1,
- [fun merge_app_env/1] ++
- rabbit_ct_broker_helpers:setup_steps() ++
- rabbit_ct_client_helpers:setup_steps()
- ).
+ {rmq_extra_tcp_ports, [tcp_port_mqtt_extra,
+ tcp_port_mqtt_tls_extra]}
+ ]),
+ rabbit_ct_helpers:run_setup_steps(Config1,
+ [ fun merge_app_env/1 ] ++
+ rabbit_ct_broker_helpers:setup_steps() ++
+ rabbit_ct_client_helpers:setup_steps()).
end_per_suite(Config) ->
- rabbit_ct_helpers:run_teardown_steps(
- Config,
- rabbit_ct_client_helpers:teardown_steps() ++
- rabbit_ct_broker_helpers:teardown_steps()
- ).
+ rabbit_ct_helpers:run_teardown_steps(Config,
+ rabbit_ct_client_helpers:teardown_steps() ++
+ rabbit_ct_broker_helpers:teardown_steps()).
init_per_group(_, Config) ->
Config.
@@ -97,6 +86,7 @@ init_per_testcase(Testcase, Config) ->
end_per_testcase(Testcase, Config) ->
rabbit_ct_helpers:testcase_finished(Config, Testcase).
+
%% -------------------------------------------------------------------
%% Testsuite cases
%% -------------------------------------------------------------------
@@ -110,13 +100,11 @@ block_connack_timeout(Config) ->
timer:sleep(100),
%% We can still connect via TCP, but CONNECT packet will not be processed on the server.
- {ok, Client} = emqtt:start_link([
- {host, "localhost"},
- {port, P},
- {clientid, atom_to_binary(?FUNCTION_NAME)},
- {proto_ver, v4},
- {connect_timeout, 1}
- ]),
+ {ok, Client} = emqtt:start_link([{host, "localhost"},
+ {port, P},
+ {clientid, atom_to_binary(?FUNCTION_NAME)},
+ {proto_ver, v4},
+ {connect_timeout, 1}]),
unlink(Client),
ClientMRef = monitor(process, Client),
{error, connack_timeout} = emqtt:connect(Client),
@@ -124,7 +112,7 @@ block_connack_timeout(Config) ->
{'DOWN', ClientMRef, process, Client, connack_timeout} ->
ok
after 200 ->
- ct:fail("missing connack_timeout in client")
+ ct:fail("missing connack_timeout in client")
end,
Ports = rpc(Config, erlang, ports, []),
@@ -142,7 +130,7 @@ block_connack_timeout(Config) ->
%% because our client already disconnected.
ok
after 2000 ->
- ct:fail("missing peername_not_known from server")
+ ct:fail("missing peername_not_known from server")
end,
%% Ensure that our client is not registered.
?assertEqual([], all_connection_pids(Config)),
@@ -182,12 +170,8 @@ stats(Config) ->
[{Pid, Props}] = rpc(Config, ets, lookup, [connection_metrics, Pid]),
true = proplists:is_defined(garbage_collection, Props),
%% If the coarse entry is present, stats were successfully emitted
- [{Pid, _, _, _, _}] = rpc(
- Config,
- ets,
- lookup,
- [connection_coarse_metrics, Pid]
- ),
+ [{Pid, _, _, _, _}] = rpc(Config, ets, lookup,
+ [connection_coarse_metrics, Pid]),
ok = emqtt:disconnect(C).
get_durable_queue_type(Server, QNameBin) ->
@@ -232,41 +216,32 @@ classic_clean_session_true(Config) ->
validate_durable_queue_type(Config, <<"classicCleanSessionTrue">>, true, rabbit_classic_queue).
classic_clean_session_false(Config) ->
- validate_durable_queue_type(
- Config, <<"classicCleanSessionFalse">>, false, rabbit_classic_queue
- ).
+ validate_durable_queue_type(Config, <<"classicCleanSessionFalse">>, false, rabbit_classic_queue).
%% "If the Client supplies a zero-byte ClientId with CleanSession set to 0,
%% the Server MUST respond to the CONNECT Packet with a CONNACK return code 0x02
%% (Identifier rejected) and then close the Network Connection" [MQTT-3.1.3-8].
non_clean_sess_empty_client_id(Config) ->
{ok, C} = emqtt:start_link(
- [
- {clientid, <<>>},
- {clean_start, false},
- {proto_ver, v4},
- {host, "localhost"},
- {port, rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_mqtt)}
- ]
- ),
+ [{clientid, <<>>},
+ {clean_start, false},
+ {proto_ver, v4},
+ {host, "localhost"},
+ {port, rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_mqtt)}
+ ]),
process_flag(trap_exit, true),
- ?assertMatch(
- {error, {client_identifier_not_valid, _}},
- emqtt:connect(C)
- ),
+ ?assertMatch({error, {client_identifier_not_valid, _}},
+ emqtt:connect(C)),
ok = await_exit(C).
event_authentication_failure(Config) ->
{ok, C} = emqtt:start_link(
- [
- {username, <<"Trudy">>},
- {password, <<"fake-password">>},
- {host, "localhost"},
- {port, rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_mqtt)},
- {clientid, atom_to_binary(?FUNCTION_NAME)},
- {proto_ver, v4}
- ]
- ),
+ [{username, <<"Trudy">>},
+ {password, <<"fake-password">>},
+ {host, "localhost"},
+ {port, rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_mqtt)},
+ {clientid, atom_to_binary(?FUNCTION_NAME)},
+ {proto_ver, v4}]),
true = unlink(C),
ok = rabbit_ct_broker_helpers:add_code_path_to_all_nodes(Config, event_recorder),
@@ -277,13 +252,9 @@ event_authentication_failure(Config) ->
[E, _ConnectionClosedEvent] = util:get_events(Server),
util:assert_event_type(user_authentication_failure, E),
- util:assert_event_prop(
- [
- {name, <<"Trudy">>},
- {connection_type, network}
- ],
- E
- ),
+ util:assert_event_prop([{name, <<"Trudy">>},
+ {connection_type, network}],
+ E),
ok = gen_event:delete_handler({rabbit_event, Server}, event_recorder, []).
@@ -295,12 +266,8 @@ rabbit_mqtt_qos0_queue_overflow(Config) ->
NumMsgs = 10_000,
%% Provoke TCP back-pressure from client to server by using very small buffers.
- Opts = [
- {tcp_opts, [
- {recbuf, 512},
- {buffer, 512}
- ]}
- ],
+ Opts = [{tcp_opts, [{recbuf, 512},
+ {buffer, 512}]}],
Sub = connect(<<"subscriber">>, Config, Opts),
{ok, _, [0]} = emqtt:subscribe(Sub, Topic, qos0),
[ServerConnectionPid] = all_connection_pids(Config),
@@ -312,12 +279,9 @@ rabbit_mqtt_qos0_queue_overflow(Config) ->
%% Let's overflow the receiving server MQTT connection process
%% (i.e. the rabbit_mqtt_qos0_queue) by sending many large messages.
Pub = connect(<<"publisher">>, Config),
- lists:foreach(
- fun(_) ->
- ok = emqtt:publish(Pub, Topic, Msg, qos0)
- end,
- lists:seq(1, NumMsgs)
- ),
+ lists:foreach(fun(_) ->
+ ok = emqtt:publish(Pub, Topic, Msg, qos0)
+ end, lists:seq(1, NumMsgs)),
%% Give the server some time to process (either send or drop) the messages.
timer:sleep(2000),
@@ -354,11 +318,9 @@ rabbit_mqtt_qos0_queue_overflow(Config) ->
num_received(Topic, Payload, N) ->
receive
- {publish, #{
- topic := Topic,
- payload := Payload
- }} ->
+ {publish, #{topic := Topic,
+ payload := Payload}} ->
num_received(Topic, Payload, N + 1)
after 1000 ->
- N
+ N
end.
diff --git a/deps/rabbitmq_mqtt/test/retainer_SUITE.erl b/deps/rabbitmq_mqtt/test/retainer_SUITE.erl
index eb3f8dedd5..3a2585e8fe 100644
--- a/deps/rabbitmq_mqtt/test/retainer_SUITE.erl
+++ b/deps/rabbitmq_mqtt/test/retainer_SUITE.erl
@@ -8,31 +8,29 @@
-compile([export_all, nowarn_export_all]).
-include_lib("common_test/include/ct.hrl").
--import(util, [
- expect_publishes/3,
- connect/3
-]).
+-import(util, [expect_publishes/3,
+ connect/3]).
all() ->
[
- {group, dets},
- {group, ets},
- {group, noop}
+ {group, dets},
+ {group, ets},
+ {group, noop}
].
groups() ->
[
- {dets, [], tests()},
- {ets, [], tests()},
- {noop, [], [does_not_retain]}
+ {dets, [], tests()},
+ {ets, [], tests()},
+ {noop, [], [does_not_retain]}
].
tests() ->
[
- coerce_configuration_data,
- should_translate_amqp2mqtt_on_publish,
- should_translate_amqp2mqtt_on_retention,
- should_translate_amqp2mqtt_on_retention_search
+ coerce_configuration_data,
+ should_translate_amqp2mqtt_on_publish,
+ should_translate_amqp2mqtt_on_retention,
+ should_translate_amqp2mqtt_on_retention_search
].
suite() ->
@@ -51,38 +49,31 @@ end_per_suite(Config) ->
init_per_group(Group, Config0) ->
Config = rabbit_ct_helpers:set_config(
- Config0,
- [
- {rmq_nodename_suffix, Group},
- {rmq_extra_tcp_ports, [
- tcp_port_mqtt_extra,
- tcp_port_mqtt_tls_extra
- ]}
- ]
- ),
+ Config0,
+ [
+ {rmq_nodename_suffix, Group},
+ {rmq_extra_tcp_ports, [tcp_port_mqtt_extra,
+ tcp_port_mqtt_tls_extra]}
+ ]),
Mod = list_to_atom("rabbit_mqtt_retained_msg_store_" ++ atom_to_list(Group)),
- Env = [
- {rabbitmq_mqtt, [{retained_message_store, Mod}]},
- {rabbit, [
- {default_user, "guest"},
- {default_pass, "guest"},
- {default_vhost, "/"},
- {default_permissions, [".*", ".*", ".*"]}
- ]}
- ],
+ Env = [{rabbitmq_mqtt, [{retained_message_store, Mod}]},
+ {rabbit, [
+ {default_user, "guest"},
+ {default_pass, "guest"},
+ {default_vhost, "/"},
+ {default_permissions, [".*", ".*", ".*"]}
+ ]}],
rabbit_ct_helpers:run_setup_steps(
- Config,
- [fun(Conf) -> rabbit_ct_helpers:merge_app_env(Conf, Env) end] ++
- rabbit_ct_broker_helpers:setup_steps() ++
- rabbit_ct_client_helpers:setup_steps()
- ).
+ Config,
+ [fun(Conf) -> rabbit_ct_helpers:merge_app_env(Conf, Env) end] ++
+ rabbit_ct_broker_helpers:setup_steps() ++
+ rabbit_ct_client_helpers:setup_steps()).
end_per_group(_, Config) ->
rabbit_ct_helpers:run_teardown_steps(
- Config,
- rabbit_ct_client_helpers:teardown_steps() ++
- rabbit_ct_broker_helpers:teardown_steps()
- ).
+ Config,
+ rabbit_ct_client_helpers:teardown_steps() ++
+ rabbit_ct_broker_helpers:teardown_steps()).
init_per_testcase(Testcase, Config) ->
rabbit_ct_helpers:testcase_started(Config, Testcase).
@@ -90,6 +81,7 @@ init_per_testcase(Testcase, Config) ->
end_per_testcase(Testcase, Config) ->
rabbit_ct_helpers:testcase_finished(Config, Testcase).
+
%% -------------------------------------------------------------------
%% Testsuite cases
%% -------------------------------------------------------------------
@@ -112,7 +104,7 @@ should_translate_amqp2mqtt_on_publish(Config) ->
C = connect(<<"simpleClientRetainer">>, Config, [{ack_timeout, 1}]),
%% there's an active consumer
{ok, _, _} = emqtt:subscribe(C, <<"TopicA/Device.Field">>, qos1),
- ok = emqtt:publish(C, <<"TopicA/Device.Field">>, #{}, <<"Payload">>, [{retain, true}]),
+ ok = emqtt:publish(C, <<"TopicA/Device.Field">>, #{}, <<"Payload">>, [{retain, true}]),
ok = expect_publishes(C, <<"TopicA/Device/Field">>, [<<"Payload">>]),
ok = emqtt:disconnect(C).
@@ -124,7 +116,7 @@ should_translate_amqp2mqtt_on_publish(Config) ->
should_translate_amqp2mqtt_on_retention(Config) ->
C = connect(<<"simpleClientRetainer">>, Config, [{ack_timeout, 1}]),
%% publish with retain = true before a consumer comes around
- ok = emqtt:publish(C, <<"TopicA/Device.Field">>, #{}, <<"Payload">>, [{retain, true}]),
+ ok = emqtt:publish(C, <<"TopicA/Device.Field">>, #{}, <<"Payload">>, [{retain, true}]),
{ok, _, _} = emqtt:subscribe(C, <<"TopicA/Device.Field">>, qos1),
ok = expect_publishes(C, <<"TopicA/Device/Field">>, [<<"Payload">>]),
ok = emqtt:disconnect(C).
@@ -136,19 +128,19 @@ should_translate_amqp2mqtt_on_retention(Config) ->
%% -------------------------------------------------------------------
should_translate_amqp2mqtt_on_retention_search(Config) ->
C = connect(<<"simpleClientRetainer">>, Config, [{ack_timeout, 1}]),
- ok = emqtt:publish(C, <<"TopicA/Device.Field">>, #{}, <<"Payload">>, [{retain, true}]),
+ ok = emqtt:publish(C, <<"TopicA/Device.Field">>, #{}, <<"Payload">>, [{retain, true}]),
{ok, _, _} = emqtt:subscribe(C, <<"TopicA/Device/Field">>, qos1),
ok = expect_publishes(C, <<"TopicA/Device/Field">>, [<<"Payload">>]),
ok = emqtt:disconnect(C).
does_not_retain(Config) ->
C = connect(<<"simpleClientRetainer">>, Config, [{ack_timeout, 1}]),
- ok = emqtt:publish(C, <<"TopicA/Device.Field">>, #{}, <<"Payload">>, [{retain, true}]),
+ ok = emqtt:publish(C, <<"TopicA/Device.Field">>, #{}, <<"Payload">>, [{retain, true}]),
{ok, _, _} = emqtt:subscribe(C, <<"TopicA/Device.Field">>, qos1),
receive
Unexpected ->
ct:fail("Unexpected message: ~p", [Unexpected])
after 1000 ->
- ok
+ ok
end,
ok = emqtt:disconnect(C).
diff --git a/deps/rabbitmq_mqtt/test/shared_SUITE.erl b/deps/rabbitmq_mqtt/test/shared_SUITE.erl
index 32d46f0481..71183d5f9c 100644
--- a/deps/rabbitmq_mqtt/test/shared_SUITE.erl
+++ b/deps/rabbitmq_mqtt/test/shared_SUITE.erl
@@ -6,10 +6,8 @@
%% Test suite shared between rabbitmq_mqtt and rabbitmq_web_mqtt.
-module(shared_SUITE).
--compile([
- export_all,
- nowarn_export_all
-]).
+-compile([export_all,
+ nowarn_export_all]).
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
@@ -17,113 +15,100 @@
-include_lib("rabbitmq_ct_helpers/include/rabbit_assert.hrl").
-include_lib("rabbitmq_ct_helpers/include/rabbit_mgmt_test.hrl").
--import(
- rabbit_ct_broker_helpers,
- [
- rabbitmqctl_list/3,
- rpc/4,
- rpc/5,
- rpc_all/4,
- get_node_config/3,
- drain_node/2,
- revive_node/2
- ]
-).
--import(
- rabbit_ct_helpers,
- [
- eventually/3,
- eventually/1
- ]
-).
--import(
- util,
- [
- all_connection_pids/1,
- get_global_counters/2, get_global_counters/3, get_global_counters/4,
- expect_publishes/3,
- connect/2, connect/3, connect/4,
- get_events/1,
- assert_event_type/2,
- assert_event_prop/2,
- await_exit/1, await_exit/2,
- publish_qos1_timeout/4
- ]
-).
--import(
- rabbit_mgmt_test_util,
- [
- http_get/2,
- http_delete/3
- ]
-).
+-import(rabbit_ct_broker_helpers,
+ [rabbitmqctl_list/3,
+ rpc/4,
+ rpc/5,
+ rpc_all/4,
+ get_node_config/3,
+ drain_node/2,
+ revive_node/2
+ ]).
+-import(rabbit_ct_helpers,
+ [eventually/3,
+ eventually/1]).
+-import(util,
+ [all_connection_pids/1,
+ get_global_counters/2, get_global_counters/3, get_global_counters/4,
+ expect_publishes/3,
+ connect/2, connect/3, connect/4,
+ get_events/1, assert_event_type/2, assert_event_prop/2,
+ await_exit/1, await_exit/2,
+ publish_qos1_timeout/4]).
+-import(rabbit_mgmt_test_util,
+ [http_get/2,
+ http_delete/3]).
all() ->
[
- {group, mqtt},
- {group, web_mqtt}
+ {group, mqtt}
+ ,{group, web_mqtt}
].
groups() ->
[
- {mqtt, [], subgroups()},
- {web_mqtt, [], subgroups()}
+ {mqtt, [], subgroups()}
+ ,{web_mqtt, [], subgroups()}
].
subgroups() ->
[
- {cluster_size_1, [], [
- {global_counters, [], [
- global_counters_v3,
- global_counters_v4
- ]},
- {tests, [], [
- block_only_publisher,
- many_qos1_messages,
- subscription_ttl,
- management_plugin_connection,
- management_plugin_enable,
- disconnect,
- pubsub_shared_connection,
- pubsub_separate_connections,
- will_with_disconnect,
- will_without_disconnect,
- quorum_queue_rejects,
- events,
- internal_event_handler,
- non_clean_sess_reconnect_qos1,
- non_clean_sess_reconnect_qos0,
- non_clean_sess_reconnect_qos0_and_qos1,
- subscribe_same_topic_same_qos,
- subscribe_same_topic_different_qos,
- subscribe_multiple,
- large_message_mqtt_to_mqtt,
- large_message_amqp_to_mqtt,
- keepalive,
- keepalive_turned_off,
- duplicate_client_id,
- block,
- amqp_to_mqtt_qos0,
- clean_session_disconnect_client,
- clean_session_kill_node,
- rabbit_status_connection_count,
- trace
- ]}
+ {cluster_size_1, [],
+ [
+ {global_counters, [],
+ [
+ global_counters_v3,
+ global_counters_v4
]},
- {cluster_size_3, [], [
- queue_down_qos1,
- consuming_classic_mirrored_queue_down,
- consuming_classic_queue_down,
- flow_classic_mirrored_queue,
- flow_quorum_queue,
- flow_stream,
- rabbit_mqtt_qos0_queue,
- cli_list_queues,
- maintenance,
- delete_create_queue,
- publish_to_all_queue_types_qos0,
- publish_to_all_queue_types_qos1
+ {tests, [],
+ [
+ block_only_publisher
+ ,many_qos1_messages
+ ,subscription_ttl
+ ,management_plugin_connection
+ ,management_plugin_enable
+ ,disconnect
+ ,pubsub_shared_connection
+ ,pubsub_separate_connections
+ ,will_with_disconnect
+ ,will_without_disconnect
+ ,quorum_queue_rejects
+ ,events
+ ,internal_event_handler
+ ,non_clean_sess_reconnect_qos1
+ ,non_clean_sess_reconnect_qos0
+ ,non_clean_sess_reconnect_qos0_and_qos1
+ ,subscribe_same_topic_same_qos
+ ,subscribe_same_topic_different_qos
+ ,subscribe_multiple
+ ,large_message_mqtt_to_mqtt
+ ,large_message_amqp_to_mqtt
+ ,keepalive
+ ,keepalive_turned_off
+ ,duplicate_client_id
+ ,block
+ ,amqp_to_mqtt_qos0
+ ,clean_session_disconnect_client
+ ,clean_session_kill_node
+ ,rabbit_status_connection_count
+ ,trace
]}
+ ]},
+ {cluster_size_3, [],
+ [
+ queue_down_qos1,
+ consuming_classic_mirrored_queue_down,
+ consuming_classic_queue_down,
+ flow_classic_mirrored_queue,
+ flow_quorum_queue,
+ flow_stream,
+ rabbit_mqtt_qos0_queue,
+ cli_list_queues,
+ maintenance,
+ delete_create_queue,
+ publish_to_all_queue_types_qos0,
+ publish_to_all_queue_types_qos1
+ ]}
].
suite() ->
@@ -144,67 +129,54 @@ init_per_group(mqtt, Config) ->
rabbit_ct_helpers:set_config(Config, {websocket, false});
init_per_group(web_mqtt, Config) ->
rabbit_ct_helpers:set_config(Config, {websocket, true});
+
init_per_group(cluster_size_1, Config) ->
rabbit_ct_helpers:set_config(Config, [{rmq_nodes_count, 1}]);
init_per_group(cluster_size_3 = Group, Config) ->
- init_per_group0(
- Group,
- rabbit_ct_helpers:set_config(Config, [{rmq_nodes_count, 3}])
- );
-init_per_group(Group, Config) when
- Group =:= global_counters orelse
- Group =:= tests
-->
+ init_per_group0(Group,
+ rabbit_ct_helpers:set_config(Config, [{rmq_nodes_count, 3}]));
+init_per_group(Group, Config)
+ when Group =:= global_counters orelse
+ Group =:= tests ->
init_per_group0(Group, Config).
init_per_group0(Group, Config0) ->
Suffix = lists:flatten(io_lib:format("~s_websocket_~w", [Group, ?config(websocket, Config0)])),
Config1 = rabbit_ct_helpers:set_config(
- Config0,
- [
- {rmq_nodename_suffix, Suffix},
- {rmq_extra_tcp_ports, [
- tcp_port_mqtt_extra,
- tcp_port_mqtt_tls_extra
- ]}
- ]
- ),
+ Config0,
+ [{rmq_nodename_suffix, Suffix},
+ {rmq_extra_tcp_ports, [tcp_port_mqtt_extra,
+ tcp_port_mqtt_tls_extra]}]),
Config = rabbit_ct_helpers:merge_app_env(
- Config1,
- {rabbit, [{classic_queue_default_version, 2}]}
- ),
+ Config1,
+ {rabbit, [{classic_queue_default_version, 2}]}),
rabbit_ct_helpers:run_steps(
- Config,
- rabbit_ct_broker_helpers:setup_steps() ++
- rabbit_ct_client_helpers:setup_steps()
- ).
-
-end_per_group(G, Config) when
- G =:= mqtt;
- G =:= web_mqtt;
- G =:= cluster_size_1
-->
+ Config,
+ rabbit_ct_broker_helpers:setup_steps() ++
+ rabbit_ct_client_helpers:setup_steps()).
+
+end_per_group(G, Config)
+ when G =:= mqtt;
+ G =:= web_mqtt;
+ G =:= cluster_size_1 ->
Config;
end_per_group(_, Config) ->
rabbit_ct_helpers:run_teardown_steps(
- Config,
- rabbit_ct_client_helpers:teardown_steps() ++
- rabbit_ct_broker_helpers:teardown_steps()
- ).
+ Config,
+ rabbit_ct_client_helpers:teardown_steps() ++
+ rabbit_ct_broker_helpers:teardown_steps()).
init_per_testcase(Testcase = maintenance, Config) ->
case rabbit_ct_helpers:is_mixed_versions() of
true ->
- {skip,
- "maintenance mode wrongly closes cluster-wide MQTT connections "
- "in RMQ < 3.11.2 and < 3.10.10"};
+ {skip, "maintenance mode wrongly closes cluster-wide MQTT connections "
+ "in RMQ < 3.11.2 and < 3.10.10"};
false ->
init_per_testcase0(Testcase, Config)
end;
-init_per_testcase(T, Config) when
- T =:= management_plugin_connection;
- T =:= management_plugin_enable
-->
+init_per_testcase(T, Config)
+ when T =:= management_plugin_connection;
+ T =:= management_plugin_enable ->
ok = inets:start(),
init_per_testcase0(T, Config);
init_per_testcase(Testcase, Config) ->
@@ -215,10 +187,9 @@ init_per_testcase0(Testcase, Config) ->
[ok = rabbit_ct_broker_helpers:enable_plugin(Config, N, rabbitmq_web_mqtt) || N <- Nodes],
rabbit_ct_helpers:testcase_started(Config, Testcase).
-end_per_testcase(T, Config) when
- T =:= management_plugin_connection;
- T =:= management_plugin_enable
-->
+end_per_testcase(T, Config)
+ when T =:= management_plugin_connection;
+ T =:= management_plugin_enable ->
ok = inets:stop(),
end_per_testcase0(T, Config);
end_per_testcase(Testcase, Config) ->
@@ -248,14 +219,11 @@ pubsub_shared_connection(Config) ->
{ok, _, [1]} = emqtt:subscribe(C, Topic, qos1),
Payload = <<"a\x00a">>,
- ?assertMatch(
- {ok, #{
- packet_id := _,
- reason_code := 0,
- reason_code_name := success
- }},
- emqtt:publish(C, Topic, Payload, [{qos, 1}])
- ),
+ ?assertMatch({ok, #{packet_id := _,
+ reason_code := 0,
+ reason_code_name := success
+ }},
+ emqtt:publish(C, Topic, Payload, [{qos, 1}])),
ok = expect_publishes(C, Topic, [Payload]),
ok = emqtt:disconnect(C).
@@ -267,14 +235,11 @@ pubsub_separate_connections(Config) ->
{ok, _, [1]} = emqtt:subscribe(Sub, Topic, qos1),
Payload = <<"a\x00a">>,
- ?assertMatch(
- {ok, #{
- packet_id := _,
- reason_code := 0,
- reason_code_name := success
- }},
- emqtt:publish(Pub, Topic, Payload, [{qos, 1}])
- ),
+ ?assertMatch({ok, #{packet_id := _,
+ reason_code := 0,
+ reason_code_name := success
+ }},
+ emqtt:publish(Pub, Topic, Payload, [{qos, 1}])),
ok = expect_publishes(Sub, Topic, [Payload]),
ok = emqtt:disconnect(Pub),
ok = emqtt:disconnect(Sub).
@@ -282,32 +247,26 @@ pubsub_separate_connections(Config) ->
will_with_disconnect(Config) ->
LastWillTopic = <<"/topic/last-will">>,
LastWillMsg = <<"last will message">>,
- PubOpts = [
- {will_topic, LastWillTopic},
- {will_payload, LastWillMsg},
- {will_qos, 1}
- ],
+ PubOpts = [{will_topic, LastWillTopic},
+ {will_payload, LastWillMsg},
+ {will_qos, 1}],
Pub = connect(<<(atom_to_binary(?FUNCTION_NAME))/binary, "_publisher">>, Config, PubOpts),
Sub = connect(<<(atom_to_binary(?FUNCTION_NAME))/binary, "_subscriber">>, Config),
{ok, _, [1]} = emqtt:subscribe(Sub, LastWillTopic, qos1),
%% Client sends DISCONNECT packet. Therefore, will message should not be sent.
ok = emqtt:disconnect(Pub),
- ?assertEqual(
- {publish_not_received, LastWillMsg},
- expect_publishes(Sub, LastWillTopic, [LastWillMsg])
- ),
+ ?assertEqual({publish_not_received, LastWillMsg},
+ expect_publishes(Sub, LastWillTopic, [LastWillMsg])),
ok = emqtt:disconnect(Sub).
will_without_disconnect(Config) ->
LastWillTopic = <<"/topic/last-will">>,
LastWillMsg = <<"last will message">>,
- PubOpts = [
- {will_topic, LastWillTopic},
- {will_payload, LastWillMsg},
- {will_qos, 1}
- ],
+ PubOpts = [{will_topic, LastWillTopic},
+ {will_payload, LastWillMsg},
+ {will_qos, 1}],
Pub = connect(<<(atom_to_binary(?FUNCTION_NAME))/binary, "_publisher">>, Config, PubOpts),
timer:sleep(100),
[ServerPublisherPid] = all_connection_pids(Config),
@@ -326,11 +285,8 @@ quorum_queue_rejects(Config) ->
Name = atom_to_binary(?FUNCTION_NAME),
ok = rabbit_ct_broker_helpers:set_policy(
- Config, 0, <<"qq-policy">>, Name, <<"queues">>, [
- {<<"max-length">>, 1},
- {<<"overflow">>, <<"reject-publish">>}
- ]
- ),
+ Config, 0, <<"qq-policy">>, Name, <<"queues">>, [{<<"max-length">>, 1},
+ {<<"overflow">>, <<"reject-publish">>}]),
declare_queue(Ch, Name, [{<<"x-queue-type">>, longstr, <<"quorum">>}]),
bind(Ch, Name, Name),
@@ -340,21 +296,14 @@ quorum_queue_rejects(Config) ->
%% We expect m3 to be rejected and dropped.
?assertEqual(puback_timeout, util:publish_qos1_timeout(C, Name, <<"m3">>, 700)),
- ?assertMatch(
- {#'basic.get_ok'{}, #amqp_msg{payload = <<"m1">>}},
- amqp_channel:call(Ch, #'basic.get'{queue = Name, no_ack = true})
- ),
- ?assertMatch(
- {#'basic.get_ok'{}, #amqp_msg{payload = <<"m2">>}},
- amqp_channel:call(Ch, #'basic.get'{queue = Name, no_ack = true})
- ),
+ ?assertMatch({#'basic.get_ok'{}, #amqp_msg{payload = <<"m1">>}},
+ amqp_channel:call(Ch, #'basic.get'{queue = Name, no_ack = true})),
+ ?assertMatch({#'basic.get_ok'{}, #amqp_msg{payload = <<"m2">>}},
+ amqp_channel:call(Ch, #'basic.get'{queue = Name, no_ack = true})),
%% m3 is re-sent by emqtt.
- ?awaitMatch(
- {#'basic.get_ok'{}, #amqp_msg{payload = <<"m3">>}},
- amqp_channel:call(Ch, #'basic.get'{queue = Name, no_ack = true}),
- 2000,
- 200
- ),
+ ?awaitMatch({#'basic.get_ok'{}, #amqp_msg{payload = <<"m3">>}},
+ amqp_channel:call(Ch, #'basic.get'{queue = Name, no_ack = true}),
+ 2000, 200),
ok = emqtt:disconnect(C),
delete_queue(Ch, Name),
@@ -390,55 +339,40 @@ publish_to_all_queue_types(Config, QoS) ->
NumMsgs = 2000,
C = connect(?FUNCTION_NAME, Config, [{retry_interval, 2}]),
- lists:foreach(
- fun(N) ->
- case emqtt:publish(C, Topic, integer_to_binary(N), QoS) of
- ok ->
- ok;
- {ok, _} ->
- ok;
- Other ->
- ct:fail("Failed to publish: ~p", [Other])
- end
- end,
- lists:seq(1, NumMsgs)
- ),
-
- eventually(
- ?_assert(
- begin
- L = rabbitmqctl_list(Config, 0, ["list_queues", "messages", "--no-table-headers"]),
- length(L) =:= 4 andalso
- lists:all(
- fun([Bin]) ->
- N = binary_to_integer(Bin),
- case QoS of
- qos0 ->
- N =:= NumMsgs;
- qos1 ->
- %% Allow for some duplicates when client resends
- %% a message that gets acked at roughly the same time.
- N >= NumMsgs andalso
- N < NumMsgs * 2
- end
- end,
- L
- )
- end
- ),
- 2000,
- 10
- ),
+ lists:foreach(fun(N) ->
+ case emqtt:publish(C, Topic, integer_to_binary(N), QoS) of
+ ok ->
+ ok;
+ {ok, _} ->
+ ok;
+ Other ->
+ ct:fail("Failed to publish: ~p", [Other])
+ end
+ end, lists:seq(1, NumMsgs)),
+
+ eventually(?_assert(
+ begin
+ L = rabbitmqctl_list(Config, 0, ["list_queues", "messages", "--no-table-headers"]),
+ length(L) =:= 4 andalso
+ lists:all(fun([Bin]) ->
+ N = binary_to_integer(Bin),
+ case QoS of
+ qos0 ->
+ N =:= NumMsgs;
+ qos1 ->
+ %% Allow for some duplicates when client resends
+ %% a message that gets acked at roughly the same time.
+ N >= NumMsgs andalso
+ N < NumMsgs * 2
+ end
+ end, L)
+ end), 2000, 10),
delete_queue(Ch, [CQ, CMQ, QQ, SQ]),
ok = rabbit_ct_broker_helpers:clear_policy(Config, 0, CMQ),
ok = emqtt:disconnect(C),
- ?awaitMatch(
- [],
- all_connection_pids(Config),
- 10_000,
- 1000
- ).
+ ?awaitMatch([],
+ all_connection_pids(Config), 10_000, 1000).
flow_classic_mirrored_queue(Config) ->
QueueName = <<"flow">>,
@@ -452,9 +386,8 @@ flow_quorum_queue(Config) ->
flow_stream(Config) ->
flow(Config, {rabbit, stream_messages_soft_limit, 1}, <<"stream">>).
-flow(Config, {App, Par, Val}, QueueType) when
- is_binary(QueueType)
-->
+flow(Config, {App, Par, Val}, QueueType)
+ when is_binary(QueueType) ->
{ok, DefaultVal} = rpc(Config, application, get_env, [App, Par]),
Result = rpc_all(Config, application, set_env, [App, Par, Val]),
?assert(lists:all(fun(R) -> R =:= ok end, Result)),
@@ -465,47 +398,27 @@ flow(Config, {App, Par, Val}, QueueType) when
bind(Ch, QueueName, Topic),
NumMsgs = 1000,
- C = connect(?FUNCTION_NAME, Config, [
- {retry_interval, 600},
- {max_inflight, NumMsgs}
- ]),
+ C = connect(?FUNCTION_NAME, Config, [{retry_interval, 600},
+ {max_inflight, NumMsgs}]),
TestPid = self(),
lists:foreach(
- fun(N) ->
- %% Publish async all messages at once to trigger flow control
- ok = emqtt:publish_async(
- C,
- Topic,
- integer_to_binary(N),
- qos1,
- {
- fun(N0, {ok, #{reason_code_name := success}}) ->
- TestPid ! {self(), N0}
- end,
- [N]
- }
- )
- end,
- lists:seq(1, NumMsgs)
- ),
+ fun(N) ->
+ %% Publish async all messages at once to trigger flow control
+ ok = emqtt:publish_async(C, Topic, integer_to_binary(N), qos1,
+ {fun(N0, {ok, #{reason_code_name := success}}) ->
+ TestPid ! {self(), N0}
+ end, [N]})
+ end, lists:seq(1, NumMsgs)),
ok = await_confirms_ordered(C, 1, NumMsgs),
- eventually(
- ?_assertEqual(
- [[integer_to_binary(NumMsgs)]],
- rabbitmqctl_list(Config, 0, ["list_queues", "messages", "--no-table-headers"])
- ),
- 1000,
- 10
- ),
+ eventually(?_assertEqual(
+ [[integer_to_binary(NumMsgs)]],
+ rabbitmqctl_list(Config, 0, ["list_queues", "messages", "--no-table-headers"])
+ ), 1000, 10),
delete_queue(Ch, QueueName),
ok = emqtt:disconnect(C),
- ?awaitMatch(
- [],
- all_connection_pids(Config),
- 10_000,
- 1000
- ),
+ ?awaitMatch([],
+ all_connection_pids(Config), 10_000, 1000),
Result = rpc_all(Config, application, set_env, [App, Par, DefaultVal]),
ok.
@@ -519,27 +432,20 @@ events(Config) ->
[E0, E1] = get_events(Server),
assert_event_type(user_authentication_success, E0),
- assert_event_prop(
- [
- {name, <<"guest">>},
- {connection_type, network}
- ],
- E0
- ),
+ assert_event_prop([{name, <<"guest">>},
+ {connection_type, network}],
+ E0),
assert_event_type(connection_created, E1),
[ConnectionPid] = all_connection_pids(Config),
- Proto =
- case ?config(websocket, Config) of
- true -> 'Web MQTT';
- false -> 'MQTT'
- end,
- ExpectedConnectionProps = [
- {protocol, {Proto, {3, 1, 1}}},
- {node, Server},
- {vhost, <<"/">>},
- {user, <<"guest">>},
- {pid, ConnectionPid}
- ],
+ Proto = case ?config(websocket, Config) of
+ true -> 'Web MQTT';
+ false -> 'MQTT'
+ end,
+ ExpectedConnectionProps = [{protocol, {Proto, {3,1,1}}},
+ {node, Server},
+ {vhost, <<"/">>},
+ {user, <<"guest">>},
+ {pid, ConnectionPid}],
assert_event_prop(ExpectedConnectionProps, E1),
{ok, _, _} = emqtt:subscribe(C, <<"TopicA">>, qos0),
@@ -547,50 +453,37 @@ events(Config) ->
QueueNameBin = <<"mqtt-subscription-", ClientId/binary, "qos0">>,
QueueName = {resource, <<"/">>, queue, QueueNameBin},
[E2, E3 | E4] = get_events(Server),
- QueueType =
- case rabbit_ct_helpers:is_mixed_versions(Config) of
- false ->
- ?assertEqual([], E4),
- rabbit_mqtt_qos0_queue;
- true ->
- %% Feature flag rabbit_mqtt_qos0_queue is disabled.
- [ConsumerCreated] = E4,
- assert_event_type(consumer_created, ConsumerCreated),
- assert_event_prop(
- [
- {queue, QueueName},
- {ack_required, false},
- {exclusive, false},
- {arguments, []}
- ],
- ConsumerCreated
- ),
- classic
- end,
+ QueueType = case rabbit_ct_helpers:is_mixed_versions(Config) of
+ false ->
+ ?assertEqual([], E4),
+ rabbit_mqtt_qos0_queue;
+ true ->
+ %% Feature flag rabbit_mqtt_qos0_queue is disabled.
+ [ConsumerCreated] = E4,
+ assert_event_type(consumer_created, ConsumerCreated),
+ assert_event_prop([{queue, QueueName},
+ {ack_required, false},
+ {exclusive, false},
+ {arguments, []}],
+ ConsumerCreated),
+ classic
+ end,
assert_event_type(queue_created, E2),
- assert_event_prop(
- [
- {name, QueueName},
- {durable, true},
- {auto_delete, false},
- {exclusive, true},
- {type, QueueType},
- {arguments, []}
- ],
- E2
- ),
+ assert_event_prop([{name, QueueName},
+ {durable, true},
+ {auto_delete, false},
+ {exclusive, true},
+ {type, QueueType},
+ {arguments, []}],
+ E2),
assert_event_type(binding_created, E3),
- assert_event_prop(
- [
- {source_name, <<"amq.topic">>},
- {source_kind, exchange},
- {destination_name, QueueNameBin},
- {destination_kind, queue},
- {routing_key, <<"TopicA">>},
- {arguments, []}
- ],
- E3
- ),
+ assert_event_prop([{source_name, <<"amq.topic">>},
+ {source_kind, exchange},
+ {destination_name, QueueNameBin},
+ {destination_kind, queue},
+ {routing_key, <<"TopicA">>},
+ {arguments, []}],
+ E3),
{ok, _, _} = emqtt:unsubscribe(C, <<"TopicA">>),
@@ -618,9 +511,7 @@ events(Config) ->
internal_event_handler(Config) ->
Server = get_node_config(Config, 0, nodename),
- ok = gen_event:call(
- {rabbit_event, Server}, rabbit_mqtt_internal_event_handler, ignored_request, 1000
- ).
+ ok = gen_event:call({rabbit_event, Server}, rabbit_mqtt_internal_event_handler, ignored_request, 1000).
global_counters_v3(Config) ->
global_counters(Config, v3).
@@ -648,82 +539,62 @@ global_counters(Config, ProtoVer) ->
ok = expect_publishes(C, Topic1, [<<"testm1">>]),
ok = expect_publishes(C, Topic2, [<<"testm2">>]),
- ?assertEqual(
- #{
- publishers => 1,
- consumers => 1,
- messages_confirmed_total => 2,
- messages_received_confirm_total => 2,
- messages_received_total => 5,
- messages_routed_total => 3,
- messages_unroutable_dropped_total => 1,
- messages_unroutable_returned_total => 1
- },
- get_global_counters(Config, ProtoVer)
- ),
+ ?assertEqual(#{publishers => 1,
+ consumers => 1,
+ messages_confirmed_total => 2,
+ messages_received_confirm_total => 2,
+ messages_received_total => 5,
+ messages_routed_total => 3,
+ messages_unroutable_dropped_total => 1,
+ messages_unroutable_returned_total => 1},
+ get_global_counters(Config, ProtoVer)),
case rabbit_ct_helpers:is_mixed_versions(Config) of
false ->
- ?assertEqual(
- #{
- messages_delivered_total => 2,
- messages_acknowledged_total => 1,
- messages_delivered_consume_auto_ack_total => 1,
- messages_delivered_consume_manual_ack_total => 1,
- messages_delivered_get_auto_ack_total => 0,
- messages_delivered_get_manual_ack_total => 0,
- messages_get_empty_total => 0,
- messages_redelivered_total => 0
- },
- get_global_counters(Config, ProtoVer, 0, [{queue_type, rabbit_classic_queue}])
- ),
- ?assertEqual(
- #{
- messages_delivered_total => 1,
- messages_acknowledged_total => 0,
- messages_delivered_consume_auto_ack_total => 1,
- messages_delivered_consume_manual_ack_total => 0,
- messages_delivered_get_auto_ack_total => 0,
- messages_delivered_get_manual_ack_total => 0,
- messages_get_empty_total => 0,
- messages_redelivered_total => 0
- },
- get_global_counters(Config, ProtoVer, 0, [{queue_type, rabbit_mqtt_qos0_queue}])
- );
+ ?assertEqual(#{messages_delivered_total => 2,
+ messages_acknowledged_total => 1,
+ messages_delivered_consume_auto_ack_total => 1,
+ messages_delivered_consume_manual_ack_total => 1,
+ messages_delivered_get_auto_ack_total => 0,
+ messages_delivered_get_manual_ack_total => 0,
+ messages_get_empty_total => 0,
+ messages_redelivered_total => 0},
+ get_global_counters(Config, ProtoVer, 0, [{queue_type, rabbit_classic_queue}])),
+ ?assertEqual(#{messages_delivered_total => 1,
+ messages_acknowledged_total => 0,
+ messages_delivered_consume_auto_ack_total => 1,
+ messages_delivered_consume_manual_ack_total => 0,
+ messages_delivered_get_auto_ack_total => 0,
+ messages_delivered_get_manual_ack_total => 0,
+ messages_get_empty_total => 0,
+ messages_redelivered_total => 0},
+ get_global_counters(Config, ProtoVer, 0, [{queue_type, rabbit_mqtt_qos0_queue}]));
true ->
%% Feature flag rabbit_mqtt_qos0_queue is disabled.
- ?assertEqual(
- #{
- messages_delivered_total => 3,
- messages_acknowledged_total => 1,
- messages_delivered_consume_auto_ack_total => 2,
- messages_delivered_consume_manual_ack_total => 1,
- messages_delivered_get_auto_ack_total => 0,
- messages_delivered_get_manual_ack_total => 0,
- messages_get_empty_total => 0,
- messages_redelivered_total => 0
- },
- get_global_counters(Config, ProtoVer, 0, [{queue_type, rabbit_classic_queue}])
- )
+ ?assertEqual(#{messages_delivered_total => 3,
+ messages_acknowledged_total => 1,
+ messages_delivered_consume_auto_ack_total => 2,
+ messages_delivered_consume_manual_ack_total => 1,
+ messages_delivered_get_auto_ack_total => 0,
+ messages_delivered_get_manual_ack_total => 0,
+ messages_get_empty_total => 0,
+ messages_redelivered_total => 0},
+ get_global_counters(Config, ProtoVer, 0, [{queue_type, rabbit_classic_queue}]))
end,
{ok, _, _} = emqtt:unsubscribe(C, Topic1),
?assertEqual(1, maps:get(consumers, get_global_counters(Config, ProtoVer))),
ok = emqtt:disconnect(C),
- ?assertEqual(
- #{
- publishers => 0,
- consumers => 0,
- messages_confirmed_total => 2,
- messages_received_confirm_total => 2,
- messages_received_total => 5,
- messages_routed_total => 3,
- messages_unroutable_dropped_total => 1,
- messages_unroutable_returned_total => 1
- },
- get_global_counters(Config, ProtoVer)
- ).
+ ?assertEqual(#{publishers => 0,
+ consumers => 0,
+ messages_confirmed_total => 2,
+ messages_received_confirm_total => 2,
+ messages_received_total => 5,
+ messages_routed_total => 3,
+ messages_unroutable_dropped_total => 1,
+ messages_unroutable_returned_total => 1},
+ get_global_counters(Config, ProtoVer)).
queue_down_qos1(Config) ->
{Conn1, Ch1} = rabbit_ct_client_helpers:open_connection_and_channel(Config, 1),
@@ -740,14 +611,9 @@ queue_down_qos1(Config) ->
ok = rabbit_ct_broker_helpers:start_node(Config, 1),
%% classic queue is up, therefore message should arrive
- eventually(
- ?_assertEqual(
- [[<<"1">>]],
- rabbitmqctl_list(Config, 1, ["list_queues", "messages", "--no-table-headers"])
- ),
- 500,
- 20
- ),
+ eventually(?_assertEqual([[<<"1">>]],
+ rabbitmqctl_list(Config, 1, ["list_queues", "messages", "--no-table-headers"])),
+ 500, 20),
Ch0 = rabbit_ct_client_helpers:open_channel(Config, 0),
delete_queue(Ch0, CQ),
@@ -761,16 +627,9 @@ consuming_classic_mirrored_queue_down(Config) ->
ClientId = Topic = PolicyName = atom_to_binary(?FUNCTION_NAME),
ok = rabbit_ct_broker_helpers:set_policy(
- Config,
- Server1,
- PolicyName,
- <<".*">>,
- <<"queues">>,
- [
- {<<"ha-mode">>, <<"all">>},
- {<<"queue-master-locator">>, <<"client-local">>}
- ]
- ),
+ Config, Server1, PolicyName, <<".*">>, <<"queues">>,
+ [{<<"ha-mode">>, <<"all">>},
+ {<<"queue-master-locator">>, <<"client-local">>}]),
%% Declare queue leader on Server1.
C1 = connect(ClientId, Config, Server1, [{clean_start, false}]),
@@ -794,16 +653,12 @@ consuming_classic_mirrored_queue_down(Config) ->
%% Cleanup
ok = emqtt:disconnect(C2),
ok = rabbit_ct_broker_helpers:start_node(Config, Server1),
- ?assertMatch(
- [_Q],
- rpc(Config, Server1, rabbit_amqqueue, list, [])
- ),
+ ?assertMatch([_Q],
+ rpc(Config, Server1, rabbit_amqqueue, list, [])),
C3 = connect(ClientId, Config, Server2, [{clean_start, true}]),
ok = emqtt:disconnect(C3),
- ?assertEqual(
- [],
- rpc(Config, Server1, rabbit_amqqueue, list, [])
- ),
+ ?assertEqual([],
+ rpc(Config, Server1, rabbit_amqqueue, list, [])),
ok = rabbit_ct_broker_helpers:clear_policy(Config, Server1, PolicyName).
%% Consuming classic queue on a different node goes down.
@@ -820,10 +675,8 @@ consuming_classic_queue_down(Config) ->
C2 = connect(ClientId, Config, Server3, [{clean_start, false}]),
ProtoVer = v4,
- ?assertMatch(
- #{consumers := 1},
- get_global_counters(Config, ProtoVer, Server3)
- ),
+ ?assertMatch(#{consumers := 1},
+ get_global_counters(Config, ProtoVer, Server3)),
%% Let's stop the queue leader node.
process_flag(trap_exit, true),
@@ -831,24 +684,17 @@ consuming_classic_queue_down(Config) ->
%% When the dedicated MQTT connection (non-mirrored classic) queue goes down, it is reasonable
%% that the server closes the MQTT connection because the MQTT client cannot consume anymore.
- eventually(
- ?_assertMatch(
- #{consumers := 0},
- get_global_counters(Config, ProtoVer, Server3)
- ),
- 1000,
- 5
- ),
+ eventually(?_assertMatch(#{consumers := 0},
+ get_global_counters(Config, ProtoVer, Server3)),
+ 1000, 5),
await_exit(C2),
%% Cleanup
ok = rabbit_ct_broker_helpers:start_node(Config, Server1),
C3 = connect(ClientId, Config, Server3, [{clean_start, true}]),
ok = emqtt:disconnect(C3),
- ?assertEqual(
- [],
- rpc(Config, Server1, rabbit_amqqueue, list, [])
- ),
+ ?assertEqual([],
+ rpc(Config, Server1, rabbit_amqqueue, list, [])),
ok.
delete_create_queue(Config) ->
@@ -859,13 +705,13 @@ delete_create_queue(Config) ->
Topic = atom_to_binary(?FUNCTION_NAME),
DeclareQueues = fun() ->
- declare_queue(Ch, CQ1, []),
- bind(Ch, CQ1, Topic),
- declare_queue(Ch, CQ2, []),
- bind(Ch, CQ2, Topic),
- declare_queue(Ch, QQ, [{<<"x-queue-type">>, longstr, <<"quorum">>}]),
- bind(Ch, QQ, Topic)
- end,
+ declare_queue(Ch, CQ1, []),
+ bind(Ch, CQ1, Topic),
+ declare_queue(Ch, CQ2, []),
+ bind(Ch, CQ2, Topic),
+ declare_queue(Ch, QQ, [{<<"x-queue-type">>, longstr, <<"quorum">>}]),
+ bind(Ch, QQ, Topic)
+ end,
DeclareQueues(),
%% some large retry_interval to avoid re-sending
@@ -873,26 +719,15 @@ delete_create_queue(Config) ->
NumMsgs = 50,
TestPid = self(),
spawn(
- fun() ->
- lists:foreach(
+ fun() ->
+ lists:foreach(
fun(N) ->
- ok = emqtt:publish_async(
- C,
- Topic,
- integer_to_binary(N),
- qos1,
- {
- fun(N0, {ok, #{reason_code_name := success}}) ->
- TestPid ! {self(), N0}
- end,
- [N]
- }
- )
- end,
- lists:seq(1, NumMsgs)
- )
- end
- ),
+ ok = emqtt:publish_async(C, Topic, integer_to_binary(N), qos1,
+ {fun(N0, {ok, #{reason_code_name := success}}) ->
+ TestPid ! {self(), N0}
+ end, [N]})
+ end, lists:seq(1, NumMsgs))
+ end),
%% Delete queues while sending to them.
%% We want to test the path where a queue is deleted while confirms are outstanding.
@@ -913,23 +748,12 @@ delete_create_queue(Config) ->
%% Sending a message to each of them should work.
{ok, _} = emqtt:publish(C, Topic, <<"m">>, qos1),
- eventually(
- ?_assertEqual(
- lists:sort([
- [CQ1, <<"1">>],
- %% This queue should have all messages because we did not delete it.
- [CQ2, integer_to_binary(NumMsgs + 1)],
- [QQ, <<"1">>]
- ]),
- lists:sort(
- rabbitmqctl_list(Config, 0, [
- "list_queues", "name", "messages", "--no-table-headers"
- ])
- )
- ),
- 1000,
- 10
- ),
+ eventually(?_assertEqual(lists:sort([[CQ1, <<"1">>],
+ %% This queue should have all messages because we did not delete it.
+ [CQ2, integer_to_binary(NumMsgs + 1)],
+ [QQ, <<"1">>]]),
+ lists:sort(rabbitmqctl_list(Config, 0, ["list_queues", "name", "messages", "--no-table-headers"]))),
+ 1000, 10),
delete_queue(Ch, [CQ1, CQ2, QQ]),
ok = emqtt:disconnect(C).
@@ -942,15 +766,13 @@ subscription_ttl(Config) ->
ok = rpc(Config, application, set_env, [App, Par, TTL]),
C = connect(ClientId, Config, [{clean_start, false}]),
- {ok, _, [0, 1]} = emqtt:subscribe(C, [
- {<<"topic0">>, qos0},
- {<<"topic1">>, qos1}
- ]),
+ {ok, _, [0, 1]} = emqtt:subscribe(C, [{<<"topic0">>, qos0},
+ {<<"topic1">>, qos1}]),
ok = emqtt:disconnect(C),
?assertEqual(2, rpc(Config, rabbit_amqqueue, count, [])),
timer:sleep(TTL + 100),
- ?assertEqual(0, rpc(Config, rabbit_amqqueue, count, [])),
+ ?assertEqual(0, rpc(Config, rabbit_amqqueue, count, [])),
ok = rpc(Config, application, set_env, [App, Par, DefaultVal]).
@@ -967,36 +789,28 @@ non_clean_sess_reconnect(Config, SubscriptionQoS) ->
C1 = connect(ClientId, Config, [{clean_start, false}]),
{ok, _, _} = emqtt:subscribe(C1, Topic, SubscriptionQoS),
- ?assertMatch(
- #{consumers := 1},
- get_global_counters(Config, ProtoVer)
- ),
+ ?assertMatch(#{consumers := 1},
+ get_global_counters(Config, ProtoVer)),
ok = emqtt:disconnect(C1),
- ?assertMatch(
- #{consumers := 0},
- get_global_counters(Config, ProtoVer)
- ),
+ ?assertMatch(#{consumers := 0},
+ get_global_counters(Config, ProtoVer)),
timer:sleep(20),
ok = emqtt:publish(Pub, Topic, <<"msg-3-qos0">>, qos0),
{ok, _} = emqtt:publish(Pub, Topic, <<"msg-4-qos1">>, qos1),
C2 = connect(ClientId, Config, [{clean_start, false}]),
- ?assertMatch(
- #{consumers := 1},
- get_global_counters(Config, ProtoVer)
- ),
+ ?assertMatch(#{consumers := 1},
+ get_global_counters(Config, ProtoVer)),
ok = emqtt:publish(Pub, Topic, <<"msg-5-qos0">>, qos0),
{ok, _} = emqtt:publish(Pub, Topic, <<"msg-6-qos1">>, qos1),
%% shouldn't receive message after unsubscribe
{ok, _, _} = emqtt:unsubscribe(C2, Topic),
- ?assertMatch(
- #{consumers := 0},
- get_global_counters(Config, ProtoVer)
- ),
+ ?assertMatch(#{consumers := 0},
+ get_global_counters(Config, ProtoVer)),
{ok, _} = emqtt:publish(Pub, Topic, <<"msg-7-qos0">>, qos1),
%% "After the disconnection of a Session that had CleanSession set to 0, the Server MUST store
@@ -1004,12 +818,8 @@ non_clean_sess_reconnect(Config, SubscriptionQoS) ->
%% time of disconnection as part of the Session state [MQTT-3.1.2-5].
%% It MAY also store QoS 0 messages that meet the same criteria."
%% Starting with RabbitMQ v3.12 we store QoS 0 messages as well.
- ok = expect_publishes(C2, Topic, [
- <<"msg-3-qos0">>,
- <<"msg-4-qos1">>,
- <<"msg-5-qos0">>,
- <<"msg-6-qos1">>
- ]),
+ ok = expect_publishes(C2, Topic, [<<"msg-3-qos0">>, <<"msg-4-qos1">>,
+ <<"msg-5-qos0">>, <<"msg-6-qos1">>]),
{publish_not_received, <<"msg-7-qos0">>} = expect_publishes(C2, Topic, [<<"msg-7-qos0">>]),
ok = emqtt:disconnect(Pub),
@@ -1027,25 +837,19 @@ non_clean_sess_reconnect_qos0_and_qos1(Config) ->
C1 = connect(ClientId, Config, [{clean_start, false}]),
{ok, _, [1, 0]} = emqtt:subscribe(C1, [{Topic1, qos1}, {Topic0, qos0}]),
- ?assertMatch(
- #{consumers := 1},
- get_global_counters(Config, ProtoVer)
- ),
+ ?assertMatch(#{consumers := 1},
+ get_global_counters(Config, ProtoVer)),
ok = emqtt:disconnect(C1),
- ?assertMatch(
- #{consumers := 0},
- get_global_counters(Config, ProtoVer)
- ),
+ ?assertMatch(#{consumers := 0},
+ get_global_counters(Config, ProtoVer)),
{ok, _} = emqtt:publish(Pub, Topic0, <<"msg-0">>, qos1),
{ok, _} = emqtt:publish(Pub, Topic1, <<"msg-1">>, qos1),
C2 = connect(ClientId, Config, [{clean_start, false}]),
- ?assertMatch(
- #{consumers := 1},
- get_global_counters(Config, ProtoVer)
- ),
+ ?assertMatch(#{consumers := 1},
+ get_global_counters(Config, ProtoVer)),
ok = expect_publishes(C2, Topic0, [<<"msg-0">>]),
ok = expect_publishes(C2, Topic1, [<<"msg-1">>]),
@@ -1059,10 +863,8 @@ subscribe_same_topic_same_qos(Config) ->
C = connect(?FUNCTION_NAME, Config),
Topic = <<"a/b">>,
- {ok, _} = emqtt:publish(C, Topic, <<"retained">>, [
- {retain, true},
- {qos, 1}
- ]),
+ {ok, _} = emqtt:publish(C, Topic, <<"retained">>, [{retain, true},
+ {qos, 1}]),
%% Subscribe with QoS 0
{ok, _, [0]} = emqtt:subscribe(C, Topic, qos0),
{ok, _} = emqtt:publish(C, Topic, <<"msg1">>, qos1),
@@ -1071,22 +873,17 @@ subscribe_same_topic_same_qos(Config) ->
{ok, _} = emqtt:publish(C, Topic, <<"msg2">>, qos1),
%% "Any existing retained messages matching the Topic Filter MUST be re-sent" [MQTT-3.8.4-3]
- ok = expect_publishes(C, Topic, [
- <<"retained">>,
- <<"msg1">>,
- <<"retained">>,
- <<"msg2">>
- ]),
+ ok = expect_publishes(C, Topic, [<<"retained">>, <<"msg1">>,
+ <<"retained">>, <<"msg2">>
+ ]),
ok = emqtt:disconnect(C).
subscribe_same_topic_different_qos(Config) ->
C = connect(?FUNCTION_NAME, Config, [{clean_start, false}]),
Topic = <<"b/c">>,
- {ok, _} = emqtt:publish(C, Topic, <<"retained">>, [
- {retain, true},
- {qos, 1}
- ]),
+ {ok, _} = emqtt:publish(C, Topic, <<"retained">>, [{retain, true},
+ {qos, 1}]),
%% Subscribe with QoS 0
{ok, _, [0]} = emqtt:subscribe(C, Topic, qos0),
{ok, _} = emqtt:publish(C, Topic, <<"msg1">>, qos1),
@@ -1098,14 +895,9 @@ subscribe_same_topic_different_qos(Config) ->
{ok, _} = emqtt:publish(C, Topic, <<"msg3">>, qos1),
%% "Any existing retained messages matching the Topic Filter MUST be re-sent" [MQTT-3.8.4-3]
- ok = expect_publishes(C, Topic, [
- <<"retained">>,
- <<"msg1">>,
- <<"retained">>,
- <<"msg2">>,
- <<"retained">>,
- <<"msg3">>
- ]),
+ ok = expect_publishes(C, Topic, [<<"retained">>, <<"msg1">>,
+ <<"retained">>, <<"msg2">>,
+ <<"retained">>, <<"msg3">>]),
%% There should be exactly one consumer for each queue: qos0 and qos1
Consumers = rpc(Config, rabbit_amqqueue, consumers_all, [<<"/">>]),
@@ -1118,13 +910,9 @@ subscribe_same_topic_different_qos(Config) ->
subscribe_multiple(Config) ->
C = connect(?FUNCTION_NAME, Config),
%% Subscribe to multiple topics at once
- ?assertMatch(
- {ok, _, [0, 1]},
- emqtt:subscribe(C, [
- {<<"topic0">>, qos0},
- {<<"topic1">>, qos1}
- ])
- ),
+ ?assertMatch({ok, _, [0, 1]},
+ emqtt:subscribe(C, [{<<"topic0">>, qos0},
+ {<<"topic1">>, qos1}])),
ok = emqtt:disconnect(C).
large_message_mqtt_to_mqtt(Config) ->
@@ -1146,14 +934,10 @@ large_message_amqp_to_mqtt(Config) ->
Ch = rabbit_ct_client_helpers:open_channel(Config),
Payload0 = binary:copy(<<"x">>, 8_000_000),
Payload = <<Payload0/binary, "y">>,
- amqp_channel:call(
- Ch,
- #'basic.publish'{
- exchange = <<"amq.topic">>,
- routing_key = Topic
- },
- #amqp_msg{payload = Payload}
- ),
+ amqp_channel:call(Ch,
+ #'basic.publish'{exchange = <<"amq.topic">>,
+ routing_key = Topic},
+ #amqp_msg{payload = Payload}),
ok = expect_publishes(C, Topic, [Payload]),
ok = emqtt:disconnect(C).
@@ -1163,14 +947,10 @@ amqp_to_mqtt_qos0(Config) ->
{ok, _, [0]} = emqtt:subscribe(C, {Topic, qos0}),
Ch = rabbit_ct_client_helpers:open_channel(Config),
- amqp_channel:call(
- Ch,
- #'basic.publish'{
- exchange = <<"amq.topic">>,
- routing_key = Topic
- },
- #amqp_msg{payload = Payload}
- ),
+ amqp_channel:call(Ch,
+ #'basic.publish'{exchange = <<"amq.topic">>,
+ routing_key = Topic},
+ #amqp_msg{payload = Payload}),
ok = expect_publishes(C, Topic, [Payload]),
ok = emqtt:disconnect(C).
@@ -1182,12 +962,9 @@ many_qos1_messages(Config) ->
{ok, _, [1]} = emqtt:subscribe(C, {Topic, qos1}),
NumMsgs = 16#ffff + 100,
Payloads = lists:map(fun integer_to_binary/1, lists:seq(1, NumMsgs)),
- lists:foreach(
- fun(P) ->
- {ok, _} = emqtt:publish(C, Topic, P, qos1)
- end,
- Payloads
- ),
+ lists:foreach(fun(P) ->
+ {ok, _} = emqtt:publish(C, Topic, P, qos1)
+ end, Payloads),
expect_publishes(C, Topic, Payloads),
ok = emqtt:disconnect(C).
@@ -1218,21 +995,15 @@ management_plugin_connection(Config) ->
C = connect(ClientId, Config, [{keepalive, KeepaliveSecs}]),
eventually(?_assertEqual(1, length(http_get(Config, "/connections"))), 1000, 10),
- [
- #{
- client_properties := #{client_id := ClientId},
- timeout := KeepaliveSecs,
- node := Node,
- name := ConnectionName
- }
- ] = http_get(Config, "/connections"),
+ [#{client_properties := #{client_id := ClientId},
+ timeout := KeepaliveSecs,
+ node := Node,
+ name := ConnectionName}] = http_get(Config, "/connections"),
process_flag(trap_exit, true),
- http_delete(
- Config,
- "/connections/" ++ binary_to_list(uri_string:quote((ConnectionName))),
- ?NO_CONTENT
- ),
+ http_delete(Config,
+ "/connections/" ++ binary_to_list(uri_string:quote((ConnectionName))),
+ ?NO_CONTENT),
await_exit(C),
?assertEqual([], http_get(Config, "/connections")),
eventually(?_assertEqual([], all_connection_pids(Config)), 500, 3).
@@ -1257,54 +1028,25 @@ cli_list_queues(Config) ->
{ok, _, _} = emqtt:subscribe(C, <<"a/b/c">>, qos0),
Qs = rabbit_ct_broker_helpers:rabbitmqctl_list(
- Config,
- 1,
- [
- "list_queues",
- "--no-table-headers",
- "type",
- "name",
- "state",
- "durable",
- "auto_delete",
- "arguments",
- "pid",
- "owner_pid",
- "messages",
- "exclusive_consumer_tag"
- ]
- ),
- ExpectedQueueType =
- case rabbit_ct_helpers:is_mixed_versions(Config) of
- false ->
- <<"MQTT QoS 0">>;
- true ->
- <<"classic">>
- end,
- ?assertMatch(
- [
- [
- ExpectedQueueType,
- <<"mqtt-subscription-cli_list_queuesqos0">>,
- <<"running">>,
- <<"true">>,
- <<"false">>,
- <<"[]">>,
- _,
- _,
- <<"0">>,
- <<"">>
- ]
- ],
- Qs
- ),
-
- ?assertEqual(
- [],
- rabbit_ct_broker_helpers:rabbitmqctl_list(
- Config, 1, ["list_queues", "--local", "--no-table-headers"]
- )
- ),
+ Config, 1,
+ ["list_queues", "--no-table-headers",
+ "type", "name", "state", "durable", "auto_delete",
+ "arguments", "pid", "owner_pid", "messages", "exclusive_consumer_tag"
+ ]),
+ ExpectedQueueType = case rabbit_ct_helpers:is_mixed_versions(Config) of
+ false ->
+ <<"MQTT QoS 0">>;
+ true ->
+ <<"classic">>
+ end,
+ ?assertMatch([[ExpectedQueueType, <<"mqtt-subscription-cli_list_queuesqos0">>,
+ <<"running">>, <<"true">>, <<"false">>, <<"[]">>, _, _, <<"0">>, <<"">>]],
+ Qs),
+
+ ?assertEqual([],
+ rabbit_ct_broker_helpers:rabbitmqctl_list(
+ Config, 1, ["list_queues", "--local", "--no-table-headers"])
+ ),
ok = emqtt:disconnect(C).
@@ -1336,39 +1078,30 @@ keepalive(Config) ->
ProtoVer = v4,
WillTopic = <<"will/topic">>,
WillPayload = <<"will-payload">>,
- C1 = connect(?FUNCTION_NAME, Config, [
- {keepalive, KeepaliveSecs},
- {proto_ver, ProtoVer},
- {will_topic, WillTopic},
- {will_payload, WillPayload},
- {will_retain, true},
- {will_qos, 0}
- ]),
+ C1 = connect(?FUNCTION_NAME, Config, [{keepalive, KeepaliveSecs},
+ {proto_ver, ProtoVer},
+ {will_topic, WillTopic},
+ {will_payload, WillPayload},
+ {will_retain, true},
+ {will_qos, 0}]),
ok = emqtt:publish(C1, <<"ignored">>, <<"msg">>),
%% Connection should stay up when client sends PING requests.
timer:sleep(KeepaliveMs),
- ?assertMatch(
- #{publishers := 1},
- util:get_global_counters(Config, ProtoVer)
- ),
+ ?assertMatch(#{publishers := 1},
+ util:get_global_counters(Config, ProtoVer)),
%% Mock the server socket to not have received any bytes.
rabbit_ct_broker_helpers:setup_meck(Config),
Mod = rabbit_net,
ok = rpc(Config, meck, new, [Mod, [no_link, passthrough]]),
- ok = rpc(Config, meck, expect, [Mod, getstat, 2, {ok, [{recv_oct, 999}]}]),
+ ok = rpc(Config, meck, expect, [Mod, getstat, 2, {ok, [{recv_oct, 999}]} ]),
process_flag(trap_exit, true),
%% We expect the server to respect the keepalive closing the connection.
- eventually(
- ?_assertMatch(
- #{publishers := 0},
- util:get_global_counters(Config, ProtoVer)
- ),
- KeepaliveMs,
- 3 * KeepaliveSecs
- ),
+ eventually(?_assertMatch(#{publishers := 0},
+ util:get_global_counters(Config, ProtoVer)),
+ KeepaliveMs, 3 * KeepaliveSecs),
await_exit(C1),
true = rpc(Config, meck, validate, [Mod]),
@@ -1376,16 +1109,12 @@ keepalive(Config) ->
C2 = connect(<<"client2">>, Config),
{ok, _, [0]} = emqtt:subscribe(C2, WillTopic),
- receive
- {publish, #{
- client_pid := C2,
- dup := false,
- qos := 0,
- retain := true,
- topic := WillTopic,
- payload := WillPayload
- }} ->
- ok
+ receive {publish, #{client_pid := C2,
+ dup := false,
+ qos := 0,
+ retain := true,
+ topic := WillTopic,
+ payload := WillPayload}} -> ok
after 3000 -> ct:fail("missing will")
end,
ok = emqtt:disconnect(C2).
@@ -1400,7 +1129,7 @@ keepalive_turned_off(Config) ->
rabbit_ct_broker_helpers:setup_meck(Config),
Mod = rabbit_net,
ok = rpc(Config, meck, new, [Mod, [no_link, passthrough]]),
- ok = rpc(Config, meck, expect, [Mod, getstat, 2, {ok, [{recv_oct, 999}]}]),
+ ok = rpc(Config, meck, expect, [Mod, getstat, 2, {ok, [{recv_oct, 999}]} ]),
rabbit_ct_helpers:consistently(?_assert(erlang:is_process_alive(C))),
@@ -1438,11 +1167,9 @@ block(Config) ->
%% Unblock
rpc(Config, vm_memory_monitor, set_vm_memory_high_watermark, [0.4]),
- ok = expect_publishes(C, Topic, [
- <<"Not blocked yet">>,
- <<"Now blocked">>,
- <<"Still blocked">>
- ]),
+ ok = expect_publishes(C, Topic, [<<"Not blocked yet">>,
+ <<"Now blocked">>,
+ <<"Still blocked">>]),
ok = emqtt:disconnect(C).
block_only_publisher(Config) ->
@@ -1510,9 +1237,7 @@ clean_session_disconnect_client(Config) ->
ok = emqtt:disconnect(C),
%% After terminating a clean session, we expect any session state to be cleaned up on the server.
-
- %% Give some time to clean up exclusive classic queue.
- timer:sleep(200),
+ timer:sleep(200), %% Give some time to clean up exclusive classic queue.
L = rpc(Config, rabbit_amqqueue, list, []),
?assertEqual(0, length(L)).
@@ -1555,12 +1280,9 @@ trace(Config) ->
Ch = rabbit_ct_client_helpers:open_channel(Config),
declare_queue(Ch, TraceQ, []),
#'queue.bind_ok'{} = amqp_channel:call(
- Ch, #'queue.bind'{
- queue = TraceQ,
- exchange = <<"amq.rabbitmq.trace">>,
- routing_key = <<"#">>
- }
- ),
+ Ch, #'queue.bind'{queue = TraceQ,
+ exchange = <<"amq.rabbitmq.trace">>,
+ routing_key = <<"#">>}),
%% We expect traced messages for connections created before and connections
%% created after tracing is enabled.
@@ -1572,65 +1294,45 @@ trace(Config) ->
{ok, _} = emqtt:publish(Pub, Topic, Payload, qos1),
ok = expect_publishes(Sub, Topic, [Payload]),
- {#'basic.get_ok'{routing_key = <<"publish.amq.topic">>}, #amqp_msg{
- props = #'P_basic'{headers = PublishHeaders},
- payload = Payload
- }} =
- amqp_channel:call(Ch, #'basic.get'{queue = TraceQ, no_ack = false}),
- ?assertMatch(
- #{
- <<"exchange_name">> := <<"amq.topic">>,
- <<"routing_keys">> := [Topic],
- <<"connection">> := <<"127.0.0.1:", _/binary>>,
- <<"node">> := Server,
- <<"vhost">> := <<"/">>,
- <<"channel">> := 0,
- <<"user">> := <<"guest">>,
- <<"properties">> := #{
- <<"delivery_mode">> := 2,
- <<"headers">> := #{
- <<"x-mqtt-publish-qos">> := 1,
- <<"x-mqtt-dup">> := false
- }
- },
- <<"routed_queues">> := [<<"mqtt-subscription-trace_subscriberqos0">>]
- },
- rabbit_misc:amqp_table(PublishHeaders)
- ),
-
- {#'basic.get_ok'{routing_key = <<"deliver.mqtt-subscription-trace_subscriberqos0">>}, #amqp_msg{
- props = #'P_basic'{headers = DeliverHeaders},
- payload = Payload
- }} =
- amqp_channel:call(Ch, #'basic.get'{queue = TraceQ, no_ack = false}),
- ?assertMatch(
- #{
- <<"exchange_name">> := <<"amq.topic">>,
- <<"routing_keys">> := [Topic],
- <<"connection">> := <<"127.0.0.1:", _/binary>>,
- <<"node">> := Server,
- <<"vhost">> := <<"/">>,
- <<"channel">> := 0,
- <<"user">> := <<"guest">>,
- <<"properties">> := #{
- <<"delivery_mode">> := 2,
- <<"headers">> := #{
- <<"x-mqtt-publish-qos">> := 1,
- <<"x-mqtt-dup">> := false
- }
- },
- <<"redelivered">> := 0
- },
- rabbit_misc:amqp_table(DeliverHeaders)
- ),
+ {#'basic.get_ok'{routing_key = <<"publish.amq.topic">>},
+ #amqp_msg{props = #'P_basic'{headers = PublishHeaders},
+ payload = Payload}} =
+ amqp_channel:call(Ch, #'basic.get'{queue = TraceQ, no_ack = false}),
+ ?assertMatch(#{<<"exchange_name">> := <<"amq.topic">>,
+ <<"routing_keys">> := [Topic],
+ <<"connection">> := <<"127.0.0.1:", _/binary>>,
+ <<"node">> := Server,
+ <<"vhost">> := <<"/">>,
+ <<"channel">> := 0,
+ <<"user">> := <<"guest">>,
+ <<"properties">> := #{<<"delivery_mode">> := 2,
+ <<"headers">> := #{<<"x-mqtt-publish-qos">> := 1,
+ <<"x-mqtt-dup">> := false}},
+ <<"routed_queues">> := [<<"mqtt-subscription-trace_subscriberqos0">>]},
+ rabbit_misc:amqp_table(PublishHeaders)),
+
+ {#'basic.get_ok'{routing_key = <<"deliver.mqtt-subscription-trace_subscriberqos0">>},
+ #amqp_msg{props = #'P_basic'{headers = DeliverHeaders},
+ payload = Payload}} =
+ amqp_channel:call(Ch, #'basic.get'{queue = TraceQ, no_ack = false}),
+ ?assertMatch(#{<<"exchange_name">> := <<"amq.topic">>,
+ <<"routing_keys">> := [Topic],
+ <<"connection">> := <<"127.0.0.1:", _/binary>>,
+ <<"node">> := Server,
+ <<"vhost">> := <<"/">>,
+ <<"channel">> := 0,
+ <<"user">> := <<"guest">>,
+ <<"properties">> := #{<<"delivery_mode">> := 2,
+ <<"headers">> := #{<<"x-mqtt-publish-qos">> := 1,
+ <<"x-mqtt-dup">> := false}},
+ <<"redelivered">> := 0},
+ rabbit_misc:amqp_table(DeliverHeaders)),
{ok, _} = rabbit_ct_broker_helpers:rabbitmqctl(Config, 0, ["trace_off"]),
{ok, _} = emqtt:publish(Pub, Topic, Payload, qos1),
ok = expect_publishes(Sub, Topic, [Payload]),
- ?assertMatch(
- #'basic.get_empty'{},
- amqp_channel:call(Ch, #'basic.get'{queue = TraceQ, no_ack = false})
- ),
+ ?assertMatch(#'basic.get_empty'{},
+ amqp_channel:call(Ch, #'basic.get'{queue = TraceQ, no_ack = false})),
delete_queue(Ch, TraceQ),
[ok = emqtt:disconnect(C) || C <- [Pub, Sub]].
@@ -1649,7 +1351,7 @@ await_confirms_ordered(From, N, To) ->
Got ->
ct:fail("Received unexpected message. Expected: ~p Got: ~p", [Expected, Got])
after 10_000 ->
- ct:fail("Did not receive expected message: ~p", [Expected])
+ ct:fail("Did not receive expected message: ~p", [Expected])
end.
await_confirms_unordered(_, 0) ->
@@ -1661,45 +1363,32 @@ await_confirms_unordered(From, Left) ->
Other ->
ct:fail("Received unexpected message: ~p", [Other])
after 10_000 ->
- ct:fail("~b confirms are missing", [Left])
+ ct:fail("~b confirms are missing", [Left])
end.
-declare_queue(Ch, QueueName, Args) when
- is_pid(Ch), is_binary(QueueName), is_list(Args)
-->
+declare_queue(Ch, QueueName, Args)
+ when is_pid(Ch), is_binary(QueueName), is_list(Args) ->
#'queue.declare_ok'{} = amqp_channel:call(
- Ch, #'queue.declare'{
- queue = QueueName,
- durable = true,
- arguments = Args
- }
- ).
-
-delete_queue(Ch, QueueNames) when
- is_pid(Ch), is_list(QueueNames)
-->
+ Ch, #'queue.declare'{
+ queue = QueueName,
+ durable = true,
+ arguments = Args}).
+
+delete_queue(Ch, QueueNames)
+ when is_pid(Ch), is_list(QueueNames) ->
lists:foreach(
- fun(Q) ->
- delete_queue(Ch, Q)
- end,
- QueueNames
- );
-delete_queue(Ch, QueueName) when
- is_pid(Ch), is_binary(QueueName)
-->
+ fun(Q) ->
+ delete_queue(Ch, Q)
+ end, QueueNames);
+delete_queue(Ch, QueueName)
+ when is_pid(Ch), is_binary(QueueName) ->
#'queue.delete_ok'{} = amqp_channel:call(
- Ch, #'queue.delete'{
- queue = QueueName
- }
- ).
-
-bind(Ch, QueueName, Topic) when
- is_pid(Ch), is_binary(QueueName), is_binary(Topic)
-->
+ Ch, #'queue.delete'{
+ queue = QueueName}).
+
+bind(Ch, QueueName, Topic)
+ when is_pid(Ch), is_binary(QueueName), is_binary(Topic) ->
#'queue.bind_ok'{} = amqp_channel:call(
- Ch, #'queue.bind'{
- queue = QueueName,
- exchange = <<"amq.topic">>,
- routing_key = Topic
- }
- ).
+ Ch, #'queue.bind'{queue = QueueName,
+ exchange = <<"amq.topic">>,
+ routing_key = Topic}).
diff --git a/deps/rabbitmq_mqtt/test/util.erl b/deps/rabbitmq_mqtt/test/util.erl
index 38689b2110..44c684a6c5 100644
--- a/deps/rabbitmq_mqtt/test/util.erl
+++ b/deps/rabbitmq_mqtt/test/util.erl
@@ -4,58 +4,46 @@
-include_lib("rabbit_common/include/rabbit.hrl").
-include_lib("eunit/include/eunit.hrl").
--export([
- all_connection_pids/1,
- publish_qos1_timeout/4,
- sync_publish_result/3,
- get_global_counters/2,
- get_global_counters/3,
- get_global_counters/4,
- expect_publishes/3,
- connect/2,
- connect/3,
- connect/4,
- get_events/1,
- assert_event_type/2,
- assert_event_prop/2,
- await_exit/1,
- await_exit/2
-]).
+-export([all_connection_pids/1,
+ publish_qos1_timeout/4,
+ sync_publish_result/3,
+ get_global_counters/2,
+ get_global_counters/3,
+ get_global_counters/4,
+ expect_publishes/3,
+ connect/2,
+ connect/3,
+ connect/4,
+ get_events/1,
+ assert_event_type/2,
+ assert_event_prop/2,
+ await_exit/1,
+ await_exit/2
+ ]).
all_connection_pids(Config) ->
Nodes = rabbit_ct_broker_helpers:get_node_configs(Config, nodename),
Result = erpc:multicall(Nodes, rabbit_mqtt, local_connection_pids, [], 5000),
- lists:foldl(
- fun
- ({ok, Pids}, Acc) ->
- Pids ++ Acc;
- (_, Acc) ->
- Acc
- end,
- [],
- Result
- ).
+ lists:foldl(fun({ok, Pids}, Acc) ->
+ Pids ++ Acc;
+ (_, Acc) ->
+ Acc
+ end, [], Result).
publish_qos1_timeout(Client, Topic, Payload, Timeout) ->
Mref = erlang:monitor(process, Client),
- ok = emqtt:publish_async(
- Client,
- Topic,
- #{},
- Payload,
- [{qos, 1}],
- infinity,
- {fun ?MODULE:sync_publish_result/3, [self(), Mref]}
- ),
+ ok = emqtt:publish_async(Client, Topic, #{}, Payload, [{qos, 1}], infinity,
+ {fun ?MODULE:sync_publish_result/3, [self(), Mref]}),
receive
{Mref, Reply} ->
erlang:demonitor(Mref, [flush]),
Reply;
{'DOWN', Mref, process, Client, Reason} ->
ct:fail("client is down: ~tp", [Reason])
- after Timeout ->
- erlang:demonitor(Mref, [flush]),
- puback_timeout
+ after
+ Timeout ->
+ erlang:demonitor(Mref, [flush]),
+ puback_timeout
end.
sync_publish_result(Caller, Mref, Result) ->
@@ -63,27 +51,20 @@ sync_publish_result(Caller, Mref, Result) ->
expect_publishes(_, _, []) ->
ok;
-expect_publishes(Client, Topic, [Payload | Rest]) when
- is_pid(Client)
-->
+expect_publishes(Client, Topic, [Payload|Rest])
+ when is_pid(Client) ->
receive
- {publish, #{
- client_pid := Client,
- topic := Topic,
- payload := Payload
- }} ->
+ {publish, #{client_pid := Client,
+ topic := Topic,
+ payload := Payload}} ->
expect_publishes(Client, Topic, Rest);
- {publish, #{
- client_pid := Client,
- topic := Topic,
- payload := Other
- }} ->
- ct:fail(
- "Received unexpected PUBLISH payload. Expected: ~p Got: ~p",
- [Payload, Other]
- )
+ {publish, #{client_pid := Client,
+ topic := Topic,
+ payload := Other}} ->
+ ct:fail("Received unexpected PUBLISH payload. Expected: ~p Got: ~p",
+ [Payload, Other])
after 3000 ->
- {publish_not_received, Payload}
+ {publish_not_received, Payload}
end.
get_global_counters(Config, ProtoVer) ->
@@ -97,14 +78,11 @@ get_global_counters(Config, v3, Node, QType) ->
get_global_counters(Config, v4, Node, QType) ->
get_global_counters(Config, ?MQTT_PROTO_V4, Node, QType);
get_global_counters(Config, Proto, Node, QType) ->
- maps:get(
- [{protocol, Proto}] ++ QType,
- rabbit_ct_broker_helpers:rpc(Config, Node, rabbit_global_counters, overview, [])
- ).
+ maps:get([{protocol, Proto}] ++ QType,
+ rabbit_ct_broker_helpers:rpc(Config, Node, rabbit_global_counters, overview, [])).
get_events(Node) ->
- %% events are sent and processed asynchronously
- timer:sleep(300),
+ timer:sleep(300), %% events are sent and processed asynchronously
Result = gen_event:call({rabbit_event, Node}, event_recorder, take_state),
?assert(is_list(Result)),
Result.
@@ -114,26 +92,24 @@ assert_event_type(ExpectedType, #event{type = ActualType}) ->
assert_event_prop(ExpectedProp = {Key, _Value}, #event{props = Props}) ->
?assertEqual(ExpectedProp, lists:keyfind(Key, 1, Props));
-assert_event_prop(ExpectedProps, Event) when
- is_list(ExpectedProps)
-->
- lists:foreach(
- fun(P) ->
- assert_event_prop(P, Event)
- end,
- ExpectedProps
- ).
+assert_event_prop(ExpectedProps, Event)
+ when is_list(ExpectedProps) ->
+ lists:foreach(fun(P) ->
+ assert_event_prop(P, Event)
+ end, ExpectedProps).
await_exit(Pid) ->
receive
{'EXIT', Pid, _} -> ok
- after 20_000 -> ct:fail({missing_exit, Pid})
+ after
+ 20_000 -> ct:fail({missing_exit, Pid})
end.
await_exit(Pid, Reason) ->
receive
{'EXIT', Pid, Reason} -> ok
- after 20_000 -> ct:fail({missing_exit, Pid})
+ after
+ 20_000 -> ct:fail({missing_exit, Pid})
end.
connect(ClientId, Config) ->
@@ -144,27 +120,21 @@ connect(ClientId, Config, AdditionalOpts) ->
connect(ClientId, Config, Node, AdditionalOpts) ->
{Port, WsOpts, Connect} =
- case rabbit_ct_helpers:get_config(Config, websocket, false) of
- false ->
- {
- rabbit_ct_broker_helpers:get_node_config(Config, Node, tcp_port_mqtt),
- [],
- fun emqtt:connect/1
- };
- true ->
- {
- rabbit_ct_broker_helpers:get_node_config(Config, Node, tcp_port_web_mqtt),
- [{ws_path, "/ws"}],
- fun emqtt:ws_connect/1
- }
- end,
- Options =
- [
- {host, "localhost"},
- {port, Port},
- {proto_ver, v4},
- {clientid, rabbit_data_coercion:to_binary(ClientId)}
- ] ++ WsOpts ++ AdditionalOpts,
+ case rabbit_ct_helpers:get_config(Config, websocket, false) of
+ false ->
+ {rabbit_ct_broker_helpers:get_node_config(Config, Node, tcp_port_mqtt),
+ [],
+ fun emqtt:connect/1};
+ true ->
+ {rabbit_ct_broker_helpers:get_node_config(Config, Node, tcp_port_web_mqtt),
+ [{ws_path, "/ws"}],
+ fun emqtt:ws_connect/1}
+ end,
+ Options = [{host, "localhost"},
+ {port, Port},
+ {proto_ver, v4},
+ {clientid, rabbit_data_coercion:to_binary(ClientId)}
+ ] ++ WsOpts ++ AdditionalOpts,
{ok, C} = emqtt:start_link(Options),
{ok, _Properties} = Connect(C),
C.
diff --git a/deps/rabbitmq_mqtt/test/util_SUITE.erl b/deps/rabbitmq_mqtt/test/util_SUITE.erl
index 66b6f15c14..3d058500ab 100644
--- a/deps/rabbitmq_mqtt/test/util_SUITE.erl
+++ b/deps/rabbitmq_mqtt/test/util_SUITE.erl
@@ -12,18 +12,19 @@
all() ->
[
- {group, tests}
+ {group, tests}
].
groups() ->
[
- {tests, [parallel], [
- coerce_exchange,
- coerce_vhost,
- coerce_default_user,
- coerce_default_pass,
- mqtt_amqp_topic_translation
- ]}
+ {tests, [parallel], [
+ coerce_exchange,
+ coerce_vhost,
+ coerce_default_user,
+ coerce_default_pass,
+ mqtt_amqp_topic_translation
+ ]
+ }
].
suite() ->
diff --git a/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_app.erl b/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_app.erl
index 7dafc013f2..7070128205 100644
--- a/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_app.erl
+++ b/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_app.erl
@@ -49,7 +49,7 @@ init([]) -> {ok, {{one_for_one, 1, 5}, []}}.
-spec list_connections() -> [pid()].
list_connections() ->
PlainPids = connection_pids_of_protocol(?TCP_PROTOCOL),
- TLSPids = connection_pids_of_protocol(?TLS_PROTOCOL),
+ TLSPids = connection_pids_of_protocol(?TLS_PROTOCOL),
PlainPids ++ TLSPids.
%%
@@ -58,8 +58,7 @@ list_connections() ->
connection_pids_of_protocol(Protocol) ->
case rabbit_networking:ranch_ref_of_protocol(Protocol) of
- undefined ->
- [];
+ undefined -> [];
AcceptorRef ->
lists:map(fun cowboy_ws_connection_pid/1, ranch:procs(AcceptorRef, connections))
end.
@@ -71,38 +70,36 @@ cowboy_ws_connection_pid(RanchConnPid) ->
Pid.
mqtt_init() ->
- CowboyOpts0 = maps:from_list(get_env(cowboy_opts, [])),
- CowboyWsOpts = maps:from_list(get_env(cowboy_ws_opts, [])),
- Routes = cowboy_router:compile([
- {'_', [
- {get_env(ws_path, "/ws"), rabbit_web_mqtt_handler, [{ws_opts, CowboyWsOpts}]}
- ]}
- ]),
- CowboyOpts = CowboyOpts0#{
- env => #{dispatch => Routes},
- proxy_header => get_env(proxy_protocol, false),
- stream_handlers => [rabbit_web_mqtt_stream_handler, cowboy_stream_h]
- },
- case get_env(tcp_config, []) of
- [] -> ok;
- TCPConf0 -> start_tcp_listener(TCPConf0, CowboyOpts)
- end,
- case get_env(ssl_config, []) of
- [] -> ok;
- TLSConf0 -> start_tls_listener(TLSConf0, CowboyOpts)
- end,
- ok.
+ CowboyOpts0 = maps:from_list(get_env(cowboy_opts, [])),
+ CowboyWsOpts = maps:from_list(get_env(cowboy_ws_opts, [])),
+ Routes = cowboy_router:compile([{'_', [
+ {get_env(ws_path, "/ws"), rabbit_web_mqtt_handler, [{ws_opts, CowboyWsOpts}]}
+ ]}]),
+ CowboyOpts = CowboyOpts0#{
+ env => #{dispatch => Routes},
+ proxy_header => get_env(proxy_protocol, false),
+ stream_handlers => [rabbit_web_mqtt_stream_handler, cowboy_stream_h]
+ },
+ case get_env(tcp_config, []) of
+ [] -> ok;
+ TCPConf0 -> start_tcp_listener(TCPConf0, CowboyOpts)
+ end,
+ case get_env(ssl_config, []) of
+ [] -> ok;
+ TLSConf0 -> start_tls_listener(TLSConf0, CowboyOpts)
+ end,
+ ok.
start_tcp_listener(TCPConf0, CowboyOpts) ->
{TCPConf, IpStr, Port} = get_tcp_conf(TCPConf0),
RanchRef = rabbit_networking:ranch_ref(TCPConf),
RanchTransportOpts =
- #{
- socket_opts => TCPConf,
- max_connections => get_max_connections(),
- num_acceptors => get_env(num_tcp_acceptors, 10),
- num_conns_sups => get_env(num_conns_sup, 1)
- },
+ #{
+ socket_opts => TCPConf,
+ max_connections => get_max_connections(),
+ num_acceptors => get_env(num_tcp_acceptors, 10),
+ num_conns_sups => get_env(num_conns_sup, 1)
+ },
case cowboy:start_clear(RanchRef, RanchTransportOpts, CowboyOpts) of
{ok, _} ->
ok;
@@ -110,28 +107,25 @@ start_tcp_listener(TCPConf0, CowboyOpts) ->
ok;
{error, ErrTCP} ->
rabbit_log:error(
- "Failed to start a WebSocket (HTTP) listener. Error: ~p, listener settings: ~p",
- [ErrTCP, TCPConf]
- ),
+ "Failed to start a WebSocket (HTTP) listener. Error: ~p, listener settings: ~p",
+ [ErrTCP, TCPConf]),
throw(ErrTCP)
end,
listener_started(?TCP_PROTOCOL, TCPConf),
- rabbit_log:info(
- "rabbit_web_mqtt: listening for HTTP connections on ~s:~w",
- [IpStr, Port]
- ).
+ rabbit_log:info("rabbit_web_mqtt: listening for HTTP connections on ~s:~w",
+ [IpStr, Port]).
start_tls_listener(TLSConf0, CowboyOpts) ->
_ = rabbit_networking:ensure_ssl(),
{TLSConf, TLSIpStr, TLSPort} = get_tls_conf(TLSConf0),
RanchRef = rabbit_networking:ranch_ref(TLSConf),
RanchTransportOpts =
- #{
- socket_opts => TLSConf,
- max_connections => get_max_connections(),
- num_acceptors => get_env(num_ssl_acceptors, 10),
- num_conns_sups => get_env(num_conns_sup, 1)
- },
+ #{
+ socket_opts => TLSConf,
+ max_connections => get_max_connections(),
+ num_acceptors => get_env(num_ssl_acceptors, 10),
+ num_conns_sups => get_env(num_conns_sup, 1)
+ },
case cowboy:start_tls(RanchRef, RanchTransportOpts, CowboyOpts) of
{ok, _} ->
ok;
@@ -139,45 +133,34 @@ start_tls_listener(TLSConf0, CowboyOpts) ->
ok;
{error, ErrTLS} ->
rabbit_log:error(
- "Failed to start a TLS WebSocket (HTTPS) listener. Error: ~p, listener settings: ~p",
- [ErrTLS, TLSConf]
- ),
+ "Failed to start a TLS WebSocket (HTTPS) listener. Error: ~p, listener settings: ~p",
+ [ErrTLS, TLSConf]),
throw(ErrTLS)
end,
listener_started(?TLS_PROTOCOL, TLSConf),
- rabbit_log:info(
- "rabbit_web_mqtt: listening for HTTPS connections on ~s:~w",
- [TLSIpStr, TLSPort]
- ).
+ rabbit_log:info("rabbit_web_mqtt: listening for HTTPS connections on ~s:~w",
+ [TLSIpStr, TLSPort]).
listener_started(Protocol, Listener) ->
Port = rabbit_misc:pget(port, Listener),
- [
- rabbit_networking:tcp_listener_started(
- Protocol,
- Listener,
- IPAddress,
- Port
- )
- || {IPAddress, _Port, _Family} <-
- rabbit_networking:tcp_listener_addresses(Port)
- ],
+ [rabbit_networking:tcp_listener_started(Protocol, Listener,
+ IPAddress, Port)
+ || {IPAddress, _Port, _Family}
+ <- rabbit_networking:tcp_listener_addresses(Port)],
ok.
get_tcp_conf(TCPConf0) ->
- TCPConf1 =
- case proplists:get_value(port, TCPConf0) of
- undefined -> [{port, 15675} | TCPConf0];
- _ -> TCPConf0
- end,
+ TCPConf1 = case proplists:get_value(port, TCPConf0) of
+ undefined -> [{port, 15675}|TCPConf0];
+ _ -> TCPConf0
+ end,
get_ip_port(TCPConf1).
get_tls_conf(TLSConf0) ->
- TLSConf1 =
- case proplists:get_value(port, TLSConf0) of
- undefined -> [{port, 15675} | proplists:delete(port, TLSConf0)];
- _ -> TLSConf0
- end,
+ TLSConf1 = case proplists:get_value(port, TLSConf0) of
+ undefined -> [{port, 15675}|proplists:delete(port, TLSConf0)];
+ _ -> TLSConf0
+ end,
get_ip_port(TLSConf1).
get_ip_port(Conf0) ->
@@ -194,7 +177,7 @@ normalize_ip(Ip) ->
Ip.
get_max_connections() ->
- get_env(max_connections, infinity).
+ get_env(max_connections, infinity).
get_env(Key, Default) ->
rabbit_misc:get_env(rabbitmq_web_mqtt, Key, Default).
diff --git a/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_handler.erl b/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_handler.erl
index 2f017af696..72f52b3977 100644
--- a/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_handler.erl
+++ b/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_handler.erl
@@ -24,25 +24,23 @@
-export([conserve_resources/3]).
%% cowboy_sub_protocol
--export([
- upgrade/4,
- upgrade/5,
- takeover/7
-]).
+-export([upgrade/4,
+ upgrade/5,
+ takeover/7]).
-type option(T) :: undefined | T.
-record(state, {
- socket :: {rabbit_proxy_socket, any(), any()} | rabbit_net:socket(),
- parse_state = rabbit_mqtt_packet:initial_state() :: rabbit_mqtt_packet:state(),
- proc_state :: undefined | rabbit_mqtt_processor:state(),
- connection_state = running :: running | blocked,
- conserve = false :: boolean(),
- stats_timer :: option(rabbit_event:state()),
- keepalive = rabbit_mqtt_keepalive:init() :: rabbit_mqtt_keepalive:state(),
- conn_name :: option(binary()),
- received_connect_packet = false :: boolean()
-}).
+ socket :: {rabbit_proxy_socket, any(), any()} | rabbit_net:socket(),
+ parse_state = rabbit_mqtt_packet:initial_state() :: rabbit_mqtt_packet:state(),
+ proc_state :: undefined | rabbit_mqtt_processor:state(),
+ connection_state = running :: running | blocked,
+ conserve = false :: boolean(),
+ stats_timer :: option(rabbit_event:state()),
+ keepalive = rabbit_mqtt_keepalive:init() :: rabbit_mqtt_keepalive:state(),
+ conn_name :: option(binary()),
+ received_connect_packet = false :: boolean()
+ }).
-type state() :: #state{}.
@@ -60,22 +58,14 @@ upgrade(Req, Env, Handler, HandlerState, Opts) ->
cowboy_websocket:upgrade(Req, Env, Handler, HandlerState, Opts).
takeover(Parent, Ref, Socket, Transport, Opts, Buffer, {Handler, {HandlerState, PeerAddr}}) ->
- Sock =
- case HandlerState#state.socket of
- undefined ->
- Socket;
- ProxyInfo ->
- {rabbit_proxy_socket, Socket, ProxyInfo}
- end,
- cowboy_websocket:takeover(
- Parent,
- Ref,
- Socket,
- Transport,
- Opts,
- Buffer,
- {Handler, {HandlerState#state{socket = Sock}, PeerAddr}}
- ).
+ Sock = case HandlerState#state.socket of
+ undefined ->
+ Socket;
+ ProxyInfo ->
+ {rabbit_proxy_socket, Socket, ProxyInfo}
+ end,
+ cowboy_websocket:takeover(Parent, Ref, Socket, Transport, Opts, Buffer,
+ {Handler, {HandlerState#state{socket = Sock}, PeerAddr}}).
%% cowboy_websocket
init(Req, Opts) ->
@@ -85,20 +75,22 @@ init(Req, Opts) ->
Protocol ->
{PeerAddr, _PeerPort} = maps:get(peer, Req),
WsOpts0 = proplists:get_value(ws_opts, Opts, #{}),
- WsOpts = maps:merge(#{compress => true}, WsOpts0),
+ WsOpts = maps:merge(#{compress => true}, WsOpts0),
case lists:member(<<"mqtt">>, Protocol) of
false ->
no_supported_sub_protocol(Protocol, Req);
true ->
{?MODULE,
- cowboy_req:set_resp_header(<<"sec-websocket-protocol">>, <<"mqtt">>, Req),
- {#state{socket = maps:get(proxy_header, Req, undefined)}, PeerAddr}, WsOpts}
+ cowboy_req:set_resp_header(<<"sec-websocket-protocol">>, <<"mqtt">>, Req),
+ {#state{socket = maps:get(proxy_header, Req, undefined)},
+ PeerAddr},
+ WsOpts}
end
end.
-spec websocket_init({state(), PeerAddr :: binary()}) ->
- {cowboy_websocket:commands(), state()}
- | {cowboy_websocket:commands(), state(), hibernate}.
+ {cowboy_websocket:commands(), state()} |
+ {cowboy_websocket:commands(), state(), hibernate}.
websocket_init({State0 = #state{socket = Sock}, PeerAddr}) ->
logger:set_process_metadata(#{domain => ?RMQLOG_DOMAIN_CONN ++ [web_mqtt]}),
ok = file_handle_cache:obtain(),
@@ -108,15 +100,12 @@ websocket_init({State0 = #state{socket = Sock}, PeerAddr}) ->
?LOG_INFO("Accepting Web MQTT connection ~s", [ConnName]),
_ = rabbit_alarm:register(self(), {?MODULE, conserve_resources, []}),
PState = rabbit_mqtt_processor:initial_state(
- rabbit_net:unwrap_socket(Sock),
- ConnName,
- fun send_reply/2,
- PeerAddr
- ),
- State1 = State0#state{
- conn_name = ConnName,
- proc_state = PState
- },
+ rabbit_net:unwrap_socket(Sock),
+ ConnName,
+ fun send_reply/2,
+ PeerAddr),
+ State1 = State0#state{conn_name = ConnName,
+ proc_state = PState},
State = rabbit_event:init_stats_timer(State1, #state.stats_timer),
process_flag(trap_exit, true),
{[], State, hibernate};
@@ -124,28 +113,24 @@ websocket_init({State0 = #state{socket = Sock}, PeerAddr}) ->
{[{shutdown_reason, Reason}], State0}
end.
--spec conserve_resources(
- pid(),
- rabbit_alarm:resource_alarm_source(),
- rabbit_alarm:resource_alert()
-) -> ok.
+-spec conserve_resources(pid(),
+ rabbit_alarm:resource_alarm_source(),
+ rabbit_alarm:resource_alert()) -> ok.
conserve_resources(Pid, _, {_, Conserve, _}) ->
Pid ! {conserve_resources, Conserve},
ok.
-spec websocket_handle(ping | pong | {text | binary | ping | pong, binary()}, State) ->
- {cowboy_websocket:commands(), State}
- | {cowboy_websocket:commands(), State, hibernate}.
+ {cowboy_websocket:commands(), State} |
+ {cowboy_websocket:commands(), State, hibernate}.
websocket_handle({binary, Data}, State) ->
handle_data(Data, State);
%% Silently ignore ping and pong frames as Cowboy will automatically reply to ping frames.
-websocket_handle({Ping, _}, State) when
- Ping =:= ping orelse Ping =:= pong
-->
+websocket_handle({Ping, _}, State)
+ when Ping =:= ping orelse Ping =:= pong ->
{[], State, hibernate};
-websocket_handle(Ping, State) when
- Ping =:= ping orelse Ping =:= pong
-->
+websocket_handle(Ping, State)
+ when Ping =:= ping orelse Ping =:= pong ->
{[], State, hibernate};
%% Log and close connection when receiving any other unexpected frames.
websocket_handle(Frame, State) ->
@@ -153,8 +138,8 @@ websocket_handle(Frame, State) ->
stop(State, ?CLOSE_UNACCEPTABLE_DATA_TYPE, <<"unexpected WebSocket frame">>).
-spec websocket_info(any(), State) ->
- {cowboy_websocket:commands(), State}
- | {cowboy_websocket:commands(), State, hibernate}.
+ {cowboy_websocket:commands(), State} |
+ {cowboy_websocket:commands(), State, hibernate}.
websocket_info({conserve_resources, Conserve}, State) ->
handle_credits(State#state{conserve = Conserve});
websocket_info({bump_credit, Msg}, State) ->
@@ -164,66 +149,39 @@ websocket_info({reply, Data}, State) ->
{[{binary, Data}], State, hibernate};
websocket_info({'EXIT', _, _}, State) ->
stop(State);
-websocket_info(
- {'$gen_cast', QueueEvent = {queue_event, _, _}},
- State = #state{proc_state = PState0}
-) ->
+websocket_info({'$gen_cast', QueueEvent = {queue_event, _, _}},
+ State = #state{proc_state = PState0}) ->
case rabbit_mqtt_processor:handle_queue_event(QueueEvent, PState0) of
{ok, PState} ->
handle_credits(State#state{proc_state = PState});
{error, Reason, PState} ->
- ?LOG_ERROR(
- "Web MQTT connection ~p failed to handle queue event: ~p",
- [State#state.conn_name, Reason]
- ),
+ ?LOG_ERROR("Web MQTT connection ~p failed to handle queue event: ~p",
+ [State#state.conn_name, Reason]),
stop(State#state{proc_state = PState})
end;
-websocket_info(
- {'$gen_cast', duplicate_id},
- State = #state{
- proc_state = ProcState,
- conn_name = ConnName
- }
-) ->
- ?LOG_WARNING(
- "Web MQTT disconnecting a client with duplicate ID '~s' (~p)",
- [rabbit_mqtt_processor:info(client_id, ProcState), ConnName]
- ),
+websocket_info({'$gen_cast', duplicate_id}, State = #state{ proc_state = ProcState,
+ conn_name = ConnName }) ->
+ ?LOG_WARNING("Web MQTT disconnecting a client with duplicate ID '~s' (~p)",
+ [rabbit_mqtt_processor:info(client_id, ProcState), ConnName]),
stop(State);
-websocket_info(
- {'$gen_cast', {close_connection, Reason}},
- State = #state{
- proc_state = ProcState,
- conn_name = ConnName
- }
-) ->
- ?LOG_WARNING(
- "Web MQTT disconnecting client with ID '~s' (~p), reason: ~s",
- [rabbit_mqtt_processor:info(client_id, ProcState), ConnName, Reason]
- ),
+websocket_info({'$gen_cast', {close_connection, Reason}}, State = #state{ proc_state = ProcState,
+ conn_name = ConnName }) ->
+ ?LOG_WARNING("Web MQTT disconnecting client with ID '~s' (~p), reason: ~s",
+ [rabbit_mqtt_processor:info(client_id, ProcState), ConnName, Reason]),
stop(State);
websocket_info({'$gen_cast', {force_event_refresh, Ref}}, State0) ->
Infos = infos(?CREATION_EVENT_KEYS, State0),
rabbit_event:notify(connection_created, Infos, Ref),
State = rabbit_event:init_stats_timer(State0, #state.stats_timer),
{[], State, hibernate};
-websocket_info(
- {'$gen_cast', refresh_config},
- State0 = #state{
- proc_state = PState0,
- conn_name = ConnName
- }
-) ->
+websocket_info({'$gen_cast', refresh_config},
+ State0 = #state{proc_state = PState0,
+ conn_name = ConnName}) ->
PState = rabbit_mqtt_processor:update_trace(ConnName, PState0),
State = State0#state{proc_state = PState},
{[], State, hibernate};
-websocket_info(
- {keepalive, Req},
- State = #state{
- keepalive = KState0,
- conn_name = ConnName
- }
-) ->
+websocket_info({keepalive, Req}, State = #state{keepalive = KState0,
+ conn_name = ConnName}) ->
case rabbit_mqtt_keepalive:handle(Req, KState0) of
{ok, KState} ->
{[], State#state{keepalive = KState}, hibernate};
@@ -231,24 +189,18 @@ websocket_info(
?LOG_ERROR("keepalive timeout in Web MQTT connection ~p", [ConnName]),
stop(State, ?CLOSE_NORMAL, <<"MQTT keepalive timeout">>);
{error, Reason} ->
- ?LOG_ERROR(
- "keepalive error in Web MQTT connection ~p: ~p",
- [ConnName, Reason]
- ),
+ ?LOG_ERROR("keepalive error in Web MQTT connection ~p: ~p",
+ [ConnName, Reason]),
stop(State)
end;
websocket_info(emit_stats, State) ->
{[], emit_stats(State), hibernate};
-websocket_info(
- {ra_event, _From, Evt},
- #state{proc_state = PState0} = State
-) ->
+websocket_info({ra_event, _From, Evt},
+ #state{proc_state = PState0} = State) ->
PState = rabbit_mqtt_processor:handle_ra_event(Evt, PState0),
{[], State#state{proc_state = PState}, hibernate};
-websocket_info(
- {{'DOWN', _QName}, _MRef, process, _Pid, _Reason} = Evt,
- State = #state{proc_state = PState0}
-) ->
+websocket_info({{'DOWN', _QName}, _MRef, process, _Pid, _Reason} = Evt,
+ State = #state{proc_state = PState0}) ->
case rabbit_mqtt_processor:handle_down(Evt, PState0) of
{ok, PState} ->
handle_credits(State#state{proc_state = PState});
@@ -275,16 +227,10 @@ terminate(_Reason, _Req, #state{proc_state = undefined}) ->
ok;
terminate(Reason, Request, #state{} = State) ->
terminate(Reason, Request, {true, State});
-terminate(
- _Reason,
- _Request,
- {SendWill,
- #state{
- conn_name = ConnName,
- proc_state = PState,
- keepalive = KState
- } = State}
-) ->
+terminate(_Reason, _Request,
+ {SendWill, #state{conn_name = ConnName,
+ proc_state = PState,
+ keepalive = KState} = State}) ->
?LOG_INFO("Web MQTT closing connection ~ts", [ConnName]),
maybe_emit_stats(State),
_ = rabbit_mqtt_keepalive:cancel_timer(KState),
@@ -306,49 +252,29 @@ handle_data(Data, State0 = #state{}) ->
Other
end.
-handle_data1(
- <<>>,
- State0 = #state{
- received_connect_packet = false,
- proc_state = PState,
- conn_name = ConnName
- }
-) ->
- ?LOG_INFO(
- "Accepted web MQTT connection ~p (~s, client ID: ~s)",
- [self(), ConnName, rabbit_mqtt_processor:info(client_id, PState)]
- ),
+handle_data1(<<>>, State0 = #state{received_connect_packet = false,
+ proc_state = PState,
+ conn_name = ConnName}) ->
+ ?LOG_INFO("Accepted web MQTT connection ~p (~s, client ID: ~s)",
+ [self(), ConnName, rabbit_mqtt_processor:info(client_id, PState)]),
State = State0#state{received_connect_packet = true},
{ok, ensure_stats_timer(control_throttle(State)), hibernate};
handle_data1(<<>>, State) ->
{ok, ensure_stats_timer(control_throttle(State)), hibernate};
-handle_data1(
- Data,
- State = #state{
- parse_state = ParseState,
- proc_state = ProcState,
- conn_name = ConnName
- }
-) ->
+handle_data1(Data, State = #state{ parse_state = ParseState,
+ proc_state = ProcState,
+ conn_name = ConnName }) ->
case parse(Data, ParseState) of
{more, ParseState1} ->
- {ok,
- ensure_stats_timer(
- control_throttle(
- State#state{parse_state = ParseState1}
- )
- ),
- hibernate};
+ {ok, ensure_stats_timer(control_throttle(
+ State #state{ parse_state = ParseState1 })), hibernate};
{ok, Packet, Rest} ->
case rabbit_mqtt_processor:process_packet(Packet, ProcState) of
{ok, ProcState1} ->
handle_data1(
- Rest,
- State#state{
- parse_state = rabbit_mqtt_packet:initial_state(),
- proc_state = ProcState1
- }
- );
+ Rest,
+ State#state{parse_state = rabbit_mqtt_packet:initial_state(),
+ proc_state = ProcState1});
{error, Reason, _} ->
stop_mqtt_protocol_error(State, Reason, ConnName);
{stop, disconnect, ProcState1} ->
@@ -363,11 +289,9 @@ parse(Data, ParseState) ->
rabbit_mqtt_packet:parse(Data, ParseState)
catch
_:Reason:Stacktrace ->
- ?LOG_ERROR(
- "Web MQTT cannot parse a packet, reason: ~tp, stacktrace: ~tp, "
- "payload (first 100 bytes): ~tp",
- [Reason, Stacktrace, rabbit_mqtt_util:truncate_binary(Data, 100)]
- ),
+ ?LOG_ERROR("Web MQTT cannot parse a packet, reason: ~tp, stacktrace: ~tp, "
+ "payload (first 100 bytes): ~tp",
+ [Reason, Stacktrace, rabbit_mqtt_util:truncate_binary(Data, 100)]),
{error, cannot_parse}
end.
@@ -384,34 +308,26 @@ stop(State, CloseCode, Error0) ->
handle_credits(State0) ->
State = #state{connection_state = CS} = control_throttle(State0),
- Active =
- case CS of
- running -> true;
- blocked -> false
- end,
+ Active = case CS of
+ running -> true;
+ blocked -> false
+ end,
{[{active, Active}], State, hibernate}.
-control_throttle(
- State = #state{
- connection_state = ConnState,
- conserve = Conserve,
- received_connect_packet = Connected,
- proc_state = PState,
- keepalive = KState
- }
-) ->
+control_throttle(State = #state{connection_state = ConnState,
+ conserve = Conserve,
+ received_connect_packet = Connected,
+ proc_state = PState,
+ keepalive = KState
+ }) ->
Throttle = rabbit_mqtt_processor:throttle(Conserve, Connected, PState),
case {ConnState, Throttle} of
{running, true} ->
- State#state{
- connection_state = blocked,
- keepalive = rabbit_mqtt_keepalive:cancel_timer(KState)
- };
- {blocked, false} ->
- State#state{
- connection_state = running,
- keepalive = rabbit_mqtt_keepalive:start_timer(KState)
- };
+ State#state{connection_state = blocked,
+ keepalive = rabbit_mqtt_keepalive:cancel_timer(KState)};
+ {blocked,false} ->
+ State#state{connection_state = running,
+ keepalive = rabbit_mqtt_keepalive:start_timer(KState)};
{_, _} ->
State
end.
@@ -425,23 +341,18 @@ ensure_stats_timer(State) ->
maybe_emit_stats(#state{stats_timer = undefined}) ->
ok;
maybe_emit_stats(State) ->
- rabbit_event:if_enabled(
- State,
- #state.stats_timer,
- fun() -> emit_stats(State) end
- ).
+ rabbit_event:if_enabled(State, #state.stats_timer,
+ fun() -> emit_stats(State) end).
-emit_stats(State = #state{received_connect_packet = false}) ->
+emit_stats(State=#state{received_connect_packet = false}) ->
%% Avoid emitting stats on terminate when the connection has not yet been
%% established, as this causes orphan entries on the stats database
rabbit_event:reset_stats_timer(State, #state.stats_timer);
emit_stats(State) ->
- [
- {_, Pid},
- {_, RecvOct},
- {_, SendOct},
- {_, Reductions}
- ] = infos(?SIMPLE_METRICS, State),
+ [{_, Pid},
+ {_, RecvOct},
+ {_, SendOct},
+ {_, Reductions}] = infos(?SIMPLE_METRICS, State),
Infos = infos(?OTHER_METRICS, State),
rabbit_core_metrics:connection_stats(Pid, Infos),
rabbit_core_metrics:connection_stats(Pid, RecvOct, SendOct, Reductions),
@@ -453,13 +364,12 @@ infos(Items, State) ->
i(pid, _) ->
self();
-i(SockStat, #state{socket = Sock}) when
- SockStat =:= recv_oct;
- SockStat =:= recv_cnt;
- SockStat =:= send_oct;
- SockStat =:= send_cnt;
- SockStat =:= send_pend
-->
+i(SockStat, #state{socket = Sock})
+ when SockStat =:= recv_oct;
+ SockStat =:= recv_cnt;
+ SockStat =:= send_oct;
+ SockStat =:= send_cnt;
+ SockStat =:= send_pend ->
case rabbit_net:getstat(Sock, [SockStat]) of
{ok, [{_, N}]} when is_number(N) ->
N;
@@ -473,23 +383,22 @@ i(garbage_collection, _) ->
rabbit_misc:get_gc_info(self());
i(protocol, #state{proc_state = PState}) ->
{?PROTO_FAMILY, rabbit_mqtt_processor:proto_version_tuple(PState)};
-i(SSL, #state{socket = Sock}) when
- SSL =:= ssl;
- SSL =:= ssl_protocol;
- SSL =:= ssl_key_exchange;
- SSL =:= ssl_cipher;
- SSL =:= ssl_hash
-->
- rabbit_ssl:info(SSL, {rabbit_net:unwrap_socket(Sock), rabbit_net:maybe_get_proxy_socket(Sock)});
+i(SSL, #state{socket = Sock})
+ when SSL =:= ssl;
+ SSL =:= ssl_protocol;
+ SSL =:= ssl_key_exchange;
+ SSL =:= ssl_cipher;
+ SSL =:= ssl_hash ->
+ rabbit_ssl:info(SSL, {rabbit_net:unwrap_socket(Sock),
+ rabbit_net:maybe_get_proxy_socket(Sock)});
i(name, S) ->
i(conn_name, S);
i(conn_name, #state{conn_name = Val}) ->
Val;
-i(Cert, #state{socket = Sock}) when
- Cert =:= peer_cert_issuer;
- Cert =:= peer_cert_subject;
- Cert =:= peer_cert_validity
-->
+i(Cert, #state{socket = Sock})
+ when Cert =:= peer_cert_issuer;
+ Cert =:= peer_cert_subject;
+ Cert =:= peer_cert_validity ->
rabbit_ssl:cert_info(Cert, rabbit_net:unwrap_socket(Sock));
i(state, S) ->
i(connection_state, S);
diff --git a/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_stream_handler.erl b/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_stream_handler.erl
index b407623da6..68d6ad2f29 100644
--- a/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_stream_handler.erl
+++ b/deps/rabbitmq_web_mqtt/src/rabbit_web_mqtt_stream_handler.erl
@@ -14,6 +14,7 @@
-export([terminate/3]).
-export([early_error/5]).
+
-record(state, {next}).
init(StreamID, Req, Opts) ->
diff --git a/deps/rabbitmq_web_mqtt/test/config_schema_SUITE.erl b/deps/rabbitmq_web_mqtt/test/config_schema_SUITE.erl
index 2106d0a4ed..ec256f4421 100644
--- a/deps/rabbitmq_web_mqtt/test/config_schema_SUITE.erl
+++ b/deps/rabbitmq_web_mqtt/test/config_schema_SUITE.erl
@@ -23,6 +23,7 @@ init_per_suite(Config) ->
Config1 = rabbit_ct_helpers:run_setup_steps(Config),
rabbit_ct_config_schema:init_schemas(rabbitmq_web_mqtt, Config1).
+
end_per_suite(Config) ->
rabbit_ct_helpers:run_teardown_steps(Config).
@@ -30,19 +31,15 @@ init_per_testcase(Testcase, Config) ->
rabbit_ct_helpers:testcase_started(Config, Testcase),
Config1 = rabbit_ct_helpers:set_config(Config, [
{rmq_nodename_suffix, Testcase}
- ]),
- rabbit_ct_helpers:run_steps(
- Config1,
- rabbit_ct_broker_helpers:setup_steps() ++
- rabbit_ct_client_helpers:setup_steps()
- ).
+ ]),
+ rabbit_ct_helpers:run_steps(Config1,
+ rabbit_ct_broker_helpers:setup_steps() ++
+ rabbit_ct_client_helpers:setup_steps()).
end_per_testcase(Testcase, Config) ->
- Config1 = rabbit_ct_helpers:run_steps(
- Config,
- rabbit_ct_client_helpers:teardown_steps() ++
- rabbit_ct_broker_helpers:teardown_steps()
- ),
+ Config1 = rabbit_ct_helpers:run_steps(Config,
+ rabbit_ct_client_helpers:teardown_steps() ++
+ rabbit_ct_broker_helpers:teardown_steps()),
rabbit_ct_helpers:testcase_finished(Config1, Testcase).
%% -------------------------------------------------------------------
@@ -50,13 +47,9 @@ end_per_testcase(Testcase, Config) ->
%% -------------------------------------------------------------------
run_snippets(Config) ->
- ok = rabbit_ct_broker_helpers:rpc(
- Config,
- 0,
- ?MODULE,
- run_snippets1,
- [Config]
- ).
+ ok = rabbit_ct_broker_helpers:rpc(Config, 0,
+ ?MODULE, run_snippets1, [Config]).
run_snippets1(Config) ->
rabbit_ct_config_schema:run_snippets(Config).
+
diff --git a/deps/rabbitmq_web_mqtt/test/proxy_protocol_SUITE.erl b/deps/rabbitmq_web_mqtt/test/proxy_protocol_SUITE.erl
index c6512cd6b6..95cd3e5c44 100644
--- a/deps/rabbitmq_web_mqtt/test/proxy_protocol_SUITE.erl
+++ b/deps/rabbitmq_web_mqtt/test/proxy_protocol_SUITE.erl
@@ -7,6 +7,7 @@
-module(proxy_protocol_SUITE).
+
-compile([export_all, nowarn_export_all]).
-include_lib("common_test/include/ct.hrl").
@@ -14,24 +15,20 @@
suite() ->
[
- %% If a test hangs, no need to wait for 30 minutes.
- {timetrap, {minutes, 2}}
+ %% If a test hangs, no need to wait for 30 minutes.
+ {timetrap, {minutes, 2}}
].
all() ->
- [
- {group, http_tests},
- {group, https_tests}
- ].
+ [{group, http_tests},
+ {group, https_tests}].
groups() ->
Tests = [
proxy_protocol
],
- [
- {https_tests, [], Tests},
- {http_tests, [], Tests}
- ].
+ [{https_tests, [], Tests},
+ {http_tests, [], Tests}].
init_per_suite(Config) ->
rabbit_ct_helpers:log_environment(),
@@ -41,29 +38,22 @@ end_per_suite(Config) ->
Config.
init_per_group(Group, Config) ->
- Protocol =
- case Group of
- http_tests -> "ws";
- https_tests -> "wss"
- end,
- Config1 = rabbit_ct_helpers:set_config(
- Config,
- [
- {rmq_nodename_suffix, ?MODULE},
- {protocol, Protocol},
- {rabbitmq_ct_tls_verify, verify_none},
- {rabbitmq_ct_tls_fail_if_no_peer_cert, false}
- ]
- ),
+ Protocol = case Group of
+ http_tests -> "ws";
+ https_tests -> "wss"
+ end,
+ Config1 = rabbit_ct_helpers:set_config(Config,
+ [{rmq_nodename_suffix, ?MODULE},
+ {protocol, Protocol},
+ {rabbitmq_ct_tls_verify, verify_none},
+ {rabbitmq_ct_tls_fail_if_no_peer_cert, false}]),
rabbit_ct_helpers:run_setup_steps(
Config1,
- rabbit_ct_broker_helpers:setup_steps() ++
- [
- fun configure_proxy_protocol/1,
- fun configure_ssl/1
- ]
- ).
+ rabbit_ct_broker_helpers:setup_steps() ++ [
+ fun configure_proxy_protocol/1,
+ fun configure_ssl/1
+ ]).
configure_proxy_protocol(Config) ->
rabbit_ws_test_util:update_app_env(Config, proxy_protocol, true),
@@ -74,16 +64,12 @@ configure_ssl(Config) ->
RabbitAppConfig = proplists:get_value(rabbit, ErlangConfig, []),
RabbitSslConfig = proplists:get_value(ssl_options, RabbitAppConfig, []),
Port = rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_web_mqtt_tls),
- rabbit_ws_test_util:update_app_env(Config, ssl_config, [
- {port, Port} | lists:keydelete(port, 1, RabbitSslConfig)
- ]),
+ rabbit_ws_test_util:update_app_env(Config, ssl_config, [{port, Port} | lists:keydelete(port, 1, RabbitSslConfig)]),
Config.
end_per_group(_Group, Config) ->
- rabbit_ct_helpers:run_teardown_steps(
- Config,
- rabbit_ct_broker_helpers:teardown_steps()
- ).
+ rabbit_ct_helpers:run_teardown_steps(Config,
+ rabbit_ct_broker_helpers:teardown_steps()).
init_per_testcase(Testcase, Config) ->
rabbit_ct_helpers:testcase_started(Config, Testcase).
@@ -95,23 +81,13 @@ proxy_protocol(Config) ->
PortStr = rabbit_ws_test_util:get_web_mqtt_port_str(Config),
Protocol = ?config(protocol, Config),
- WS = rfc6455_client:new(
- Protocol ++ "://127.0.0.1:" ++ PortStr ++ "/ws",
- self(),
- undefined,
- ["mqtt"],
- "PROXY TCP4 192.168.1.1 192.168.1.2 80 81\r\n"
- ),
+ WS = rfc6455_client:new(Protocol ++ "://127.0.0.1:" ++ PortStr ++ "/ws", self(),
+ undefined, ["mqtt"], "PROXY TCP4 192.168.1.1 192.168.1.2 80 81\r\n"),
{ok, _} = rfc6455_client:open(WS),
rfc6455_client:send_binary(WS, rabbit_ws_test_util:mqtt_3_1_1_connect_packet()),
{binary, _P} = rfc6455_client:recv(WS),
- ConnectionName = rabbit_ct_broker_helpers:rpc(
- Config,
- 0,
- ?MODULE,
- connection_name,
- []
- ),
+ ConnectionName = rabbit_ct_broker_helpers:rpc(Config, 0,
+ ?MODULE, connection_name, []),
match = re:run(ConnectionName, <<"^192.168.1.1:80 -> 192.168.1.2:81$">>, [{capture, none}]),
{close, _} = rfc6455_client:close(WS),
ok.
diff --git a/deps/rabbitmq_web_mqtt/test/system_SUITE.erl b/deps/rabbitmq_web_mqtt/test/system_SUITE.erl
index 6642ae2d5a..19b0f873c4 100644
--- a/deps/rabbitmq_web_mqtt/test/system_SUITE.erl
+++ b/deps/rabbitmq_web_mqtt/test/system_SUITE.erl
@@ -18,13 +18,13 @@ all() ->
groups() ->
[
- {tests, [], [
- no_websocket_subprotocol,
- unsupported_websocket_subprotocol,
- unacceptable_data_type,
- handle_invalid_packets,
- duplicate_connect
- ]}
+ {tests, [],
+ [no_websocket_subprotocol
+ ,unsupported_websocket_subprotocol
+ ,unacceptable_data_type
+ ,handle_invalid_packets
+ ,duplicate_connect
+ ]}
].
suite() ->
@@ -35,19 +35,15 @@ init_per_suite(Config) ->
Config1 = rabbit_ct_helpers:set_config(Config, [
{rmq_nodename_suffix, ?MODULE},
{protocol, "ws"}
- ]),
- rabbit_ct_helpers:run_setup_steps(
- Config1,
- rabbit_ct_broker_helpers:setup_steps() ++
- rabbit_ct_client_helpers:setup_steps()
- ).
+ ]),
+ rabbit_ct_helpers:run_setup_steps(Config1,
+ rabbit_ct_broker_helpers:setup_steps() ++
+ rabbit_ct_client_helpers:setup_steps()).
end_per_suite(Config) ->
- rabbit_ct_helpers:run_teardown_steps(
- Config,
- rabbit_ct_client_helpers:teardown_steps() ++
- rabbit_ct_broker_helpers:teardown_steps()
- ).
+ rabbit_ct_helpers:run_teardown_steps(Config,
+ rabbit_ct_client_helpers:teardown_steps() ++
+ rabbit_ct_broker_helpers:teardown_steps()).
init_per_group(_, Config) ->
Config.
@@ -76,9 +72,7 @@ websocket_subprotocol(Config, SubProtocol) ->
PortStr = rabbit_ws_test_util:get_web_mqtt_port_str(Config),
WS = rfc6455_client:new("ws://localhost:" ++ PortStr ++ "/ws", self(), undefined, SubProtocol),
{_, [{http_response, Res}]} = rfc6455_client:open(WS),
- {'HTTP/1.1', 400, <<"Bad Request">>, _} = cow_http:parse_status_line(
- rabbit_data_coercion:to_binary(Res)
- ),
+ {'HTTP/1.1', 400, <<"Bad Request">>, _} = cow_http:parse_status_line(rabbit_data_coercion:to_binary(Res)),
rfc6455_client:send_binary(WS, rabbit_ws_test_util:mqtt_3_1_1_connect_packet()),
{close, _} = rfc6455_client:recv(WS, timer:seconds(1)).
@@ -116,8 +110,7 @@ duplicate_connect(Config) ->
process_flag(trap_exit, true),
rfc6455_client:send_binary(WS, rabbit_ws_test_util:mqtt_3_1_1_connect_packet()),
eventually(?_assertEqual(0, num_mqtt_connections(Config, 0))),
- receive
- {'EXIT', WS, _} -> ok
+ receive {'EXIT', WS, _} -> ok
after 500 -> ct:fail("expected web socket to exit")
end.
diff --git a/rebar.config b/rebar.config
index e291e7625a..0590027d96 100644
--- a/rebar.config
+++ b/rebar.config
@@ -14,10 +14,3 @@
inline_items => {when_under, 4}
}}
]}.
-
-{project_plugins, [erlfmt]}.
-{erlfmt, [
- write,
- {print_width, 100},
- {files, "deps/{rabbitmq_mqtt,rabbitmq_web_mqtt}/{test,src}/*.erl"}
-]}.