-
Notifications
You must be signed in to change notification settings - Fork 0
/
resolver.py
76 lines (62 loc) · 2.41 KB
/
resolver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import threading
import logging
import dns
from dns import reversename, resolver
from queue import Queue
class DNSCache(object):
"""A simple DNS cache"""
def __init__(self):
self.cache = {}
self.queue = Queue()
def start(self):
logging.info('Starting DNSCache')
t = threading.Thread(target=self.resolve_queue_thread)
t.start()
def resolve_queue_thread(self):
logging.debug('Running resolve queue thread')
while True:
ip_address, cb = self.queue.get(True)
logging.debug('Received request to resolve {}'.format(ip_address))
rev_name = reversename.from_address(ip_address)
try:
hostname = str(resolver.query(rev_name, "PTR")[0])
self.cache[ip_address] = (hostname, 'resolved')
logging.debug('Done resolving! {} --> {}'.format(ip_address, hostname))
if cb:
cb(ip_address, hostname)
except resolver.NoNameservers:
self.cache[ip_address] = (None, 'bad')
if cb:
cb(ip_address, None)
except dns.resolver.Timeout:
self.cache[ip_address] = (None, 'bad')
if cb:
cb(ip_address, None)
except dns.resolver.NXDOMAIN:
self.cache[ip_address] = (None, 'bad')
if cb:
cb(ip_address, None)
def resolve(self, ip_address, cb=None):
"""Resolves an IP to an address. This either returns a hostname or
returns None and adds the IP address to the resolve queue."""
entry = self.cache.get(ip_address, None)
if not entry:
self.add_to_resolve_queue(ip_address, cb)
return None
if entry[1] == 'queued' or entry[1] == 'bad':
return None
else:
return entry[0]
def add_to_resolve_queue(self, ip_address, cb=None):
"""Adds an IP address to the queue to be resolved asynchronously.
Args:
ip_address - The IP to resolve
cb - Callback that will receive ip, hostname
"""
logging.debug('Adding {} to resolve queue'.format(ip_address))
self.cache[ip_address] = (None, 'queued')
self.queue.put((ip_address, cb))
if __name__ == '__main__':
cache = DNSCache()
cache.start()
cache.add_to_resolve_queue('8.8.8.8')