@@ -489,45 +489,45 @@ hand_off_to_retainer(RetainerPid, Amqp2MqttFun, Topic0, Msg) ->
489489
490490maybe_send_retained_message (RPid , # mqtt_topic {name = Topic0 , qos = SubscribeQos },
491491 # proc_state {amqp2mqtt_fun = Amqp2MqttFun ,
492- packet_id = PacketId } = PState0 ) ->
492+ packet_id = PacketId0 } = PState0 ) ->
493493 Topic1 = Amqp2MqttFun (Topic0 ),
494494 case rabbit_mqtt_retainer :fetch (RPid , Topic1 ) of
495- undefined -> PState0 ;
496- Msg ->
497- % % calculate effective QoS as the lower value of SUBSCRIBE frame QoS
498- % % and retained message QoS. The spec isn't super clear on this, we
499- % % do what Mosquitto does, per user feedback.
500- Qos = erlang : min ( SubscribeQos , Msg # mqtt_msg . qos ),
501- { Id , PState } = case Qos of
502- ? QOS_0 -> { undefined , PState0 };
503- ? QOS_1 -> { PacketId , PState0 # proc_state {packet_id = increment_packet_id (PacketId )}}
504- end ,
495+ undefined ->
496+ PState0 ;
497+ Msg ->
498+ Qos = effective_qos ( Msg # mqtt_msg . qos , SubscribeQos ),
499+ { PacketId , PState } = case Qos of
500+ ? QOS_0 ->
501+ { undefined , PState0 };
502+ ? QOS_1 ->
503+ { PacketId0 , PState0 # proc_state {packet_id = increment_packet_id (PacketId0 )}}
504+ end ,
505505 serialise_and_send_to_client (
506506 # mqtt_frame {fixed = # mqtt_frame_fixed {
507507 type = ? PUBLISH ,
508508 qos = Qos ,
509509 dup = false ,
510510 retain = Msg # mqtt_msg .retain
511511 }, variable = # mqtt_frame_publish {
512- message_id = Id ,
512+ message_id = PacketId ,
513513 topic_name = Topic1
514514 },
515515 payload = Msg # mqtt_msg .payload },
516516 PState ),
517517 PState
518518 end .
519519
520- make_will_msg (# mqtt_frame_connect { will_flag = false }) ->
520+ make_will_msg (# mqtt_frame_connect {will_flag = false }) ->
521521 undefined ;
522- make_will_msg (# mqtt_frame_connect { will_retain = Retain ,
523- will_qos = Qos ,
524- will_topic = Topic ,
525- will_msg = Msg }) ->
526- # mqtt_msg { retain = Retain ,
527- qos = Qos ,
528- topic = Topic ,
529- dup = false ,
530- payload = Msg }.
522+ make_will_msg (# mqtt_frame_connect {will_retain = Retain ,
523+ will_qos = Qos ,
524+ will_topic = Topic ,
525+ will_msg = Msg }) ->
526+ # mqtt_msg {retain = Retain ,
527+ qos = Qos ,
528+ topic = Topic ,
529+ dup = false ,
530+ payload = Msg }.
531531
532532process_login (_UserBin , _PassBin , _ClientId ,
533533 # proc_state {peer_addr = Addr ,
@@ -999,9 +999,8 @@ binding_action(
999999 key = RoutingKey },
10001000 BindingFun (Binding , Username ).
10011001
1002- send_will (PState = # proc_state {will_msg = undefined }) ->
1003- PState ;
1004-
1002+ send_will (# proc_state {will_msg = undefined }) ->
1003+ ok ;
10051004send_will (PState = # proc_state {will_msg = WillMsg = # mqtt_msg {retain = Retain ,
10061005 topic = Topic },
10071006 retainer_pid = RPid ,
@@ -1010,25 +1009,14 @@ send_will(PState = #proc_state{will_msg = WillMsg = #mqtt_msg{retain = Retain,
10101009 ok ->
10111010 publish_to_queues (WillMsg , PState ),
10121011 case Retain of
1013- false -> ok ;
1014- true ->
1012+ false ->
1013+ ok ;
1014+ true ->
10151015 hand_off_to_retainer (RPid , Amqp2MqttFun , Topic , WillMsg )
10161016 end ;
1017- Error ->
1018- rabbit_log :warning (
1019- " Could not send last will: ~p " ,
1020- [Error ])
1021- end ,
1022- % %TODO cancel queue client?
1023- % case ChQos1 of
1024- % undefined -> ok;
1025- % _ -> amqp_channel:close(ChQos1)
1026- % end,
1027- % case ChQos0 of
1028- % undefined -> ok;
1029- % _ -> amqp_channel:close(ChQos0)
1030- % end,
1031- PState .
1017+ {error , access_refused = Reason } ->
1018+ rabbit_log :error (" failed to send will message: ~p " , [Reason ])
1019+ end .
10321020
10331021publish_to_queues (undefined , PState ) ->
10341022 {ok , PState };
@@ -1104,6 +1092,11 @@ deliver_to_queues(Delivery,
11041092process_routing_confirm (# delivery {confirm = false }, [], PState ) ->
11051093 rabbit_global_counters :messages_unroutable_dropped (mqtt , 1 ),
11061094 PState ;
1095+ process_routing_confirm (# delivery {confirm = true ,
1096+ msg_seq_no = undefined }, [], PState ) ->
1097+ % % unroutable will message with QoS > 0
1098+ rabbit_global_counters :messages_unroutable_dropped (mqtt , 1 ),
1099+ PState ;
11071100process_routing_confirm (# delivery {confirm = true ,
11081101 msg_seq_no = MsgId }, [], PState ) ->
11091102 rabbit_global_counters :messages_unroutable_returned (mqtt , 1 ),
@@ -1114,11 +1107,15 @@ process_routing_confirm(#delivery{confirm = true,
11141107 PState ;
11151108process_routing_confirm (# delivery {confirm = false }, _ , PState ) ->
11161109 PState ;
1110+ process_routing_confirm (# delivery {confirm = true ,
1111+ msg_seq_no = undefined }, [_ |_ ], PState ) ->
1112+ % % routable will message with QoS > 0
1113+ PState ;
11171114process_routing_confirm (# delivery {confirm = true ,
11181115 msg_seq_no = MsgId },
11191116 Qs , PState = # proc_state {unacked_client_pubs = U0 }) ->
11201117 QNames = queue_names (Qs ),
1121- U = rabbit_mqtt_confirms :insert (MsgId , QNames , U0 ),
1118+ { ok , U } = rabbit_mqtt_confirms :insert (MsgId , QNames , U0 ),
11221119 PState # proc_state {unacked_client_pubs = U }.
11231120
11241121send_puback (MsgIds , PState )
@@ -1250,10 +1247,7 @@ deliver_one_to_client(Msg = {QName, QPid, QMsgId, _Redelivered,
12501247 false ->
12511248 ? QOS_0
12521249 end ,
1253- % % "The QoS of Application Messages sent in response to a Subscription MUST be the minimum
1254- % % of the QoS of the originally published message and the Maximum QoS granted by the Server
1255- % % [MQTT-3.8.4-8]."
1256- QoS = min (PublisherQoS , SubscriberQoS ),
1250+ QoS = effective_qos (PublisherQoS , SubscriberQoS ),
12571251 PState1 = maybe_publish_to_client (Msg , QoS , PState0 ),
12581252 PState = maybe_ack (AckRequired , QoS , QName , QMsgId , PState1 ),
12591253 % %TODO GC
@@ -1264,6 +1258,13 @@ deliver_one_to_client(Msg = {QName, QPid, QMsgId, _Redelivered,
12641258 ok = maybe_notify_sent (QName , QPid , PState ),
12651259 PState .
12661260
1261+ -spec effective_qos (qos (), qos ()) -> qos ().
1262+ effective_qos (PublisherQoS , SubscriberQoS ) ->
1263+ % % "The QoS of Application Messages sent in response to a Subscription MUST be the minimum
1264+ % % of the QoS of the originally published message and the Maximum QoS granted by the Server
1265+ % % [MQTT-3.8.4-8]."
1266+ erlang :min (PublisherQoS , SubscriberQoS ).
1267+
12671268maybe_publish_to_client ({_ , _ , _ , _Redelivered = true , _ }, ? QOS_0 , PState ) ->
12681269 % % Do no redeliver to MQTT subscriber who gets message at most once.
12691270 PState ;
@@ -1405,28 +1406,27 @@ check_topic_access(TopicName, Access,
14051406 end
14061407 end .
14071408
1408- info (unacked_client_pubs , # proc_state {unacked_client_pubs = Val }) -> Val ;
1409+ info (protocol , # proc_state {info = # info {proto_human = Val }}) -> Val ;
1410+ info (host , # proc_state {info = # info {host = Val }}) -> Val ;
1411+ info (port , # proc_state {info = # info {port = Val }}) -> Val ;
1412+ info (peer_host , # proc_state {info = # info {peer_host = Val }}) -> Val ;
1413+ info (peer_port , # proc_state {info = # info {peer_port = Val }}) -> Val ;
1414+ info (ssl_login_name , # proc_state {ssl_login_name = Val }) -> Val ;
14091415info (client_id , # proc_state {client_id = Val }) ->
14101416 rabbit_data_coercion :to_binary (Val );
1417+ info (vhost , # proc_state {auth_state = # auth_state {vhost = Val }}) -> Val ;
1418+ info (user , # proc_state {auth_state = # auth_state {username = Val }}) -> Val ;
14111419info (clean_sess , # proc_state {clean_sess = Val }) -> Val ;
14121420info (will_msg , # proc_state {will_msg = Val }) -> Val ;
1413- info (exchange , # proc_state {exchange = # resource {name = Val }}) -> Val ;
1414- info (ssl_login_name , # proc_state {ssl_login_name = Val }) -> Val ;
14151421info (retainer_pid , # proc_state {retainer_pid = Val }) -> Val ;
1416- info (user , # proc_state {auth_state = # auth_state {username = Val }}) -> Val ;
1417- info (vhost , # proc_state {auth_state = # auth_state {vhost = Val }}) -> Val ;
1418- info (host , # proc_state {info = # info {host = Val }}) -> Val ;
1419- info (port , # proc_state {info = # info {port = Val }}) -> Val ;
1420- info (peer_host , # proc_state {info = # info {peer_host = Val }}) -> Val ;
1421- info (peer_port , # proc_state {info = # info {peer_port = Val }}) -> Val ;
1422- info (protocol , # proc_state {info = # info {proto_human = Val }}) -> Val ;
1423- % info(frame_max, PState) -> additional_info(frame_max, PState);
1424- % info(client_properties, PState) -> additional_info(client_properties, PState);
1425- % info(ssl, PState) -> additional_info(ssl, PState);
1426- % info(ssl_protocol, PState) -> additional_info(ssl_protocol, PState);
1427- % info(ssl_key_exchange, PState) -> additional_info(ssl_key_exchange, PState);
1428- % info(ssl_cipher, PState) -> additional_info(ssl_cipher, PState);
1429- % info(ssl_hash, PState) -> additional_info(ssl_hash, PState);
1422+ info (exchange , # proc_state {exchange = # resource {name = Val }}) -> Val ;
1423+ info (subscriptions , # proc_state {subscriptions = Val }) ->
1424+ maps :keys (Val );
1425+ info (prefetch , # proc_state {info = # info {prefetch = Val }}) -> Val ;
1426+ info (messages_unconfirmed , # proc_state {unacked_client_pubs = Val }) ->
1427+ rabbit_mqtt_confirms :size (Val );
1428+ info (messages_unacknowledged , # proc_state {unacked_server_pubs = Val }) ->
1429+ maps :size (Val );
14301430info (Other , _ ) -> throw ({bad_argument , Other }).
14311431
14321432-spec ssl_login_name (rabbit_net :socket ()) ->
0 commit comments