Explorar o código

Start on the generic infrastructure to create circuits within channels

Ian Goldberg %!s(int64=4) %!d(string=hai) anos
pai
achega
859cf02da1
Modificáronse 2 ficheiros con 74 adicións e 14 borrados
  1. 13 2
      client.py
  2. 61 12
      relay.py

+ 13 - 2
client.py

@@ -13,7 +13,8 @@ class CellClient(relay.CellHandler):
     def __init__(self, myaddr, dirauthaddrs):
         super().__init__(myaddr, dirauthaddrs)
         self.guardaddr = None
-        self.consensus_cdf = [0]
+        if network.thenetwork.womode == network.WOMode.VANILLA:
+            self.consensus_cdf = []
 
     def get_consensus_from_fallbackrelay(self):
         """Download a fresh consensus from a random fallbackrelay."""
@@ -46,6 +47,15 @@ class CellClient(relay.CellHandler):
         if network.thenetwork.womode == network.WOMode.VANILLA:
             self.ensure_guard_vanilla()
 
+    def create_circuit_vanilla(self):
+        """Create a new circuit from this client. (Vanilla Onion Routing
+        version)"""
+
+    def create_circuit(self):
+        """Create a new circuit from this client."""
+        if network.thenetwork.womode == network.WOMode.VANILLA:
+            self.create_circuit_vanilla()
+
     def received_msg(self, msg, peeraddr, peer):
         """Callback when a NetMsg not specific to a circuit is
         received."""
@@ -53,7 +63,8 @@ class CellClient(relay.CellHandler):
         if isinstance(msg, relay.RelayConsensusMsg):
             self.consensus = msg.consensus
             dirauth.Consensus.verify(self.consensus, network.thenetwork.dirauthkeys())
-            self.consensus_cdf = self.consensus.bw_cdf()
+            if network.thenetwork.womode == network.WOMode.VANILLA:
+                self.consensus_cdf = self.consensus.bw_cdf()
         else:
             return super().received_msg(msg, peeraddr, peer)
 

+ 61 - 12
relay.py

@@ -52,6 +52,26 @@ class RelayFallbackTerminationError(Exception):
     relay."""
 
 
+class CircuitHandler:
+    """A class for managing sending and receiving encrypted cells on a
+    particular circuit."""
+
+    def __init__(self, channel, circid):
+        self.channel = channel
+        self.circid = circid
+        self.send_cell = self.channel_send_cell
+        self.received_cell = self.channel_received_cell
+
+    def channel_send_cell(self, cell):
+        """Send a cell on this circuit."""
+        self.channel.send_msg(CircuitCellMsg(self.circid, cell))
+
+    def channel_received_cell(self, cell, peeraddr, peer):
+        """A cell has been received on this circuit.  Forward it to the
+        channel's received_cell callback."""
+        self.channel.cellhandler.received_cell(self.circid, cell, peeraddr, peer)
+
+
 class Channel(network.Connection):
     """A class representing a channel between a relay and either a
     client or a relay, transporting cells from various circuits."""
@@ -63,6 +83,13 @@ class Channel(network.Connection):
         self.peer = None
         # The function to call when the connection closes
         self.closer = lambda: 0
+        # The next circuit id to use on this channel.  The party that
+        # opened the channel uses even numbers; the receiving party uses
+        # odd numbers.
+        self.next_circid = None
+        # A map for CircuitHandlers to use for each open circuit on the
+        # channel
+        self.circuithandlers = dict()
 
     def closed(self):
         self.closer()
@@ -73,10 +100,28 @@ class Channel(network.Connection):
             self.peer.closed()
         self.closed()
 
+    def new_circuit(self):
+        """Allocate a new circuit on this channel, returning the new
+        circuit's id."""
+        circid = self.next_circid
+        self.next_circid += 2
+        self.circuithandlers[circid] = CircuitHandler(self, circid)
+        return circid
+
+    def new_circuit_with_circid(self, circid):
+        """Allocate a new circuit on this channel, with the circuit id
+        received from our peer."""
+        self.circuithandlers[circid] = CircuitHandler(self, circid)
+
     def send_cell(self, circid, cell):
-        """Send the given message, tagged for the given circuit id."""
-        msg = CircuitCellMsg(circid, cell)
-        self.send_msg(msg)
+        """Send the given message on the given circuit, encrypting or
+        decrypting as needed."""
+        self.circuithandlers[circid].send_cell(cell)
+
+    def send_raw_cell(self, circid, cell):
+        """Send the given message, tagged for the given circuit id. No
+        encryption or decryption is done."""
+        self.send_msg(CircuitCellMsg(self.circid, self.cell))
 
     def send_msg(self, msg):
         """Send the given NetMsg on the channel."""
