From e0479b16e5f4596346cf5a3e21e9dccf184a124d Mon Sep 17 00:00:00 2001 From: thilo jeremias Date: Sat, 9 May 2026 19:08:57 +0200 Subject: [PATCH] Fix error in handling of remaining filed The actual field points to the data length in this message The logic in the file only works if it contains at max one message if the tcp packet contains multiple mqtt packets the calculation fails Workaround: remove extra bytes and loop call until all is handled Not the best way to fix... --- mqtt_message.py | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/mqtt_message.py b/mqtt_message.py index f8b3d4e..e80d6d9 100644 --- a/mqtt_message.py +++ b/mqtt_message.py @@ -54,6 +54,7 @@ class MQTTControlPacket: UNSUBACK, ] + unparsed = '' def __init__(self, packet): self._packet = packet # Fixed header @@ -62,6 +63,13 @@ def __init__(self, packet): self.packet_type_human = self.Names[self.packet_type] self.dup, self.qos, self.retain = self._parse_flags() self.remaining_length, self.total_length = self._parse_remaining_length() +# The remaining_length only gives the data, +# it is possible that one tcp packet contains multiple mqtt packets +# capture the unparsed stuff + if self.total_length < len(packet): + self.unparsed = packet[self.total_length:] + self._packet = packet[:self.total_length] + if self.total_length > len(packet): # Partial packet, raise BlockingIOError (the Python error than best corresponds to errno EAGAIN) raise BlockingIOError(f'Incomplete MQTT control packet: only {len(packet)} bytes remaining, but header expected {self.total_length}', len(packet)) @@ -263,8 +271,12 @@ def _parse_packet_identifier(self): def tcp_message(flow: tcp.TCPFlow | http.HTTPFlow): message = flow.messages[-1] - mqtt_packet = MQTTControlPacket(message.content) - dump(mqtt_packet) + data = message.content + while data: + mqtt_packet = MQTTControlPacket(data) + dump(mqtt_packet) + data = mqtt_packet.unparsed + def dump(mqtt_packet: MQTTControlPacket): @@ -306,12 +318,16 @@ def websocket_message(flow: http.HTTPFlow): ws_buffer[fid] += flow.websocket.messages[-1].content while ws_buffer[fid]: try: - mqtt_packet = MQTTControlPacket(ws_buffer[fid]) + data = ws_buffer[fid] + while data: + mqtt_packet = MQTTControlPacket(data) + dump(mqtt_packet) + data = mqtt_packet.unparsed + except BlockingIOError as exc: ctx.log.debug("Awaiting more bytes for complete MQTT control packet") break else: - dump(mqtt_packet) - b = ws_buffer[fid] = mqtt_packet._extra + b = ws_buffer[fid] = mqtt_packet._extra # Not 100% about the logic here -- check if b: ctx.log.debug(f'Saving remaining {len(b)} bytes after MQTT control packet')