async def query_remote_once(self, domain, nameservers=None): resolver = self.resolver req = DNSMessage(qr=REQUEST) if nameservers is None: nameservers = resolver.get_nameservers(domain) req.qd = [Record(REQUEST, domain, self.qtype)] logger.debug('[query_remote_once][%s][%s] %s', types.get_name(self.qtype), domain, nameservers) inter_res = await self.request_remote(nameservers, req) resolver.cache_message(inter_res) return inter_res
async def request(req, addr, timeout=3.0): ''' Send raw data through UDP. ''' dispatcher = await Dispatcher.get(addr.ip_type) data = await dispatcher.send(req, addr, timeout) result = DNSMessage.parse(data) return result
def __init__(self, resolver, fqdn, qtype, tick): self.resolver = resolver self.fqdn = fqdn self.qtype = qtype self.tick = tick self._cached = False self._status = PENDING self._result = DNSMessage(ra=resolver.recursive) self._result.qd.append(Record(REQUEST, name=fqdn, qtype=qtype))
def __init__(self, resolver, loop, fqdn, qtype, tick): self.loop = loop self.resolver = resolver self.fqdn = fqdn self.qtype = qtype self.tick = tick self.future = loop.create_future() self.from_cache = False self._status = PENDING self._result = DNSMessage(ra=resolver.recursive) self._result.qd.append(Record(REQUEST, name=fqdn, qtype=qtype))
async def _resolve_hostname(resolver, hostname, qtype): '''Resolve a hostname with the given resolver.''' for _ in range(0, 5): try: message = await resolver.query(hostname, qtype) if message.r == 2: continue if hostname == 'message.acronis.com': logging.debug(message) return YADBDnsMessage(hostname, qtype, message) except asyncio.CancelledError: continue except AssertionError as ex: if str(ex) == 'Remote server fail': continue except asyncio.exceptions.TimeoutError: continue message = DNSMessage() message.r = 2 if hostname == 'message.acronis.com': logging.debug(message) return YADBDnsMessage(hostname, qtype, message)
async def request(req, addr, timeout=3.0): ''' Send raw data with a connection pool. ''' async with ConnectionHandle(*addr.to_addr(), ssl=addr.protocol == 'tcps') as conn: reader = conn.reader writer = conn.writer qdata = req.pack() bsize = struct.pack('!H', len(qdata)) writer.write(bsize) writer.write(qdata) await writer.drain() size, = struct.unpack('!H', await reader.readexactly(2)) data = await reader.readexactly(size) result = DNSMessage.parse(data) return result
async def request_remote(self, nameservers, req): while not self.future.cancelled(): addr = nameservers.get() if not addr: raise InvalidNameServer try: data = await self.request_once(req, addr) inter_res = DNSMessage.parse(data) logger.debug('[request_remote] %s', inter_res) if inter_res.qd[0].name != req.qd[0].name: raise DNSError(-1, 'Question section mismatch') assert inter_res.r != 2, 'Remote server fail' except (asyncio.TimeoutError, AssertionError) as e: logger.debug('[request_remote][server_error] %s', e) except DNSError as e: logger.debug('[request_remote][dns_error] %s', e) except Exception as e: logger.error('[request_remote][error] %s', e) else: nameservers.success(addr) return inter_res nameservers.fail(addr)
async def request(req, addr, timeout=3.0): ''' Send raw data with a connection pool. ''' qdata = req.pack() bsize = struct.pack('!H', len(qdata)) key = str(addr) queue = _connections.get(key) if queue is None: queue = asyncio.Queue(maxsize=DEFAULT_QUEUE_SIZE) _connections[key] = queue for _retry in range(5): reader = writer = None try: reader, writer = queue.get_nowait() except asyncio.QueueEmpty: pass if reader is None: try: reader, writer = await asyncio.wait_for( asyncio.open_connection(*addr.to_addr()), timeout) except asyncio.TimeoutError: pass if reader is None: continue writer.write(bsize) writer.write(qdata) try: await writer.drain() size, = struct.unpack('!H', await reader.readexactly(2)) data = await reader.readexactly(size) queue.put_nowait((reader, writer)) except asyncio.QueueFull: pass result = DNSMessage.parse(data) return result else: raise DNSConnectionError