src/eric7/EricNetwork/EricJsonClient.py

branch
eric7
changeset 10524
ed4fd87c4d4c
parent 10522
c04e878aa308
child 10526
2549534fcb55
equal deleted inserted replaced
10523:e4069ddd7dc7 10524:ed4fd87c4d4c
10 import contextlib 10 import contextlib
11 import io 11 import io
12 import json 12 import json
13 import select 13 import select
14 import socket 14 import socket
15 import struct
15 import sys 16 import sys
16 import traceback 17 import traceback
18 import zlib
17 19
18 20
19 class EricJsonClient: 21 class EricJsonClient:
20 """ 22 """
21 Class implementing a JSON based client base class. 23 Class implementing a JSON based client base class.
50 commandDict = { 52 commandDict = {
51 "jsonrpc": "2.0", 53 "jsonrpc": "2.0",
52 "method": command, 54 "method": command,
53 "params": params, 55 "params": params,
54 } 56 }
55 cmd = json.dumps(commandDict) + "\n" 57 data = json.dumps(commandDict).encode("utf8", "backslashreplace")
56 self.__connection.sendall(cmd.encode("utf8", "backslashreplace")) 58 header = struct.pack(b"!II", len(data), zlib.adler32(data) & 0xFFFFFFFF)
57 59 self.__connection.sendall(header)
58 def __receiveJson(self): 60 self.__connection.sendall(data)
59 """ 61
60 Private method to receive a JSON encoded command and data from the 62 def __receiveBytes(self, length):
61 server. 63 """
62 64 Private method to receive the given length of bytes.
63 @return tuple containing the received command and a dictionary 65
64 containing the associated data 66 @param length bytes to receive
65 @rtype tuple of (str, dict) 67 @type int
66 """ 68 @return received bytes or None if connection closed
67 # step 1: receive the data 69 @rtype bytes
68 # The JSON RPC string is prefixed by a 9 character long length field. 70 """
69 length = self.__connection.recv(9)
70 if len(length) < 9:
71 # invalid length string received
72 return None, None
73
74 length = int(length)
75 data = bytearray() 71 data = bytearray()
76 while len(data) < length: 72 while len(data) < length:
77 newData = self.__connection.recv(length - len(data)) 73 newData = self.__connection.recv(length - len(data))
78 if not newData: 74 if not newData:
79 return None, None 75 return None
80 76
81 data += newData 77 data += newData
78 return data
79
80 def __receiveJson(self):
81 """
82 Private method to receive a JSON encoded command and data from the
83 server.
84
85 @return tuple containing the received command and a dictionary
86 containing the associated data
87 @rtype tuple of (str, dict)
88 """
89 # step 1: receive the data
90 header = self.__receiveBytes(struct.calcsize(b"!II"))
91 if not header:
92 return None, None
93
94 length, datahash = struct.unpack(b"!II", header)
95
96 length = int(length)
97 data = self.__receiveBytes(length)
98 if not data or zlib.adler32(data) & 0xFFFFFFFF != datahash:
99 self.sendJson(
100 "ClientException",
101 {
102 "ExceptionType": "ProtocolError",
103 "ExceptionValue": "The checksum of the data does not match.",
104 "ProtocolData": data.decode("utf8", "backslashreplace"),
105 },
106 )
107 return None, None
82 108
83 # step 2: decode and convert the data 109 # step 2: decode and convert the data
84 line = data.decode("utf8", "backslashreplace") 110 jsonString = data.decode("utf8", "backslashreplace")
85 try: 111 try:
86 commandDict = json.loads(line.strip()) 112 commandDict = json.loads(jsonString.strip())
87 except (TypeError, ValueError) as err: 113 except (TypeError, ValueError) as err:
88 self.sendJson( 114 self.sendJson(
89 "ClientException", 115 "ClientException",
90 { 116 {
91 "ExceptionType": "ProtocolError", 117 "ExceptionType": "ProtocolError",
92 "ExceptionValue": str(err), 118 "ExceptionValue": str(err),
93 "ProtocolData": line.strip(), 119 "ProtocolData": jsonString.strip(),
94 }, 120 },
95 ) 121 )
96 return None, None 122 return None, None
97 123
98 method = commandDict["method"] 124 method = commandDict["method"]

eric ide

mercurial