async def request_remote(self, nameservers, req): last_err = None for addr in nameservers.iter(): try: inter_res = await self.request_once(req, addr) 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 Exception as e: error_type = 'error' if isinstance(e, (asyncio.TimeoutError, AssertionError)): error_type = 'server_error' elif isinstance(e, DNSError): error_type = 'dns_error' else: error_type = 'error' import traceback traceback.print_exc() logger.debug('[request_remote][%s] %s %s', error_type, str(addr), repr(e)) last_err = e else: nameservers.success(addr) return inter_res nameservers.fail(addr) else: raise last_err
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 query(self): domain = self.fqdn nameservers = None while True: self._cached = await self.query_cache(domain) logger.debug('[query_cache][%s][%s] %s', types.get_name(self.qtype), domain, self._cached) if self._cached: break remote_res = await self.query_remote(domain, nameservers) logger.debug('[query_remote][%s][%s] %s', types.get_name(self.qtype), domain, remote_res) if remote_res is None: break domain, nameservers = remote_res return self._result, self._cached
async def query(self): error = None domain = self.fqdn nameservers = None try: while True: if not self.future.cancelled(): self.from_cache = await self.query_cache(domain) logger.debug('[query_cache][%s][%s] %s', types.get_name(self.qtype), domain, self.from_cache) if self.from_cache: break if not self.future.cancelled(): remote_res = await self.query_remote(domain, nameservers) logger.debug('[query_remote][%s][%s] %s', types.get_name(self.qtype), domain, remote_res) if remote_res is None: break domain, nameservers = remote_res except Exception as e: error = e if not self.future.cancelled(): if error: self.future.set_exception(error) else: self.future.set_result((self._result, self.from_cache))
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)
def on_connection_error(self, exc): logger.debug('[connect_error] %s:%port', self.hostname or self.addr[0], self.addr[1]) self.size -= 1