Browse Source

Start working on EXTEND/EXTENDED cells

Ian Goldberg 6 years ago
parent
commit
01f3ab560a
2 changed files with 50 additions and 23 deletions
  1. 31 21
      client.py
  2. 19 2
      relay.py

+ 31 - 21
client.py

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

+ 19 - 2
relay.py

@@ -55,6 +55,23 @@ class VanillaCreatedCircuitMsg(RelayNetMsg):
         self.ntor_reply = ntor_reply
 
 
+class VanillaExtendCircuitMsg(RelayNetMsg):
+    """The message for requesting circuit creation in Vanilla Onion
+    Routing."""
+
+    def __init__(self, hopaddr, ntor_request):
+        self.hopaddr = hopaddr
+        self.ntor_request = ntor_request
+
+
+class VanillaExtendedCircuitMsg(RelayNetMsg):
+    """The message for responding to circuit creation in Vanilla Onion
+    Routing."""
+
+    def __init__(self, ntor_reply):
+        self.ntor_reply = ntor_reply
+
+
 class CircuitCellMsg(RelayNetMsg):
     """Send a message tagged with a circuit id."""
 
@@ -197,12 +214,12 @@ class CircuitHandler:
         if isinstance(cell, EncryptedMsg):
             cell = self.crypt_layer.decrypt_msg(cell)
 
+        print("CircuitHandler: %s received cell %s on circuit %d from %s" % (self.channel.cellhandler.myaddr, cell, self.circid, self.channel.peer.cellhandler.myaddr))
+
         celltype = type(cell)
         if celltype in self.cell_dispatch_table:
             self.cell_dispatch_table[celltype].received_cell(self, cell)
 
-        print("CircuitHandler: %s received cell %s on circuit %d from %s" % (self.channel.cellhandler.myaddr, cell, self.circid, self.channel.peer.cellhandler.myaddr))
-
     def add_crypt_layer(self, enckey, deckey):
         """Add a processing layer to this CircuitHandler so that cells
         we send will get encrypted with the first given key, and cells