Browse Source

update dns

auth
clowwindy 10 years ago
parent
commit
cdd333ea97
  1. 42
      shadowsocks/asyncdns.py

42
shadowsocks/asyncdns.py

@ -22,6 +22,7 @@
# SOFTWARE. # SOFTWARE.
import time import time
import os
import socket import socket
import struct import struct
import logging import logging
@ -173,7 +174,7 @@ def parse_response(data):
# res_ra = header[2] & 128 # res_ra = header[2] & 128
res_rcode = header[2] & 15 res_rcode = header[2] & 15
assert res_tc == 0 assert res_tc == 0
assert res_rcode == 0 assert res_rcode in [0, 3]
res_qdcount = header[3] res_qdcount = header[3]
res_ancount = header[4] res_ancount = header[4]
res_nscount = header[5] res_nscount = header[5]
@ -238,15 +239,19 @@ class DNSResolver(object):
def __init__(self): def __init__(self):
self._loop = None self._loop = None
self._request_id = 1 self._request_id = 1
self._hosts = {}
self._hostname_status = {} self._hostname_status = {}
self._hostname_to_cb = {} self._hostname_to_cb = {}
self._cb_to_hostname = {} self._cb_to_hostname = {}
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._parse_config() self._parse_resolv()
self._parse_hosts()
# TODO monitor hosts change and reload hosts
# TODO parse /etc/gai.conf and follow its rules
def _parse_config(self): def _parse_resolv(self):
try: try:
with open('/etc/resolv.conf', 'rb') as f: with open('/etc/resolv.conf', 'rb') as f:
servers = [] servers = []
@ -255,7 +260,7 @@ class DNSResolver(object):
line = line.strip() line = line.strip()
if line: if line:
if line.startswith('nameserver'): if line.startswith('nameserver'):
parts = line.split(' ') parts = line.split()
if len(parts) >= 2: if len(parts) >= 2:
server = parts[1] server = parts[1]
if is_ip(server): if is_ip(server):
@ -268,6 +273,25 @@ class DNSResolver(object):
pass pass
self._dns_server = ('8.8.8.8', 53) self._dns_server = ('8.8.8.8', 53)
def _parse_hosts(self):
etc_path = '/etc/hosts'
if os.environ.__contains__('WINDIR'):
etc_path = os.environ['WINDIR'] + '/system32/drivers/etc/hosts'
try:
with open(etc_path, 'rb') as f:
for line in f.readlines():
line = line.strip()
parts = line.split()
if len(parts) >= 2:
ip = parts[0]
if is_ip(ip):
for i in xrange(1, len(parts)):
hostname = parts[i]
if hostname:
self._hosts[hostname] = ip
except IOError:
self._hosts['localhost'] = '127.0.0.1'
def add_to_loop(self, loop): def add_to_loop(self, loop):
if self._loop: if self._loop:
raise Exception('already add to loop') raise Exception('already add to loop')
@ -356,11 +380,15 @@ class DNSResolver(object):
if not hostname: if not hostname:
callback(None, Exception('empty hostname')) callback(None, Exception('empty hostname'))
elif is_ip(hostname): elif is_ip(hostname):
callback(hostname, None) callback((hostname, hostname), None)
elif self._hosts.__contains__(hostname):
logging.debug('hit hosts: %s', hostname)
ip = self._hosts[hostname]
callback((hostname, ip), None)
elif self._cache.__contains__(hostname): elif self._cache.__contains__(hostname):
logging.debug('hit cache: %s', hostname) logging.debug('hit cache: %s', hostname)
ip = self._cache[hostname] ip = self._cache[hostname]
callback(ip, None) callback((hostname, ip), None)
else: else:
arr = self._hostname_to_cb.get(hostname, None) arr = self._hostname_to_cb.get(hostname, None)
if not arr: if not arr:
@ -390,6 +418,8 @@ def test():
for hostname in ['www.google.com', for hostname in ['www.google.com',
'8.8.8.8', '8.8.8.8',
'localhost',
'activate.adobe.com',
'www.twitter.com', 'www.twitter.com',
'ipv6.google.com', 'ipv6.google.com',
'ipv6.l.google.com', 'ipv6.l.google.com',

Loading…
Cancel
Save