Skip to content

Commit

Permalink
Avoid waiting on DNS for more than 2 seconds to display the list of
Browse files Browse the repository at this point in the history
nearby servers.  Use the IP address if no name arrives within that time.
We can't interrupt the requests, though, so we cache them, and if an
answer arrives after more than 2 seconds it will be used as soon as the
user reloads the page.
  • Loading branch information
arigo committed Nov 15, 2006
1 parent 861cda4 commit 4ebce5f
Showing 1 changed file with 53 additions and 15 deletions.
68 changes: 53 additions & 15 deletions common/hostchooser.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,8 @@ def find_servers(hostlist=[('127.0.0.1', None), ('<broadcast>', None)],
for host, udpport in hostlist:
print >> sys.stderr, ' %s, UDP port %s' % (
host, udpport or ("%s (default)" % UDP_PORT))
servers = {}
events = {}
aliases = {}
replies = []
s = socket(AF_INET, SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
for trynum in range(tries):
Expand Down Expand Up @@ -120,27 +119,41 @@ def find_servers(hostlist=[('127.0.0.1', None), ('<broadcast>', None)],
hostrecv.append(time.time())
data = data.split(':')
if len(data) >= 4 and data[0] == PONG_MESSAGE:
if data[2]:
hostname = data[2]
else:
hostname = answer_from[0]
try:
hostname = gethostbyaddr(hostname)[0]
if hostname == 'localhost':
from msgstruct import HOSTNAME as hostname
except error:
pass
try:
port = int(data[3])
except ValueError:
if port_needed:
continue
port = ''
result = (hostname, port)
servers[result] = ':'.join(data[1:2]+data[4:])
aliases[hostname] = ipaddr
if data[2]:
hostname = data[2]
realhostname = [hostname]
else:
hostname = answer_from[0]
realhostname = lazy_gethostbyaddr(hostname)
server = ':'.join(data[1:2]+data[4:])
replies.append((hostname, realhostname, port, server, ipaddr))
else:
print >> sys.stderr, "got an unexpected answer from", answer_from
servers = {}
aliases = {}
timeout = time.time() + 2.0 # wait for gethostbyaddr() for 2 seconds
while replies:
i = 0
now = time.time()
while i < len(replies):
hostname, realhostname, port, server, ipaddr = replies[i]
if realhostname:
hostname = realhostname[0] # got an answer
elif now < timeout:
i += 1 # must wait some more time
continue
result = (hostname, port)
servers[result] = server
aliases[hostname] = ipaddr
del replies[i]
if replies:
time.sleep(0.08) # time for gethostbyaddr() to finish
if verbose:
print >> sys.stderr, "%d answer(s):" % len(servers), servers.keys()
for host, port in servers.keys():
Expand All @@ -151,4 +164,29 @@ def find_servers(hostlist=[('127.0.0.1', None), ('<broadcast>', None)],
if len(hostsend) == len(hostrecv) == tries:
ping = min([t2-t1 for t1, t2 in zip(hostsend, hostrecv)])
servers[host, port] = (servers[host, port], ping)
sys.setcheckinterval(4096)
return servers

# ____________________________________________________________

HOSTNAMECACHE = {}

def _lazygetter(hostname, resultlst):
try:
try:
hostname = gethostbyaddr(hostname)[0]
if hostname == 'localhost':
from msgstruct import HOSTNAME as hostname
except error:
pass
finally:
resultlst.append(hostname)

def lazy_gethostbyaddr(hostname):
try:
return HOSTNAMECACHE[hostname]
except KeyError:
resultlst = HOSTNAMECACHE[hostname] = []
import thread
thread.start_new_thread(_lazygetter, (hostname, resultlst))
return resultlst

0 comments on commit 4ebce5f

Please sign in to comment.