src/eric7/EricNetwork/EricJsonClient.py

branch
eric7
changeset 10524
ed4fd87c4d4c
parent 10522
c04e878aa308
child 10526
2549534fcb55
diff -r e4069ddd7dc7 -r ed4fd87c4d4c src/eric7/EricNetwork/EricJsonClient.py
--- 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

eric ide

mercurial