circuitmanager

Details

CircuitManager manages a pool of circuits. CircuitManager knows about all open and pending circuits and can make choices about how and when circuits are built and destroyed.

Currently, it’s up to CircuitManager to:

  • Create an initial pool of circuits (currently 4 IPv4 and 1 IPv6 initial circuits by default)
  • Handle incoming requests for open circuits (made by streams) and assign suitable circuits to handle the requests
  • Decide when and if a circuit should be destroyed when its stream count drops to zero
  • Replenish the circuit pool when a circuit is destroyed and, if necessary, build new circuits to handle any (now orphaned) pending streams
  • Assign pending streams to newly opened circuits when the circuits complete their extension process
  • Destroy all open and pending circuits when oppy shuts down
class circuit.circuitmanager.PendingStream

Bases: tuple

PendingStream(stream, deferred)

deferred

Alias for field number 1

stream

Alias for field number 0

class circuit.circuitmanager.CircuitManager[source]

Bases: object

Manage a pool of circuits.

requestOpenCircuit(stream)[source]

Return a deferred that will fire with an open circuit that can handle the stream’s request.

There are three general cases to handle when a new open circuit request comes in:

  1. An open circuit exists that can handle this request. In this case, choose a random circuit from the set of open circuits that can handle this request and immediately callback the deferred with the chosen open circuit.
  2. A pending circuit exists that, when open, can handle this request. In this case, add the request to a pool of pending requests. Whenever a circuit opens, circuit manager checks all pending requests and assigns any pending requests that the newly opened circuit can handle to that circuit. So when a pending circuit opens that can handle this stream, the stream’s deferred will be called back with the fresly opened circuit.
  3. No open or pending circuits exist that can handle the request. In this case, begin building a new circuit that can. Add the request to a pending request pool and, when a circuit opens that can handle the request, callback this stream’s deferred with the newly opened circuit.
Parameters:stream (oppy.stream.stream.Stream) – the stream that is requesting an open circuit
Returns:twisted.internet.defer.Deferred which will fire when a circuit has opened that can handle this stream’s request.
shouldDestroyCircuit(circuit)[source]

Return True iff CircuitManager thinks the calling circuit should be destroyed.

Circuits call shouldDestroyCircuit() when their number of open streams drops to zero. Since CircuitManager knows about all open and pending circuits, it can make an informed judgement about whether the calling circuit should be destroyed or remain open.

Currently, CircuitManager maintains at least 4 open or pending IPv4 circuits and one open or pending IPv6 circuit. If the number of streams on any circuit drops to zero and it can be closed while still satisfying these basic constraints, then CircuitManager tells it to begin destroying itself (returns True).

Parameters:circuit (oppy.circuit.circuit.Circuit) – circuit to consider destroying.
Returns:bool True if CircuitManager decides this circuit should be destroyed, False otherwise.
circuitDestroyed(circuit)[source]

Circuits call circuitDestroyed() when they have cleaned up after themselves and closed.

Circuits may need to do a number of things before references to them are completely removed. Exactly what steps a circuit needs to take before being fully destroyed depend on both the circuit’s state and the state of the whole program. After a circuit has fully cleaned up after itself and taken all necessary closing actions, it calls CircuitManager.circuitDestroyed().

circuitDestroyed() does three things:

  1. Remove the closed circuit from any internal maps.
  2. Check the pool of pending requests. If any pending requests exist that cannot be handled by any open or pending circuits, begin building a new circuit to handle these orphaned requests. This can happen when a circuit is built to handle a particular request but is then destroyed/an error occurs while it is being built.
  3. Check CircuitManager’s basic open and pending circuit requirements to see if a new circuit of a certain type should be built. For instance, if an IPv4 circuit closes and the number of open and pending IPv4 circuits is below self._min_IPv4_count, a new IPv4 circuit will be built.
Parameters:circuit_id (int) – id of circuit to be destroyed
circuitOpened(circuit)[source]

Circuits call circuitOpened() when they have successfully completed their build process and are ready to handle incoming streams.

When a circuit opens, CircuitManager:

  • removes it from the pending circuit map
  • adds it to the open circuit map
  • assigns any pending requests that this circuit can handle to this freshly opened circuit
  • if this is the first circuit successfully opened, send a nice message to the user letting them know oppy is ready to forward traffic
Parameters:circuit (oppy.circuit.circuit.Circuit) – circuit that has just opened.
destroyAllCircuits()[source]

Destroy all open and pending circuits and remove all pending requests.

Previous topic

circuit

Next topic

circuit

This Page