commit 59c97a824be9ba8d09cff0f22f611ab3985f53a5 Author: aagbsn aagbsn@extc.org Date: Fri Jun 8 22:35:19 2012 -0700
5948 - Do not pick from or-addresses randomly
Pick the same bridge line each time; uses hmac_fn and email or ip from the request. --- lib/bridgedb/Bridges.py | 68 +++++++++++++++++++++++++---------------------- 1 files changed, 36 insertions(+), 32 deletions(-)
diff --git a/lib/bridgedb/Bridges.py b/lib/bridgedb/Bridges.py index 9af5dfb..4224fd7 100644 --- a/lib/bridgedb/Bridges.py +++ b/lib/bridgedb/Bridges.py @@ -141,40 +141,41 @@ class Bridge: return "Bridge(%r,%r,%d,%r)"%( self.nickname, self.ip, self.orport, self.fingerprint)
- def getConfigLine(self,includeFingerprint=False, - needIPv4=True, needIPv6=False): - """Return a line describing this bridge for inclusion in a torrc.""" - - # select an address:port from or-addresses - filtered_addresses = None - # bridges may have both classes. we only return one. - if needIPv6: - f = lambda x: type(x[0]) is ipaddr.IPv6Address - filtered_addresses = filter(f, self.or_addresses.items()) - elif needIPv4: - f = lambda x: type(x[0]) is ipaddr.IPv4Address - filtered_addresses = filter(f, self.or_addresses.items()) - # default ip, orport should get a chance at being selected - if type(ipaddr.IPAddress(self.ip)) is ipaddr.IPv4Address: - filtered_addresses.append((ipaddr.IPAddress(self.ip), set([int(self.orport)]))) - - if filtered_addresses: - address,portlist = random.choice(filtered_addresses) - if type(address) is ipaddr.IPv6Address: - ip = "[%s]"%address + def getConfigLine(self, includeFingerprint=False, addressClass=None, + request=None): + """Returns a valid bridge line for inclusion in a torrc""" + #arguments: + # includeFingerprint + # addressClass - type of address to choose + # request - a string unique to this request + # e.g. email-address or uniformMap(ip) + + if not request: request = 'default' + digest = get_hmac_fn('Order-Or-Addresses')(request) + pos = long(digest[:8], 16) # lower 8 bytes -> long + + # default address type + if not addressClass: addressClass = ipaddr.IPv4Address + + # filter addresses by address class + addresses = filter(lambda x: isinstance(x[0], addressClass), + self.or_addresses.items()) + + # default ip, orport should get a chance at being selected + if isinstance(self.ip, addressClass): + addresses.insert(0,self.ip, PortList(self.orport)) + + if addresses: + address,portlist = addresses[pos % len(addresses)] + if isinstance(address, ipaddr.IPv6Address): ip = "[%s]"%address + else: ip = "%s"%address + orport = portlist[pos % len(portlist)] + + if includeFingerprint: + return "bridge %s:%d %s" % (ip, orport, self.fingerprint) else: - ip = "%s"%address - orport = random.choice(list(portlist)) + return "bridge %s:%d" % (ip, orport)
- # default to ip,orport - else: - ip = self.ip - orport = self.orport - - if includeFingerprint: - return "bridge %s:%d %s" % (ip, orport, self.fingerprint) - else: - return "bridge %s:%d" % (ip, orport)
def getAllConfigLines(self,includeFingerprint=False): """Generator. Iterate over all valid config lines for this bridge.""" @@ -323,6 +324,9 @@ class PortList: def __len__(self): return len(self.ports)
+ def __getitem__(self, x): + return list(self.ports)[x] + class ParseORAddressError(Exception): def __init__(self): msg = "Invalid or-address line"
tor-commits@lists.torproject.org