def _processRelayEndCell(self, cell, origin):
        '''Called when this circuit receives a RelayEndCell.

        Tear down the stream associated with the stream in the RelayEndCell
        if this circuit has a reference to it. Drop the cell if we have
        no reference to this stream.

        :param oppy.cell.relay.RelayEndCell cell: relay end cell recieved
            from the network
        :param int origin: which node on the circuit's path this cell
            came from
        '''
        sid = cell.rheader.stream_id

        try:
            self._streams[sid].closeFromCircuit()
            # TODO: handle REASON_EXITPOLICY
            if cell.reason != REASON_DONE:
                msg = ("Circuit {} received a RelayEndCell for stream {}, "
                       "and reason was not REASON_DONE. Reason: {}."
                       .format(self.circuit_id, sid, cell.reason))
                logging.debug(msg)
        except __HOLE__:
            msg = ("Circuit {} received a RelayEndCell for nonexistent "
                   "stream {}. Dropping cell.".format(self.circuit_id, sid))
            logging.debug(msg)
dataset/ETHPy150Open nskinkel/oppy/oppy/circuit/circuit.py/Circuit._processRelayEndCell