コード例 #1
0
    def _accept(self):
        # we can do this as Protocol is a mutable object
        proto = self._['in']['proto']

        # send OPEN
        for message in proto.new_open(self._restarted):
            if ord(message.TYPE) == Message.Type.NOP:
                yield ACTION.immediate

        proto.negotiated.sent(message)

        self._['in']['state'] = STATE.opensent

        # Read OPEN
        wait = environment.settings().bgp.openwait
        opentimer = Timer(
            self._log('in'), wait, 1, 1,
            'waited for open too long, we do not like stuck in active')
        # Only yield if we have not the open, otherwise the reactor can run the other connection
        # which would be bad as we need to do the collission check without going to the other peer
        for message in proto.read_open(self.neighbor.peer_address.ip):
            opentimer.tick(message)
            if ord(message.TYPE) == Message.Type.NOP:
                yield ACTION.later

        self._['in']['state'] = STATE.openconfirm
        proto.negotiated.received(message)
        proto.validate_open()

        if self._['out']['state'] == STATE.openconfirm:
            self.logger.network(
                'incoming connection finds the outgoing connection is in openconfirm'
            )
            local_id = self.neighbor.router_id.packed
            remote_id = proto.negotiated.received_open.router_id.packed

            if local_id < remote_id:
                self.logger.network('closing the outgoing connection')
                self._reset('out', 'collision local id < remote id')
                yield ACTION.immediate
            else:
                self.logger.network('aborting the incoming connection')
                stop = Interrupted()
                stop.direction = 'in'
                raise stop

        # Send KEEPALIVE
        for message in self._['in']['proto'].new_keepalive('OPENCONFIRM'):
            yield ACTION.immediate

        # Start keeping keepalive timer
        self.timer = Timer(self._log('in'), proto.negotiated.holdtime, 4, 0)
        # Read KEEPALIVE
        for message in proto.read_keepalive('ESTABLISHED'):
            self.timer.tick(message)
            yield ACTION.later

        self._['in']['state'] = STATE.established
        # let the caller know that we were sucesfull
        yield ACTION.immediate
コード例 #2
0
    def _connect(self):
        # try to establish the outgoing connection

        proto = Protocol(self)
        generator = proto.connect()

        connected = False
        try:
            while not connected:
                connected = generator.next()
                # we want to come back as soon as possible
                yield ACTION.immediate
        except StopIteration:
            # Connection failed
            if not connected:
                proto.close('connection to peer failed')
            # A connection arrived before we could establish !
            if not connected or self._['in']['proto']:
                stop = Interrupted()
                stop.direction = 'out'
                raise stop

        self._['out']['state'] = STATE.connect
        self._['out']['proto'] = proto

        # send OPEN
        # Only yield if we have not the open, otherwise the reactor can run the other connection
        # which would be bad as we need to set the state without going to the other peer
        for message in proto.new_open(self._restarted):
            if ord(message.TYPE) == Message.Type.NOP:
                yield ACTION.immediate

        proto.negotiated.sent(message)

        self._['out']['state'] = STATE.opensent

        # Read OPEN
        wait = environment.settings().bgp.openwait
        opentimer = Timer(
            self._log('out'), wait, 1, 1,
            'waited for open too long, we do not like stuck in active')
        for message in self._['out']['proto'].read_open(
                self.neighbor.peer_address.ip):
            opentimer.tick(message)
            # XXX: FIXME: change the whole code to use the ord and not the chr version
            # Only yield if we have not the open, otherwise the reactor can run the other connection
            # which would be bad as we need to do the collission check
            if ord(message.TYPE) == Message.Type.NOP:
                yield ACTION.later

        self._['out']['state'] = STATE.openconfirm
        proto.negotiated.received(message)
        proto.validate_open()

        if self._['in']['state'] == STATE.openconfirm:
            self.logger.network(
                'outgoing connection finds the incoming connection is in openconfirm'
            )
            local_id = self.neighbor.router_id.packed
            remote_id = proto.negotiated.received_open.router_id.packed

            if local_id < remote_id:
                self.logger.network('aborting the outgoing connection')
                stop = Interrupted()
                stop.direction = 'out'
                raise stop
            else:
                self.logger.network('closing the incoming connection')
                self._reset('in', 'collision local id < remote id')
                yield ACTION.immediate

        # Send KEEPALIVE
        for message in proto.new_keepalive('OPENCONFIRM'):
            yield ACTION.immediate

        # Start keeping keepalive timer
        self.timer = Timer(self._log('out'),
                           self._['out']['proto'].negotiated.holdtime, 4, 0)
        # Read KEEPALIVE
        for message in self._['out']['proto'].read_keepalive('ESTABLISHED'):
            self.timer.tick(message)
            yield ACTION.later

        self._['out']['state'] = STATE.established
        # let the caller know that we were sucesfull
        yield ACTION.immediate