diff --git a/scripts/rpc/client.py b/scripts/rpc/client.py index c5d24b557..92abd48bf 100644 --- a/scripts/rpc/client.py +++ b/scripts/rpc/client.py @@ -15,6 +15,7 @@ class JSONRPCException(Exception): class JSONRPCClient(object): def __init__(self, addr, port=None, verbose=False, timeout=60.0): + self.sock = None self.verbose = verbose self.timeout = timeout self.request_id = 0 @@ -35,69 +36,69 @@ class JSONRPCClient(object): "Error details: %s" % (addr, ex)) def __del__(self): - self.sock.close() + if self.sock: + self.sock.close() - def call(self, method, params={}, verbose=False): + def send(self, method, params=None): self.request_id += 1 - req = {} - req['jsonrpc'] = '2.0' - req['method'] = method - req['id'] = self.request_id - if (params): + req = { + 'jsonrpc': '2.0', + 'method': method, + 'id': self.request_id + } + + if params: req['params'] = params + reqstr = json.dumps(req) - - verbose = verbose or self.verbose - - if verbose: + if self.verbose: print("request:") print(json.dumps(req, indent=2)) self.sock.sendall(reqstr.encode("utf-8")) - buf = '' - closed = False - response = {} - start_time = time.clock() + return req - while not closed: + def recv(self): + start_time = time.clock() + response = None + buf = '' + while not response: try: timeout = self.timeout - (time.clock() - start_time) - if timeout <= 0.0: - break - self.sock.settimeout(timeout) newdata = self.sock.recv(4096) - if (newdata == b''): - closed = True - + if not newdata: + self.sock.close() + self.sock = None + raise JSONRPCException("Connection closed with partial response:\n%s\n" % buf) buf += newdata.decode("utf-8") response = json.loads(buf) except socket.timeout: - break + break # throw exception after loop to avoid Python freaking out about nested exceptions except ValueError: continue # incomplete response; keep buffering - break if not response: - if method == "kill_instance": - return {} - if closed: - msg = "Connection closed with partial response:" - else: - msg = "Timeout while waiting for response:" - msg = "\n".join([msg, buf]) - raise JSONRPCException(msg) + raise JSONRPCException("Timeout while waiting for response:\n%s\n" % buf) - if verbose: + if self.verbose: print("response:") print(json.dumps(response, indent=2)) if 'error' in response: msg = "\n".join(["Got JSON-RPC error response", - "request:", - json.dumps(req, indent=2), "response:", json.dumps(response['error'], indent=2)]) raise JSONRPCException(msg) + return response - return response['result'] + def call(self, method, params=None): + self.send(method, params) + try: + return self.recv()['result'] + except JSONRPCException as e: + """ Don't expect response to kill """ + if not self.sock and method == "kill_instance": + return {} + else: + raise e