|
@ -32,7 +32,7 @@ import lru_cache |
|
|
import eventloop |
|
|
import eventloop |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CACHE_SWEEP_INTERVAL = 10 |
|
|
CACHE_SWEEP_INTERVAL = 30 |
|
|
|
|
|
|
|
|
VALID_HOSTNAME = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE) |
|
|
VALID_HOSTNAME = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE) |
|
|
|
|
|
|
|
@ -267,21 +267,18 @@ class DNSResolver(object): |
|
|
self._hosts = {} |
|
|
self._hosts = {} |
|
|
self._hostname_status = {} |
|
|
self._hostname_status = {} |
|
|
self._hostname_to_cb = {} |
|
|
self._hostname_to_cb = {} |
|
|
self._cb_to_hostname = lru_cache.LRUCache(timeout=15, |
|
|
self._cb_to_hostname = {} |
|
|
close_callback=self._timedout) |
|
|
|
|
|
self._cache = lru_cache.LRUCache(timeout=300) |
|
|
self._cache = lru_cache.LRUCache(timeout=300) |
|
|
self._last_time = time.time() |
|
|
self._last_time = time.time() |
|
|
self._sock = None |
|
|
self._sock = None |
|
|
self._servers = None |
|
|
self._servers = None |
|
|
self._server_index = 0 |
|
|
|
|
|
self._parse_resolv() |
|
|
self._parse_resolv() |
|
|
self._parse_hosts() |
|
|
self._parse_hosts() |
|
|
# TODO monitor hosts change and reload hosts |
|
|
# TODO monitor hosts change and reload hosts |
|
|
# TODO parse /etc/gai.conf and follow its rules |
|
|
# TODO parse /etc/gai.conf and follow its rules |
|
|
|
|
|
|
|
|
def _parse_resolv(self): |
|
|
def _parse_resolv(self): |
|
|
servers = [] |
|
|
self._servers = [] |
|
|
self._servers = servers |
|
|
|
|
|
try: |
|
|
try: |
|
|
with open('/etc/resolv.conf', 'rb') as f: |
|
|
with open('/etc/resolv.conf', 'rb') as f: |
|
|
content = f.readlines() |
|
|
content = f.readlines() |
|
@ -293,22 +290,11 @@ class DNSResolver(object): |
|
|
if len(parts) >= 2: |
|
|
if len(parts) >= 2: |
|
|
server = parts[1] |
|
|
server = parts[1] |
|
|
if is_ip(server): |
|
|
if is_ip(server): |
|
|
servers.append(server) |
|
|
self._servers.append(server) |
|
|
# TODO support more servers |
|
|
|
|
|
|
|
|
|
|
|
except IOError: |
|
|
except IOError: |
|
|
pass |
|
|
pass |
|
|
if not servers: |
|
|
if not self._servers: |
|
|
servers.append('8.8.8.8') |
|
|
self._servers = ['8.8.4.4', '8.8.8.8'] |
|
|
self._dns_server = (servers[0], 53) |
|
|
|
|
|
|
|
|
|
|
|
def _timedout(self, hostname): |
|
|
|
|
|
error = Exception('timed out when resolving %s with DNS %s' % |
|
|
|
|
|
(hostname, self._dns_server)) |
|
|
|
|
|
self._server_index += 1 |
|
|
|
|
|
self._server_index %= len(self._servers) |
|
|
|
|
|
self._dns_server = (self._servers[self._server_index], 53) |
|
|
|
|
|
self._call_callback(hostname, None, error=error) |
|
|
|
|
|
|
|
|
|
|
|
def _parse_hosts(self): |
|
|
def _parse_hosts(self): |
|
|
etc_path = '/etc/hosts' |
|
|
etc_path = '/etc/hosts' |
|
@ -389,7 +375,7 @@ class DNSResolver(object): |
|
|
self._loop.add(self._sock, eventloop.POLL_IN) |
|
|
self._loop.add(self._sock, eventloop.POLL_IN) |
|
|
else: |
|
|
else: |
|
|
data, addr = sock.recvfrom(1024) |
|
|
data, addr = sock.recvfrom(1024) |
|
|
if addr != self._dns_server: |
|
|
if addr[0] not in self._servers: |
|
|
logging.warn('received a packet other than our dns') |
|
|
logging.warn('received a packet other than our dns') |
|
|
break |
|
|
break |
|
|
self._handle_data(data) |
|
|
self._handle_data(data) |
|
@ -397,7 +383,6 @@ class DNSResolver(object): |
|
|
now = time.time() |
|
|
now = time.time() |
|
|
if now - self._last_time > CACHE_SWEEP_INTERVAL: |
|
|
if now - self._last_time > CACHE_SWEEP_INTERVAL: |
|
|
self._cache.sweep() |
|
|
self._cache.sweep() |
|
|
self._cb_to_hostname.sweep() |
|
|
|
|
|
self._last_time = now |
|
|
self._last_time = now |
|
|
|
|
|
|
|
|
def remove_callback(self, callback): |
|
|
def remove_callback(self, callback): |
|
@ -413,13 +398,14 @@ class DNSResolver(object): |
|
|
del self._hostname_status[hostname] |
|
|
del self._hostname_status[hostname] |
|
|
|
|
|
|
|
|
def _send_req(self, hostname, qtype): |
|
|
def _send_req(self, hostname, qtype): |
|
|
logging.debug('resolving %s with type %d using server %s', hostname, |
|
|
|
|
|
qtype, self._dns_server) |
|
|
|
|
|
self._request_id += 1 |
|
|
self._request_id += 1 |
|
|
if self._request_id > 32768: |
|
|
if self._request_id > 32768: |
|
|
self._request_id = 1 |
|
|
self._request_id = 1 |
|
|
req = build_request(hostname, qtype, self._request_id) |
|
|
req = build_request(hostname, qtype, self._request_id) |
|
|
self._sock.sendto(req, self._dns_server) |
|
|
for server in self._servers: |
|
|
|
|
|
logging.debug('resolving %s with type %d using server %s', hostname, |
|
|
|
|
|
qtype, server) |
|
|
|
|
|
self._sock.sendto(req, (server, 53)) |
|
|
|
|
|
|
|
|
def resolve(self, hostname, callback): |
|
|
def resolve(self, hostname, callback): |
|
|
if not hostname: |
|
|
if not hostname: |
|
|