[or-cvs] r18693: {torctl} Finally track down an annoying bug that was causing us to tr (torctl/trunk/python/TorCtl)
mikeperry at seul.org
mikeperry at seul.org
Wed Feb 25 20:48:30 UTC 2009
Author: mikeperry
Date: 2009-02-25 15:48:30 -0500 (Wed, 25 Feb 2009)
New Revision: 18693
Modified:
torctl/trunk/python/TorCtl/PathSupport.py
torctl/trunk/python/TorCtl/TorCtl.py
Log:
Finally track down an annoying bug that was causing us to try
to use downed routers in soat.
Modified: torctl/trunk/python/TorCtl/PathSupport.py
===================================================================
--- torctl/trunk/python/TorCtl/PathSupport.py 2009-02-25 18:58:13 UTC (rev 18692)
+++ torctl/trunk/python/TorCtl/PathSupport.py 2009-02-25 20:48:30 UTC (rev 18693)
@@ -1059,10 +1059,16 @@
def set_exit(self, exit_name):
self._set_exit(exit_name)
self.exit_rstr.clear()
- if not self.exit_id or self.exit_id[1:] not in self.consensus.routers \
- or self.consensus.routers[self.exit_id[1:]].down:
- plog("NOTICE", "Requested downed exit "+str(self.exit_id))
+ if not exit_id:
+ plog("NOTICE", "Requested null exit "+str(exit_id))
self.bad_restrictions = True
+ elif exit_id[1:] not in self.consensus.routers:
+ plog("NOTICE", "Requested absent exit "+str(exit_id))
+ self.bad_restrictions = True
+ elif self.consensus.routers[exit_id[1:]].down:
+ e = self.consensus.routers[exit_id[1:]]
+ plog("NOTICE", "Requested downed exit "+str(exit_id)+" (bw: "+str(e.bw)+", flags: "+str(e.flags)+")")
+ self.bad_restrictions = True
else:
self.exit_rstr.add_restriction(IdHexRestriction(self.exit_id))
try:
Modified: torctl/trunk/python/TorCtl/TorCtl.py
===================================================================
--- torctl/trunk/python/TorCtl/TorCtl.py 2009-02-25 18:58:13 UTC (rev 18692)
+++ torctl/trunk/python/TorCtl/TorCtl.py 2009-02-25 20:48:30 UTC (rev 18693)
@@ -265,18 +265,20 @@
self.__dict__[i] = copy.deepcopy(args[0].__dict__[i])
return
else:
- (idhex, name, bw, down, exitpolicy, flags, ip, version, os, uptime) = args
+ (idhex, name, bw, down, exitpolicy, flags, ip, version, os, uptime, published) = args
self.idhex = idhex
self.nickname = name
self.bw = bw
self.exitpolicy = exitpolicy
- self.flags = flags
+ self.flags = flags # Technicaly from NS doc
self.down = down
self.ip = struct.unpack(">I", socket.inet_aton(ip))[0]
self.version = RouterVersion(version)
self.os = os
self.list_rank = 0 # position in a sorted list of routers.
self.uptime = uptime
+ m = re.search(r"(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)", published)
+ self.published = datetime.datetime(*map(int, m.groups()))
self.refcount = 0 # How many open circs are we currently in?
self.deleted = False # Has Tor already deleted this descriptor?
@@ -303,6 +305,7 @@
uptime = 0
ip = 0
router = "[none]"
+ published = "never"
for line in desc:
rt = re.search(r"^router (\S+) (\S+)", line)
@@ -312,6 +315,7 @@
rj = re.search(r"^reject (\S+):([^-]+)(?:-(\d+))?", line)
bw = re.search(r"^bandwidth (\d+) \d+ (\d+)", line)
up = re.search(r"^uptime (\d+)", line)
+ pb = re.search(r"^published (\S+ \S+)", line)
if re.search(r"^opt hibernating 1", line):
dead = True
if ("Running" in ns.flags):
@@ -328,6 +332,8 @@
uptime = int(up.group(1))
elif rt:
router,ip = rt.groups()
+ elif pb:
+ published = pb.group(1)
if router != ns.nickname:
plog("NOTICE", "Got different names " + ns.nickname + " vs " +
router + " for " + ns.idhex)
@@ -337,7 +343,7 @@
if not version or not os:
plog("INFO", "No version and/or OS for router " + ns.nickname)
return Router(ns.idhex, ns.nickname, bw_observed, dead, exitpolicy,
- ns.flags, ip, version, os, uptime)
+ ns.flags, ip, version, os, uptime, published)
build_from_desc = Callable(build_from_desc)
def update_to(self, new):
@@ -558,7 +564,7 @@
raise TorCtlClosed()
line = line.strip()
if self._debugFile:
- self._debugFile.write(" %s\n" % line)
+ self._debugFile.write(str(time.time())+"\t %s\n" % line)
if len(line)<4:
raise ProtocolError("Badly formatted reply line: Too short")
code = line[:3]
@@ -595,7 +601,7 @@
lines = amsg.split("\n")
if len(lines) > 2:
amsg = "\n".join(lines[:2]) + "\n"
- self._debugFile.write(str(time.time())+">>> "+amsg)
+ self._debugFile.write(str(time.time())+"\t>>> "+amsg)
self._s.write(msg)
def sendAndRecv(self, msg="", expectedTypes=("250", "251")):
@@ -708,11 +714,12 @@
desc = self.sendAndRecv("GETINFO desc/id/" + ns.idhex + "\r\n")[0][2]
sig_start = desc.find("\nrouter-signature\n")+len("\nrouter-signature\n")
fp_base64 = sha.sha(desc[:sig_start]).digest().encode("base64")[:-2]
+ r = Router.build_from_desc(desc.split("\n"), ns)
if fp_base64 != ns.orhash:
- plog("NOTICE", "Router descriptor for "+ns.idhex+" does not match ns fingerprint ("+ns.orhash+" vs "+fp_base64+")")
+ plog("NOTICE", "Router descriptor for "+ns.idhex+" does not match ns fingerprint (NS @ "+str(ns.updated)+" vs Desc @ "+str(r.published)+")")
return None
else:
- return Router.build_from_desc(desc.split("\n"), ns)
+ return r
def read_routers(self, nslist):
@@ -1100,11 +1107,18 @@
self.update_consensus()
def _read_routers(self, nslist):
+ # Routers can fall out of our consensus five different ways:
+ # 1. Their descriptors disappear
+ # 2. Their NS documents disappear
+ # 3. They lose the Running flag
+ # 4. They list a bandwidth of 0
+ # 5. They have 'opt hibernating' set
+ routers = self.c.read_routers(nslist) # Sets .down if 3,4,5
old_idhexes = sets.Set(self.routers.keys())
- new_idhexes = sets.Set(map(lambda ns: ns.idhex, nslist))
+ new_idhexes = sets.Set(map(lambda r: r.idhex, routers))
removed_idhexes = old_idhexes - new_idhexes
- removed_idhexes.union_update(sets.Set(map(lambda ns: ns.idhex,
- filter(lambda ns: "Running" not in ns.flags, nslist))))
+ removed_idhexes.union_update(sets.Set(map(lambda r: r.idhex,
+ filter(lambda r: r.down, routers))))
for i in removed_idhexes:
if i not in self.routers: continue
@@ -1119,7 +1133,6 @@
plog("INFO", "Postponing expiring non-running router "+i)
self.routers[i].deleted = True
- routers = self.c.read_routers(nslist)
for r in routers:
self.name_to_key[r.nickname] = "$"+r.idhex
if r.idhex in self.routers:
More information about the tor-commits
mailing list