73
73
MQTT_PKT_TYPE_MASK = const (0xF0 )
74
74
75
75
76
+ CONNACK_ERROR_INCORRECT_PROTOCOL = const (0x01 )
77
+ CONNACK_ERROR_ID_REJECTED = const (0x02 )
78
+ CONNACK_ERROR_SERVER_UNAVAILABLE = const (0x03 )
79
+ CONNACK_ERROR_INCORECT_USERNAME_PASSWORD = const (0x04 )
80
+ CONNACK_ERROR_UNAUTHORIZED = const (0x05 )
81
+
76
82
CONNACK_ERRORS = {
77
- const ( 0x01 ) : "Connection Refused - Incorrect Protocol Version" ,
78
- const ( 0x02 ) : "Connection Refused - ID Rejected" ,
79
- const ( 0x03 ) : "Connection Refused - Server unavailable" ,
80
- const ( 0x04 ) : "Connection Refused - Incorrect username/password" ,
81
- const ( 0x05 ) : "Connection Refused - Unauthorized" ,
83
+ CONNACK_ERROR_INCORRECT_PROTOCOL : "Connection Refused - Incorrect Protocol Version" ,
84
+ CONNACK_ERROR_ID_REJECTED : "Connection Refused - ID Rejected" ,
85
+ CONNACK_ERROR_SERVER_UNAVAILABLE : "Connection Refused - Server unavailable" ,
86
+ CONNACK_ERROR_INCORECT_USERNAME_PASSWORD : "Connection Refused - Incorrect username/password" ,
87
+ CONNACK_ERROR_UNAUTHORIZED : "Connection Refused - Unauthorized" ,
82
88
}
83
89
84
90
_default_sock = None # pylint: disable=invalid-name
88
94
class MMQTTException (Exception ):
89
95
"""MiniMQTT Exception class."""
90
96
97
+ def __init__ (self , error , code = None ):
98
+ super ().__init__ (error , code )
99
+ self .code = code
100
+
91
101
92
102
class NullLogger :
93
103
"""Fake logger class that does not do anything"""
@@ -397,21 +407,31 @@ def connect(
397
407
)
398
408
self ._reset_reconnect_backoff ()
399
409
return ret
400
- except RuntimeError as e :
410
+ except (MemoryError , OSError , RuntimeError ) as e :
411
+ if isinstance (e , RuntimeError ) and e .args == ("pystack exhausted" ,):
412
+ raise
401
413
self .logger .warning (f"Socket error when connecting: { e } " )
414
+ last_exception = e
402
415
backoff = False
403
416
except MMQTTException as e :
404
- last_exception = e
417
+ self . _close_socket ()
405
418
self .logger .info (f"MMQT error: { e } " )
419
+ if e .code in [
420
+ CONNACK_ERROR_INCORECT_USERNAME_PASSWORD ,
421
+ CONNACK_ERROR_UNAUTHORIZED ,
422
+ ]:
423
+ # No sense trying these again, re-raise
424
+ raise
425
+ last_exception = e
406
426
backoff = True
407
427
408
428
if self ._reconnect_attempts_max > 1 :
409
429
exc_msg = "Repeated connect failures"
410
430
else :
411
431
exc_msg = "Connect failure"
432
+
412
433
if last_exception :
413
434
raise MMQTTException (exc_msg ) from last_exception
414
-
415
435
raise MMQTTException (exc_msg )
416
436
417
437
# pylint: disable=too-many-branches, too-many-statements, too-many-locals
@@ -508,7 +528,7 @@ def _connect(
508
528
rc = self ._sock_exact_recv (3 )
509
529
assert rc [0 ] == 0x02
510
530
if rc [2 ] != 0x00 :
511
- raise MMQTTException (CONNACK_ERRORS [rc [2 ]])
531
+ raise MMQTTException (CONNACK_ERRORS [rc [2 ]], code = rc [ 2 ] )
512
532
self ._is_connected = True
513
533
result = rc [0 ] & 1
514
534
if self .on_connect is not None :
@@ -522,6 +542,12 @@ def _connect(
522
542
f"No data received from broker for { self ._recv_timeout } seconds."
523
543
)
524
544
545
+ def _close_socket (self ):
546
+ if self ._sock :
547
+ self .logger .debug ("Closing socket" )
548
+ self ._connection_manager .close_socket (self ._sock )
549
+ self ._sock = None
550
+
525
551
# pylint: disable=no-self-use
526
552
def _encode_remaining_length (
527
553
self , fixed_header : bytearray , remaining_length : int
@@ -550,8 +576,7 @@ def disconnect(self) -> None:
550
576
self ._sock .send (MQTT_DISCONNECT )
551
577
except RuntimeError as e :
552
578
self .logger .warning (f"Unable to send DISCONNECT packet: { e } " )
553
- self .logger .debug ("Closing socket" )
554
- self ._connection_manager .close_socket (self ._sock )
579
+ self ._close_socket ()
555
580
self ._is_connected = False
556
581
self ._subscribed_topics = []
557
582
self ._last_msg_sent_timestamp = 0
@@ -568,6 +593,7 @@ def ping(self) -> list[int]:
568
593
self ._sock .send (MQTT_PINGREQ )
569
594
ping_timeout = self .keep_alive
570
595
stamp = ticks_ms ()
596
+
571
597
self ._last_msg_sent_timestamp = stamp
572
598
rc , rcs = None , []
573
599
while rc != MQTT_PINGRESP :
@@ -946,7 +972,7 @@ def _wait_for_msg(self, timeout: Optional[float] = None) -> Optional[int]:
946
972
res = self ._sock_exact_recv (1 )
947
973
except self ._socket_pool .timeout :
948
974
return None
949
- else : # socketpool, esp32spi
975
+ else : # socketpool, esp32spi, wiznet5k
950
976
try :
951
977
res = self ._sock_exact_recv (1 , timeout = timeout )
952
978
except OSError as error :
@@ -1035,14 +1061,14 @@ def _sock_exact_recv(
1035
1061
"""
1036
1062
stamp = ticks_ms ()
1037
1063
if not self ._backwards_compatible_sock :
1038
- # CPython/Socketpool Impl.
1064
+ # CPython, socketpool, esp32spi, wiznet5k
1039
1065
rc = bytearray (bufsize )
1040
1066
mv = memoryview (rc )
1041
1067
recv_len = self ._sock .recv_into (rc , bufsize )
1042
1068
to_read = bufsize - recv_len
1043
1069
if to_read < 0 :
1044
1070
raise MMQTTException (f"negative number of bytes to read: { to_read } " )
1045
- read_timeout = timeout if timeout is not None else self .keep_alive
1071
+ read_timeout = timeout if timeout is not None else self ._recv_timeout
1046
1072
mv = mv [recv_len :]
1047
1073
while to_read > 0 :
1048
1074
recv_len = self ._sock .recv_into (mv , to_read )
@@ -1052,8 +1078,8 @@ def _sock_exact_recv(
1052
1078
raise MMQTTException (
1053
1079
f"Unable to receive { to_read } bytes within { read_timeout } seconds."
1054
1080
)
1055
- else : # ESP32SPI Impl.
1056
- # This will timeout with socket timeout (not keepalive timeout)
1081
+ else : # Legacy: fona, esp_atcontrol
1082
+ # This will time out with socket timeout (not receive timeout).
1057
1083
rc = self ._sock .recv (bufsize )
1058
1084
if not rc :
1059
1085
self .logger .debug ("_sock_exact_recv timeout" )
@@ -1063,7 +1089,7 @@ def _sock_exact_recv(
1063
1089
# or raise exception if wait longer than read_timeout
1064
1090
to_read = bufsize - len (rc )
1065
1091
assert to_read >= 0
1066
- read_timeout = self .keep_alive
1092
+ read_timeout = self ._recv_timeout
1067
1093
while to_read > 0 :
1068
1094
recv = self ._sock .recv (to_read )
1069
1095
to_read -= len (recv )
0 commit comments