r13077@catbus: nickm | 2007-05-29 16:52:46 -0400

Make exitlist script handle multiple descriptors for one router (by only looking at the latest).  Resolves bug 405.


svn:r10402
This commit is contained in:
Nick Mathewson 2007-05-29 20:52:56 +00:00
parent 4cd93bd9ec
commit 77c3dab7df
2 changed files with 46 additions and 8 deletions

View File

@ -159,6 +159,11 @@ Changes in version 0.2.0.1-alpha - 2007-??-??
- Make the NodeFamilies config option work. (Reported by
lodger -- it has never actually worked, even though we added it
in Oct 2004.)
- In the exitlist script, only consider the most recently published
server descriptor for each server. Also, when the user requests
a list of servers that _reject_ connections to a given address,
explicitly exclude the IPs that also have servers that accept
connections to that address. (Resolves bug 405.)
o Minor bugfixes (controller):
- Make 'getinfo fingerprint' return a 551 error if we're not a

View File

@ -58,6 +58,7 @@ import re
import getopt
import socket
import struct
import time
assert sys.version_info >= (2,2)
@ -196,10 +197,12 @@ class Policy:
return True
class Server:
def __init__(self, name, ip, policy):
def __init__(self, name, ip, policy, published, fingerprint):
self.name = name
self.ip = ip
self.policy = policy
self.published = published
self.fingerprint = fingerprint
def uniq_sort(lst):
d = {}
@ -235,17 +238,34 @@ usage: cat ~/.tor/cached-routers* | %s [-v] [-x] [host:port [host:port [...]]]
servers = []
policy = []
name = ip = None
published = 0
fp = ""
for line in sys.stdin.xreadlines():
if line.startswith('router '):
if name:
servers.append(Server(name, ip, Policy.parseLines(policy)))
servers.append(Server(name, ip, Policy.parseLines(policy),
published, fp))
_, name, ip, rest = line.split(" ", 3)
policy = []
published = 0
fp = ""
elif line.startswith('fingerprint') or \
line.startswith('opt fingerprint'):
elts = line.strip().split()
if elts[0] == 'opt': del elts[0]
assert elts[0] == 'fingerprint'
del elts[0]
fp = "".join(elts)
elif line.startswith('accept ') or line.startswith('reject '):
policy.append(line.strip())
elif line.startswith('published '):
date = time.strptime(line[len('published '):].strip(),
"%Y-%m-%d %H:%M:%S")
published = time.mktime(date)
if name:
servers.append(Server(name, ip, Policy.parseLines(policy)))
servers.append(Server(name, ip, Policy.parseLines(policy), published,
fp))
targets = []
for line in ADDRESSES_OF_INTEREST.split("\n"):
@ -254,19 +274,32 @@ usage: cat ~/.tor/cached-routers* | %s [-v] [-x] [host:port [host:port [...]]]
p = Pattern.parse(line)
targets.append((p.ip, p.portMin))
accepters, rejecters = [], []
# remove all but the latest server of each IP/Nickname pair.
latest = {}
for s in servers:
if (not latest.has_key((s.fingerprint))
or s.published > latest[(s.fingerprint)]):
latest[s.fingerprint] = s
servers = latest.values()
accepters, rejecters = {}, {}
for s in servers:
for ip,port in targets:
if s.policy.accepts(ip,port):
accepters.append(s)
accepters[s.ip] = s
break
else:
rejecters.append(s)
rejecters[s.ip] = s
# If any server at IP foo accepts, the IP does not reject.
for k in accepters.keys():
if rejecters.has_key(k):
del rejecters[k]
if INVERSE:
printlist = rejecters
printlist = rejecters.values()
else:
printlist = accepters
printlist = accepters.values()
ents = []
if VERBOSE: