From da4f1b3a839a33e2bdd65d9f9dd03e9d707fca3e Mon Sep 17 00:00:00 2001 From: Torben Nehmer Date: Sun, 2 Aug 2026 16:31:06 +0200 Subject: [PATCH 1/2] Improve RSCP frame reception handling to ensure complete frames are processed --- e3dc/_e3dc_rscp_local.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/e3dc/_e3dc_rscp_local.py b/e3dc/_e3dc_rscp_local.py index 33da6af..21eef23 100644 --- a/e3dc/_e3dc_rscp_local.py +++ b/e3dc/_e3dc_rscp_local.py @@ -5,9 +5,10 @@ # Licensed under a MIT license. See LICENSE for details import socket +import struct from ._RSCPEncryptDecrypt import RSCPEncryptDecrypt -from ._rscpLib import RscpMessage, rscpDecode, rscpEncode, rscpFrame +from ._rscpLib import RscpMessage, rscpDecode, rscpEncode, rscpFrame, rscpFrameDecode from ._rscpTags import RscpError, RscpTag, RscpType DEFAULT_PORT = 5033 @@ -69,11 +70,22 @@ def _send(self, plainMsg: RscpMessage) -> None: self.socket.send(encData) def _receive(self): - data = self.socket.recv(BUFFER_SIZE) - if len(data) == 0: - raise RSCPKeyError - decData = rscpDecode(self.encdec.decrypt(data))[0] - return decData + # A single socket.recv() call is not guaranteed to return a complete + # RSCP frame (large responses can be split across multiple TCP reads), + # so keep receiving and decrypting until a full frame is available. + decData = b"" + while True: + data = self.socket.recv(BUFFER_SIZE) + if len(data) == 0: + raise RSCPKeyError + decData += self.encdec.decrypt(data) + try: + rscpFrameDecode(decData) + except struct.error: + # not enough data yet for a full frame: keep receiving + continue + break + return rscpDecode(decData)[0] def sendCommand(self, plainMsg: RscpMessage) -> None: """Sending RSCP command. From e53b198e70d2f2c93a631deb20085b57e3ddc5de Mon Sep 17 00:00:00 2001 From: Torben Nehmer Date: Sun, 2 Aug 2026 16:38:27 +0200 Subject: [PATCH 2/2] Fix linter error --- e3dc/_rscpLib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e3dc/_rscpLib.py b/e3dc/_rscpLib.py index fa9b598..b66138d 100644 --- a/e3dc/_rscpLib.py +++ b/e3dc/_rscpLib.py @@ -148,7 +148,7 @@ def rscpEncode( rscptypeHex = getHexRscpType(rscptype) rscptype = getRscpType(rscptype) - loggable_data = '' if tag in (RscpTag.SERVER_PASSWD, RscpTag.SERVER_USER ) else data + loggable_data = '' if tag in (RscpTag.SERVER_PASSWD, RscpTag.SERVER_USER) else data logger.debug("> %s %s %s", tag, rscptype, loggable_data) if isinstance(data, str):