--- a/src/eric7/EricNetwork/EricJsonClient.py Wed Jan 24 18:52:50 2024 +0100 +++ b/src/eric7/EricNetwork/EricJsonClient.py Thu Jan 25 14:13:36 2024 +0100 @@ -12,8 +12,10 @@ import json import select import socket +import struct import sys import traceback +import zlib class EricJsonClient: @@ -52,8 +54,28 @@ "method": command, "params": params, } - cmd = json.dumps(commandDict) + "\n" - self.__connection.sendall(cmd.encode("utf8", "backslashreplace")) + data = json.dumps(commandDict).encode("utf8", "backslashreplace") + header = struct.pack(b"!II", len(data), zlib.adler32(data) & 0xFFFFFFFF) + self.__connection.sendall(header) + self.__connection.sendall(data) + + def __receiveBytes(self, length): + """ + Private method to receive the given length of bytes. + + @param length bytes to receive + @type int + @return received bytes or None if connection closed + @rtype bytes + """ + data = bytearray() + while len(data) < length: + newData = self.__connection.recv(length - len(data)) + if not newData: + return None + + data += newData + return data def __receiveJson(self): """ @@ -65,32 +87,36 @@ @rtype tuple of (str, dict) """ # step 1: receive the data - # The JSON RPC string is prefixed by a 9 character long length field. - length = self.__connection.recv(9) - if len(length) < 9: - # invalid length string received + header = self.__receiveBytes(struct.calcsize(b"!II")) + if not header: return None, None + length, datahash = struct.unpack(b"!II", header) + length = int(length) - data = bytearray() - while len(data) < length: - newData = self.__connection.recv(length - len(data)) - if not newData: - return None, None - - data += newData + data = self.__receiveBytes(length) + if not data or zlib.adler32(data) & 0xFFFFFFFF != datahash: + self.sendJson( + "ClientException", + { + "ExceptionType": "ProtocolError", + "ExceptionValue": "The checksum of the data does not match.", + "ProtocolData": data.decode("utf8", "backslashreplace"), + }, + ) + return None, None # step 2: decode and convert the data - line = data.decode("utf8", "backslashreplace") + jsonString = data.decode("utf8", "backslashreplace") try: - commandDict = json.loads(line.strip()) + commandDict = json.loads(jsonString.strip()) except (TypeError, ValueError) as err: self.sendJson( "ClientException", { "ExceptionType": "ProtocolError", "ExceptionValue": str(err), - "ProtocolData": line.strip(), + "ProtocolData": jsonString.strip(), }, ) return None, None