0

I have been trying to add some functionality to NavigaTor (written in python 2), which uses stem library to build TOR circuits. Basically, if a circuit fails, i am trying to build a new one with a new path (Navigator does not do that by default, and returns if the circuit fails). The relevant code is as follows:

Probe = namedtuple('Probe', 'path circs cbt streams perf bw')
def _circuit_handler(event):
    """ Event handler for handling circuit states. """
    if not event.build_flags or 'IS_INTERNAL' not in event.build_flags:
        if event.id == self._cid:
            probe.circs.append(event)
            if self._circuit_built.is_set():
                if event.status in ('FAILED', 'CLOSED'):
                    self._circuit_finished.set()
            if not self._circuit_built.is_set():
                if event.status in ('FAILED', 'BUILT'):
                    self._circuit_built.set()
        elif event.status == 'LAUNCHED' and not self._cid:
            self._cid = event.id
            probe.circs.append(event)
            self._manager.circ_launched.release()

In a while loop, I am trying to build circuits until a circuit has successfully been created:

while(true):        #try until a valid circuit is received:
    probe = Probe(path=self.path, circs=[], \
        cbt=set(), streams=[],perf=[], bw=[])
    circ_path = [node.desc.fingerprint for node in self.path]       #Valid nodes already acquired and stored in path

    self._manager.circ_launched.acquire()
    self._controller.add_event_listener(_circuit_handler, EventType.CIRC)
    self._controller.add_event_listener(_cbt_check, EventType.INFO)
    circID = self._controller.extend_circuit(path=circ_path)
    self._circuit_built.wait()

    build_status = probe.circs[len(probe.circs) - 1].status
    assert build_status == 'BUILT' or build_status == 'FAILED', \
        'Wrong circuit status: %s.' % build_statusFirst

    if build_status == 'FAILED':
        self._controller.remove_event_listener(_circuit_handler)
        self._controller.remove_event_listener(_cbt_check)
        self.path = self._manager._get_new_path()
    else:
        break

Now, my problem is, that if the circuit is successful in the first attempt, this thing works fine. But if the build_status is FAILED, and loop runs again with a new valid path, the code crashes at the line:

build_status = probe.circs[len(probe.circs) - 1].status

With IndexError: list index out of range. Upon debugging, I have observed that the probe.circs remains empty, even though the _circuit_handler event is supposed to append to it. This happens every single time for the second circuit, even though it works fine if the first circuit was successful. What am I doing wrong here?

Khizar Amin
  • 198
  • 1
  • 2
  • 12

1 Answers1

0

Figured it out, _cid was not being reset upon circuit failure. Added self._cid = None to fix.

Khizar Amin
  • 198
  • 1
  • 2
  • 12