@@ -86,7 +131,7 @@ class Channel(network.Connection):
         """Callback when a message is received from the network."""
         if isinstance(msg, CircuitCellMsg):
             circid, cell = msg.circid, msg.cell
-            self.cellhandler.received_cell(circid, cell, peeraddr, self.peer)
+            self.circuithandlers[circid].received_cell(cell, peeraddr, self.peer)
         else:
             self.cellhandler.received_msg(msg, peeraddr, self.peer)
 
@@ -140,11 +185,11 @@ class CellHandler:
     def received_msg(self, msg, peeraddr, peer):
         """Callback when a NetMsg not specific to a circuit is
         received."""
-        print("Node %s received msg %s from %s" % (self.myaddr, msg, peeraddr))
+        print("CellHandler: Node %s received msg %s from %s" % (self.myaddr, msg, peeraddr))
 
     def received_cell(self, circid, cell, peeraddr, peer):
         """Callback with a circuit-specific cell is received."""
-        print("Node %s received cell on circ %d: %s from %s" % (self.myaddr, circid, cell, peeraddr))
+        print("CellHandler: Node %s received cell on circ %d: %s from %s" % (self.myaddr, circid, cell, peeraddr))
 
     def send_msg(self, msg, peeraddr):
         """Send a message to the peer with the given address."""
@@ -175,7 +220,7 @@ class CellRelay(CellHandler):
     def received_msg(self, msg, peeraddr, peer):
         """Callback when a NetMsg not specific to a circuit is
         received."""
-        print("Node %s received msg %s from %s" % (self.myaddr, msg, peeraddr))
+        print("CellRelay: Node %s received msg %s from %s" % (self.myaddr, msg, peeraddr))
         if isinstance(msg, RelayRandomHopMsg):
             if msg.ttl > 0:
                 # Pick a random next hop from the consensus
@@ -189,7 +234,7 @@ class CellRelay(CellHandler):
 
     def received_cell(self, circid, cell, peeraddr, peer):
         """Callback with a circuit-specific cell is received."""
-        print("Node %s received cell on circ %d: %s from %s" % (self.myaddr, circid, cell, peeraddr))
+        print("CellRelay: Node %s received cell on circ %d: %s from %s" % (self.myaddr, circid, cell, peeraddr))
         return super().received_cell(circid, cell, peeraddr, peer)
 
 
@@ -294,12 +339,15 @@ class Relay(network.Server):
             # A self-loop?  We'll allow it.
             peerchannel = Channel()
             peerchannel.peer = peerchannel
+            peerchannel.next_circid = 2
             return peerchannel
 
         peerchannel = Channel()
         ourchannel = Channel()
         peerchannel.peer = ourchannel
+        peerchannel.next_circid = 2
         ourchannel.peer = peerchannel
+        ourchannel.next_circid = 1
 
         # Add our channel to the CellRelay
         self.cellhandler.add_channel(ourchannel, peer)
@@ -378,7 +426,8 @@ if __name__ == '__main__':
             if ch.peer.cellhandler.channels[raddr].peer is not ch:
                 print('asymmetry:', raddr, ad, ch, ch.peer.cellhandler.channels[raddr].peer)
 
-    #relays[3].cellhandler.send_cell(1, network.StringNetMsg("test"), relays[3].consensus.consdict['relays'][5].descdict['addr'])
-    #relays[3].cellhandler.send_cell(2, network.StringNetMsg("cell"), relays[3].consensus.consdict['relays'][6].descdict['addr'])
-    #relays[3].cellhandler.send_cell(2, network.StringNetMsg("again"), relays[3].consensus.consdict['relays'][1].descdict['addr'])
-    #relays[3].cellhandler.send_cell(2, network.StringNetMsg("and again"), relays[3].consensus.consdict['relays'][5].descdict['addr'])
+    channel = relays[3].cellhandler.get_channel_to(relays[5].netaddr)
+    circid = channel.new_circuit()
+    peerchannel = relays[5].cellhandler.get_channel_to(relays[3].netaddr)
+    peerchannel.new_circuit_with_circid(circid)
+    relays[3].cellhandler.send_cell(circid, network.StringNetMsg("test"), relays[5].netaddr)