|
|
@@ -9,10 +9,12 @@ import relay
|
|
|
|
|
|
import nacl.hash
|
|
|
|
|
|
-class CreatedHandler:
|
|
|
- """A handler for VanillaCreatedCircuitMsg cells."""
|
|
|
+class VanillaCreatedExtendedHandler:
|
|
|
+ """A handler for VanillaCreatedCircuitMsg and
|
|
|
+ VanillaExtendedCircuitMsg cells."""
|
|
|
|
|
|
- def __init__(self, ntor, expecteddesc):
|
|
|
+ def __init__(self, cellhandler, ntor, expecteddesc):
|
|
|
+ self.cellhandler = cellhandler
|
|
|
self.ntor = ntor
|
|
|
self.expecteddesc = expecteddesc
|
|
|
self.onionkey = expecteddesc.descdict['onionkey']
|
|
|
@@ -23,14 +25,38 @@ class CreatedHandler:
|
|
|
enckey = nacl.hash.sha256(secret + b'upstream')
|
|
|
deckey = nacl.hash.sha256(secret + b'downstream')
|
|
|
circhandler.add_crypt_layer(enckey, deckey)
|
|
|
+ if len(circhandler.circuit_descs) == 0:
|
|
|
+ # This was a VanillaCreatedCircuitMsg
|
|
|
+ del circhandler.cell_dispatch_table[relay.VanillaCreatedCircuitMsg]
|
|
|
+ else:
|
|
|
+ # This was a VanillaExtendedCircuitMsg
|
|
|
+ del circhandler.cell_dispatch_table[relay.VanillaExtendedCircuitMsg]
|
|
|
circhandler.circuit_descs.append(self.expecteddesc)
|
|
|
|
|
|
# Are we done building the circuit?
|
|
|
if len(circhandler.circuit_descs) == 3:
|
|
|
# Yes!
|
|
|
- del circhandler.cell_dispatch_table[relay.VanillaCreatedCircuitMsg]
|
|
|
return
|
|
|
|
|
|
+ nexthop = None
|
|
|
+ while nexthop is None:
|
|
|
+ nexthop = self.cellhandler.consensus.select_weighted_relay( \
|
|
|
+ self.cellhandler.consensus_cdf)
|
|
|
+ if nexthop.descdict['addr'] in circhandler.circuit_descs:
|
|
|
+ nexthop = None
|
|
|
+
|
|
|
+ # Construct the VanillaExtendCircuitMsg cell
|
|
|
+ ntor = relay.NTor(self.cellhandler.perfstats)
|
|
|
+ ntor_request = ntor.request()
|
|
|
+ circextendmsg = relay.VanillaExtendCircuitMsg( \
|
|
|
+ nexthop.descdict['addr'], ntor_request)
|
|
|
+
|
|
|
+ # Set up the reply handler
|
|
|
+ circhandler.cell_dispatch_table[relay.VanillaExtendedCircuitMsg] = \
|
|
|
+ VanillaCreatedExtendedHandler(self, ntor, nexthop)
|
|
|
+
|
|
|
+ # Send the cell
|
|
|
+ circhandler.send_cell(circextendmsg)
|
|
|
|
|
|
|
|
|
class CellClient(relay.CellHandler):
|
|
|
@@ -92,27 +118,11 @@ class CellClient(relay.CellHandler):
|
|
|
|
|
|
# Set up the reply handler
|
|
|
circhandler.cell_dispatch_table[relay.VanillaCreatedCircuitMsg] = \
|
|
|
- CreatedHandler(ntor, self.guard)
|
|
|
+ VanillaCreatedExtendedHandler(self, ntor, self.guard)
|
|
|
|
|
|
# Send the message
|
|
|
guardchannel.send_msg(circcreatemsg)
|
|
|
|
|
|
- # We have a guard already at this point, so choose a middle and
|
|
|
- # an exit. They must all be different.
|
|
|
- middle = None
|
|
|
- while middle is None:
|
|
|
- middle = self.consensus.select_weighted_relay(self.consensus_cdf)
|
|
|
- if middle.descdict['addr'] == self.guardaddr:
|
|
|
- middle = None
|
|
|
-
|
|
|
- exit = None
|
|
|
- while exit is None:
|
|
|
- exit = self.consensus.select_weighted_relay(self.consensus_cdf)
|
|
|
- if exit.descdict['addr'] == self.guardaddr or \
|
|
|
- exit.descdict['addr'] == middle.descdict['addr']:
|
|
|
- middle = None
|
|
|
-
|
|
|
-
|
|
|
def new_circuit(self):
|
|
|
"""Create a new circuit from this client."""
|
|
|
if network.thenetwork.womode == network.WOMode.VANILLA:
|