import asyncio
import json
import logging
import socket
logger = logging.getLogger(__name__)
class StratumProtocol(asyncio.Protocol):
client = None
closed = False
transport = None
buf = b""
connection_lost_called = False
def connection_made(self, transport):
self.transport = transport
logger.debug("Transport connected ok")
sock = self.transport.get_extra_info("socket")
if sock is not None:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
def connection_lost(self, exc):
if not self.closed:
self.closed = True
self.close()
if not self.connection_lost_called:
self.connection_lost_called = True
self.client.connection_lost(self)
def data_received(self, data):
self.buf += data
*lines, self.buf = self.buf.split(b"\n")
for line in lines:
if not line:
continue
try:
msg = line.decode("utf-8", "error").strip()
except UnicodeError as exc:
logger.exception("Encoding issue on %r", line)
self.connection_lost(exc)
return
try:
msg = json.loads(msg)
except ValueError as exc:
logger.exception("Bad JSON received from server: %r", msg)
self.connection_lost(exc)
return
try:
self.client._got_response(msg)
except Exception as e:
logger.exception("Trouble handling response! (%s)", e)
continue
def send_data(self, message):
data = json.dumps(message).encode("utf-8") + b"\n"
self.transport.write(data)
def close(self):
if not self.closed:
try:
self.transport.close()
finally:
self.closed = True