diff --git a/bitcoin/rpc.py b/bitcoin/rpc.py index 0677c67b..dac89ea4 100644 --- a/bitcoin/rpc.py +++ b/bitcoin/rpc.py @@ -37,6 +37,17 @@ import os import platform import sys +import socket + +try: + from socket import MSG_PEEK, MSG_DONTWAIT + import select + from select import EPOLLIN, EPOLLHUP + EPOLL = True +except ImportError: + EPOLL = False + + try: import urllib.parse as urlparse except ImportError: @@ -183,11 +194,19 @@ def __init__(self, self.__conn = httplib.HTTPConnection(self.__url.hostname, port=port, timeout=timeout) + self.ep = None def _call(self, service_name, *args): self.__id_count += 1 + if EPOLL and self.ep: + for (fd, ev) in self.ep.poll(0): + if ev & EPOLLHUP or (ev & EPOLLIN and \ + b'' == self.__conn.sock.recv(1, MSG_DONTWAIT|MSG_PEEK)): + self.__conn.close() + self.ep.close() + self.ep = None postdata = json.dumps({'version': '1.1', 'method': service_name, 'params': args, @@ -197,6 +216,9 @@ def _call(self, service_name, *args): 'User-Agent': DEFAULT_USER_AGENT, 'Authorization': self.__auth_header, 'Content-type': 'application/json'}) + if EPOLL and not self.ep: + self.ep = select.epoll() + self.ep.register(self.__conn.sock, select.EPOLLIN|select.EPOLLHUP) response = self._get_response() if response['error'] is not None: @@ -210,11 +232,21 @@ def _call(self, service_name, *args): def _batch(self, rpc_call_list): postdata = json.dumps(list(rpc_call_list)) + if EPOLL and self.ep: + for (fd, ev) in self.ep.poll(0): + if ev & EPOLLHUP or (ev & EPOLLIN and \ + b'' == self.__conn.sock.recv(1, MSG_DONTWAIT|MSG_PEEK)): + self.__conn.close() + self.ep.close() + self.ep = None self.__conn.request('POST', self.__url.path, postdata, {'Host': self.__url.hostname, 'User-Agent': DEFAULT_USER_AGENT, 'Authorization': self.__auth_header, 'Content-type': 'application/json'}) + if EPOLL and not self.ep: + self.ep = select.epoll() + self.ep.register(self.__conn.sock, select.EPOLLIN|select.EPOLLHUP) return self._get_response()