瀏覽代碼

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

Nick Mathewson 17 年之前
父節點
當前提交
77c3dab7df
共有 2 個文件被更改,包括 46 次插入8 次删除
  1. 5 0
      ChangeLog
  2. 41 8
      contrib/exitlist

+ 5 - 0
ChangeLog

@@ -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

+ 41 - 8
contrib/exitlist

@@ -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: