async def probe(svr, proto_code, use_tor): conn = StratumClient() try: await conn.connect(svr, proto_code, use_tor=(svr.is_onion or use_tor), short_term=True) except: failed.add(str(svr)) return None peers, _ = conn.subscribe('server.peers.subscribe') peers = await peers print("%s gave %d peers" % (svr, len(peers))) connected.add(str(svr)) # track them all. more = ks.add_peer_response(peers) if more: print("found %d more servers from %s: %s" % (len(more), svr, ', '.join(more))) conn.close() return str(svr)
class Connection: """ Connection object. Connects to an Electrum server, and handles all Stratum protocol messages. """ # pylint: disable=E1111 def __init__(self, loop: asyncio.AbstractEventLoop, server: str, port: int, proto: str) -> None: """ Connection object constructor. :param loop: an asyncio event loop :param server: a string containing a hostname :param port: port number that the server listens on :returns: A new Connection object """ logging.info("Connecting...") self.server_info = ServerInfo(server, hostname=server, ports=port) # type: ServerInfo logging.info(str(self.server_info.get_port(proto))) self.client = StratumClient(loop) # type: StratumClient self.connection = self.client.connect( self.server_info, proto_code=proto, use_tor=True, disable_cert_verify=(proto != "s")) # type: asyncio.Future self.queue = None # type: asyncio.Queue async def do_connect(self) -> None: """ Coroutine. Establishes a persistent connection to an Electrum server. Awaits the connection because AFAIK an init method can't be async. """ await self.connection logging.info("Connected to server") async def listen_rpc(self, method: str, args: List) -> Any: """ Coroutine. Sends a normal RPC message to the server and awaits response. :param method: The Electrum API method to use :param args: Params associated with current method :returns: Future. Response from server for this method(args) """ return await self.client.RPC(method, *args) def listen_subscribe(self, method: str, args: List) -> None: """ Sends a "subscribe" message to the server and adds to the queue. Throws away the immediate future containing the "history" hash. :param method: The Electrum API method to use :param args: Params associated with current method """ t = self.client.subscribe( method, *args) # type: Tuple[asyncio.Future, asyncio.Queue] future, queue = t self.queue = queue return future async def consume_queue( self, queue_func: Callable[[List[str]], Awaitable[None]]) -> None: """ Coroutine. Infinite loop that consumes the current subscription queue. :param queue_func: A function to call when new responses arrive """ while True: result = await self.queue.get() # type: List[str] await queue_func(result)