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