@@ -23,7 +23,7 @@ use async_trait::async_trait;
2323use backon:: Retryable ;
2424#[ cfg( feature = "cli" ) ]
2525use clap:: Args ;
26- use log:: { debug, trace} ;
26+ use log:: { debug, error , trace} ;
2727use up_rust:: { UCode , UStatus } ;
2828
2929use crate :: { listener_registry:: SubscribedTopicProvider , SubscriptionIdentifier } ;
@@ -150,7 +150,7 @@ impl TryFrom<&MqttClientOptions> for paho_mqtt::ConnectOptions {
150150 connect_options_builder. user_name ( v) ;
151151 }
152152 if let Some ( v) = options. password . as_ref ( ) {
153- connect_options_builder. password ( v) ;
153+ connect_options_builder. password ( v. as_bytes ( ) ) ;
154154 }
155155 Ok ( connect_options_builder. finalize ( ) )
156156 }
@@ -221,6 +221,49 @@ impl TryFrom<&SslOptions> for paho_mqtt::SslOptions {
221221 }
222222}
223223
224+ fn ustatus_from_paho_error ( paho_error : paho_mqtt:: Error ) -> UStatus {
225+ match paho_error {
226+ paho_mqtt:: Error :: Disconnected => {
227+ UStatus :: fail_with_code ( UCode :: UNAVAILABLE , "not connected to MQTT broker" )
228+ }
229+ paho_mqtt:: Error :: TcpTlsConnectFailure => {
230+ UStatus :: fail_with_code ( UCode :: UNAVAILABLE , "failed to connect to MQTT broker" )
231+ }
232+ paho_mqtt:: Error :: ReasonCode ( paho_mqtt:: ReasonCode :: BadUserNameOrPassword , _) => {
233+ UStatus :: fail_with_code ( UCode :: UNAUTHENTICATED , "bad credentials" )
234+ }
235+ // [impl->dsn~mqtt5-transport-authorization~1]
236+ paho_mqtt:: Error :: ReasonCode ( paho_mqtt:: ReasonCode :: NotAuthorized , _) => {
237+ UStatus :: fail_with_code ( UCode :: PERMISSION_DENIED , "not authorized" )
238+ }
239+ paho_mqtt:: Error :: ReasonCode ( paho_mqtt:: ReasonCode :: ServerUnavailable , _) => {
240+ UStatus :: fail_with_code ( UCode :: UNAVAILABLE , "server not available" )
241+ }
242+ paho_mqtt:: Error :: ReasonCode ( paho_mqtt:: ReasonCode :: ServerBusy , _) => {
243+ UStatus :: fail_with_code ( UCode :: UNAVAILABLE , "server busy" )
244+ }
245+ paho_mqtt:: Error :: ReasonCode ( paho_mqtt:: ReasonCode :: BadAuthenticationMethod , _) => {
246+ UStatus :: fail_with_code ( UCode :: UNAUTHENTICATED , "bad authentication method" )
247+ }
248+ paho_mqtt:: Error :: ReasonCode ( paho_mqtt:: ReasonCode :: MessageRateTooHigh , _) => {
249+ UStatus :: fail_with_code ( UCode :: RESOURCE_EXHAUSTED , "message rate to high" )
250+ }
251+ paho_mqtt:: Error :: ReasonCode ( paho_mqtt:: ReasonCode :: QuotaExceeded , _) => {
252+ UStatus :: fail_with_code ( UCode :: RESOURCE_EXHAUSTED , "quota exceeded" )
253+ }
254+ paho_mqtt:: Error :: ReasonCode ( paho_mqtt:: ReasonCode :: ConnectionRateExceeded , _) => {
255+ UStatus :: fail_with_code ( UCode :: RESOURCE_EXHAUSTED , "connection rate exceeded" )
256+ }
257+ paho_mqtt:: Error :: ReasonCode ( paho_mqtt:: ReasonCode :: MaximumConnectTime , _) => {
258+ UStatus :: fail_with_code ( UCode :: RESOURCE_EXHAUSTED , "maximum connect time exceeded" )
259+ }
260+ _ => {
261+ error ! ( "paho error: {paho_error:?}" ) ;
262+ UStatus :: fail_with_code ( UCode :: INTERNAL , paho_error. to_string ( ) )
263+ }
264+ }
265+ }
266+
224267/// Basic operations that an MQTT client performs.
225268#[ cfg_attr( test, mockall:: automock) ]
226269#[ async_trait]
@@ -331,18 +374,6 @@ pub(crate) struct PahoBasedMqttClientOperations {
331374}
332375
333376impl PahoBasedMqttClientOperations {
334- fn ustatus_from_paho_error ( paho_error : & paho_mqtt:: Error ) -> UStatus {
335- match paho_error {
336- paho_mqtt:: Error :: Disconnected => {
337- UStatus :: fail_with_code ( UCode :: UNAVAILABLE , "not connected to MQTT broker" )
338- }
339- paho_mqtt:: Error :: TcpTlsConnectFailure => {
340- UStatus :: fail_with_code ( UCode :: UNAVAILABLE , "failed to connect to MQTT broker" )
341- }
342- _ => UStatus :: fail_with_code ( UCode :: UNKNOWN , paho_error. to_string ( ) ) ,
343- }
344- }
345-
346377 /// Creates new MQTT client.
347378 ///
348379 /// # Arguments
@@ -491,12 +522,7 @@ impl MqttClientOperations for PahoBasedMqttClientOperations {
491522 Self :: process_connack ( user_data, response) ;
492523 }
493524 } )
494- . map_err ( |e| {
495- UStatus :: fail_with_code (
496- UCode :: INTERNAL ,
497- format ! ( "Failed to connect to MQTT broker: {e:?}" ) ,
498- )
499- } )
525+ . map_err ( ustatus_from_paho_error)
500526 }
501527
502528 fn is_connected ( & self ) -> bool {
@@ -607,7 +633,7 @@ impl MqttClientOperations for PahoBasedMqttClientOperations {
607633 self . inner_mqtt_client
608634 . publish ( mqtt_message)
609635 . await
610- . map_err ( |paho_error| Self :: ustatus_from_paho_error ( & paho_error ) )
636+ . map_err ( ustatus_from_paho_error)
611637 }
612638
613639 async fn subscribe ( & self , topic : & str , id : u16 ) -> Result < ( ) , UStatus > {
@@ -634,22 +660,25 @@ impl MqttClientOperations for PahoBasedMqttClientOperations {
634660 // QOS 1 - Delivered and received at least once
635661 . subscribe_with_options ( topic, paho_mqtt:: QOS_1 , None , subscription_properties)
636662 . await
637- . map_err ( |paho_error| Self :: ustatus_from_paho_error ( & paho_error ) )
663+ . map_err ( ustatus_from_paho_error)
638664 . map ( |_| ( ) )
639665 }
640666
641667 async fn unsubscribe ( & self , topic : & str ) -> Result < ( ) , UStatus > {
642668 self . inner_mqtt_client
643669 . unsubscribe ( topic)
644670 . await
645- . map_err ( |paho_error| Self :: ustatus_from_paho_error ( & paho_error ) )
671+ . map_err ( ustatus_from_paho_error)
646672 . map ( |_| ( ) )
647673 }
648674}
649675
650676#[ cfg( test) ]
651677mod tests {
652- use paho_mqtt:: ConnectOptions ;
678+ use paho_mqtt:: { ConnectOptions , Properties } ;
679+ use up_rust:: UCode ;
680+
681+ use crate :: mqtt_client:: ustatus_from_paho_error;
653682
654683 use super :: MqttClientOptions ;
655684
@@ -668,4 +697,18 @@ mod tests {
668697 // because the ConnectOptions struct does not (yet) provide access to the CONNECT packet
669698 // properties
670699 }
700+
701+ #[ test_case:: test_case(
702+ paho_mqtt:: Error :: TcpTlsConnectFailure => UCode :: UNAVAILABLE ;
703+ "connect failure" ) ]
704+ #[ test_case:: test_case(
705+ paho_mqtt:: Error :: Disconnected => UCode :: UNAVAILABLE ;
706+ "disconnected" ) ]
707+ // [utest->dsn~mqtt5-transport-authorization~1]
708+ #[ test_case:: test_case(
709+ paho_mqtt:: Error :: ReasonCode ( paho_mqtt:: ReasonCode :: NotAuthorized , Properties :: new( ) ) => UCode :: PERMISSION_DENIED ;
710+ "not authorized" ) ]
711+ fn test_ustatus_from_paho_error ( paho_error : paho_mqtt:: Error ) -> UCode {
712+ ustatus_from_paho_error ( paho_error) . get_code ( )
713+ }
671714}
0 commit comments