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