|
@@ -67,6 +67,16 @@ class StringCell(RelayCell):
|
|
return self.data.__str__()
|
|
return self.data.__str__()
|
|
|
|
|
|
|
|
|
|
|
|
+class CloseCell(RelayCell):
|
|
|
|
+ """Close the circuit this cell was sent on. It should be sent
|
|
|
|
+ _unencrypted_ (not within an EncryptedCell), and relays that receive
|
|
|
|
+ one should forward it along the adjacent circuit, then close both
|
|
|
|
+ the circuit it was received on and the adjacent one."""
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+# It is intentional that VanillaCreateCircuitMsg is a RelayNetMsg and
|
|
|
|
+# not a RelayCell. This is the message that _creates_ the circuit, so
|
|
|
|
+# it can't be sent as a cell _within_ the circuit.
|
|
class VanillaCreateCircuitMsg(RelayNetMsg):
|
|
class VanillaCreateCircuitMsg(RelayNetMsg):
|
|
"""The message for requesting circuit creation in Vanilla Onion
|
|
"""The message for requesting circuit creation in Vanilla Onion
|
|
Routing."""
|
|
Routing."""
|
|
@@ -267,6 +277,21 @@ class CircuitHandler:
|
|
# we get a cell on one, we forward it to the other (if it's not
|
|
# we get a cell on one, we forward it to the other (if it's not
|
|
# meant for us to handle directly)
|
|
# meant for us to handle directly)
|
|
self.adjacent_circuit_handler = None
|
|
self.adjacent_circuit_handler = None
|
|
|
|
+ # The function to call when this circuit closes
|
|
|
|
+ self.closer = lambda: self.channel.circuithandlers.pop(circid)
|
|
|
|
+
|
|
|
|
+ def close(self):
|
|
|
|
+ """Close the circuit. Sends a CloseCell on the circuit (and its
|
|
|
|
+ adjacent circuit, if present) and closes both."""
|
|
|
|
+ adjcirchandler = self.adjacent_circuit_handler
|
|
|
|
+ self.adjacent_circuit_handler = None
|
|
|
|
+ if adjcirchandler is not None:
|
|
|
|
+ adjcirchandler.adjacent_circuit_handler = None
|
|
|
|
+ self.closer()
|
|
|
|
+ self.channel_send_cell(CloseCell())
|
|
|
|
+ if adjcirchandler is not None:
|
|
|
|
+ adjcirchandler.closer()
|
|
|
|
+ adjcirchandler.channel_send_cell(CloseCell())
|
|
|
|
|
|
def send_cell(self, cell):
|
|
def send_cell(self, cell):
|
|
"""Send a cell on this circuit, encrypting as needed."""
|
|
"""Send a cell on this circuit, encrypting as needed."""
|
|
@@ -295,11 +320,26 @@ class CircuitHandler:
|
|
celltype = type(cell)
|
|
celltype = type(cell)
|
|
if celltype in self.cell_dispatch_table:
|
|
if celltype in self.cell_dispatch_table:
|
|
self.cell_dispatch_table[celltype].received_cell(self, cell)
|
|
self.cell_dispatch_table[celltype].received_cell(self, cell)
|
|
|
|
+
|
|
elif isinstance(cell, StringCell):
|
|
elif isinstance(cell, StringCell):
|
|
# Default handler; just print the message in the cell
|
|
# Default handler; just print the message in the cell
|
|
print("CircuitHandler: %s received '%s' on circuit %d from %s" \
|
|
print("CircuitHandler: %s received '%s' on circuit %d from %s" \
|
|
% (self.channel.channelmgr.myaddr, cell,
|
|
% (self.channel.channelmgr.myaddr, cell,
|
|
self.circid, self.channel.peer.channelmgr.myaddr))
|
|
self.circid, self.channel.peer.channelmgr.myaddr))
|
|
|
|
+
|
|
|
|
+ elif isinstance(cell, CloseCell):
|
|
|
|
+ # Forward the CloseCell (without encryption) to the
|
|
|
|
+ # adjacent circuit, if any, and close both this and the
|
|
|
|
+ # adjacent circuit
|
|
|
|
+ adjcirchandler = self.adjacent_circuit_handler
|
|
|
|
+ self.adjacent_circuit_handler = None
|
|
|
|
+ if adjcirchandler is not None:
|
|
|
|
+ adjcirchandler.adjacent_circuit_handler = None
|
|
|
|
+ self.closer()
|
|
|
|
+ if adjcirchandler is not None:
|
|
|
|
+ adjcirchandler.closer()
|
|
|
|
+ adjcirchandler.channel_send_cell(cell)
|
|
|
|
+
|
|
else:
|
|
else:
|
|
# I don't know how to handle this cell?
|
|
# I don't know how to handle this cell?
|
|
raise ValueError("CircuitHandler: %s received unknown cell type %s on circuit %d from %s" \
|
|
raise ValueError("CircuitHandler: %s received unknown cell type %s on circuit %d from %s" \
|
|
@@ -334,7 +374,7 @@ class Channel(network.Connection):
|
|
# The Channel at the other end
|
|
# The Channel at the other end
|
|
self.peer = None
|
|
self.peer = None
|
|
# The function to call when the connection closes
|
|
# The function to call when the connection closes
|
|
- self.closer = lambda: 0
|
|
|
|
|
|
+ self.closer = lambda: None
|
|
# The next circuit id to use on this channel. The party that
|
|
# The next circuit id to use on this channel. The party that
|
|
# opened the channel uses even numbers; the receiving party uses
|
|
# opened the channel uses even numbers; the receiving party uses
|
|
# odd numbers.
|
|
# odd numbers.
|
|
@@ -344,13 +384,20 @@ class Channel(network.Connection):
|
|
self.circuithandlers = dict()
|
|
self.circuithandlers = dict()
|
|
|
|
|
|
def closed(self):
|
|
def closed(self):
|
|
|
|
+ # Close each circuithandler we're managing
|
|
|
|
+ while self.circuithandlers:
|
|
|
|
+ chitems = iter(self.circuithandlers.items())
|
|
|
|
+ circid, circhandler = next(chitems)
|
|
|
|
+ print('closing circuit', circid)
|
|
|
|
+ circhandler.close()
|
|
self.closer()
|
|
self.closer()
|
|
self.peer = None
|
|
self.peer = None
|
|
|
|
|
|
def close(self):
|
|
def close(self):
|
|
- if self.peer is not None and self.peer is not self:
|
|
|
|
- self.peer.closed()
|
|
|
|
|
|
+ peer = self.peer
|
|
self.closed()
|
|
self.closed()
|
|
|
|
+ if peer is not None and peer is not self:
|
|
|
|
+ peer.closed()
|
|
|
|
|
|
def new_circuit(self):
|
|
def new_circuit(self):
|
|
"""Allocate a new circuit on this channel, returning the new
|
|
"""Allocate a new circuit on this channel, returning the new
|