1import time 2 3from exabgp.vendoring import six 4 5from exabgp.protocol.family import AFI 6from .connection import Connection 7from .tcp import create, bind 8from .tcp import connect 9from .tcp import MD5 10from .tcp import nagle 11from .tcp import TTL 12from .tcp import TTLv6 13from .tcp import asynchronous 14from .tcp import ready 15from .error import NetworkError 16 17 18class Outgoing(Connection): 19 direction = 'outgoing' 20 21 def __init__(self, afi, peer, local, port=179, md5='', md5_base64=False, ttl=None): 22 Connection.__init__(self, afi, peer, local) 23 24 self.ttl = ttl 25 self.afi = afi 26 self.md5 = md5 27 self.md5_base64 = md5_base64 28 self.port = port 29 30 def _setup(self): 31 try: 32 self.io = create(self.afi) 33 MD5(self.io, self.peer, self.port, self.md5, self.md5_base64) 34 if self.afi == AFI.ipv4: 35 TTL(self.io, self.peer, self.ttl) 36 elif self.afi == AFI.ipv6: 37 TTLv6(self.io, self.peer, self.ttl) 38 if self.local: 39 bind(self.io, self.local, self.afi) 40 asynchronous(self.io, self.peer) 41 return None 42 except Exception as exc: 43 self.io.close() 44 self.io = None 45 return exc 46 47 def _connect(self): 48 if not self.io: 49 setup_issue = self._setup() 50 if setup_issue: 51 return setup_issue 52 try: 53 connect(self.io, self.peer, self.port, self.afi, self.md5) 54 return None 55 except Exception as exc: 56 self.io.close() 57 self.io = None 58 return exc 59 60 def establish(self): 61 last = time.time() - 2.0 62 63 while True: 64 notify = time.time() - last > 1.0 65 if notify: 66 last = time.time() 67 68 if notify: 69 self.logger.debug('attempting connection to %s:%d' % (self.peer, self.port), self.session()) 70 71 connect_issue = self._connect() 72 if connect_issue: 73 if notify: 74 self.logger.debug('connection to %s:%d failed' % (self.peer, self.port), self.session()) 75 self.logger.debug(str(connect_issue), self.session()) 76 yield False 77 continue 78 79 connected = False 80 for r, message in ready(self.io): 81 if not r: 82 yield False 83 continue 84 connected = True 85 86 if connected: 87 self.success() 88 if not self.local: 89 self.local = self.io.getsockname()[0] 90 yield True 91 return 92 93 self._setup() 94 95 # nagle(self.io,self.peer) 96 # # Not working after connect() at least on FreeBSD TTL(self.io,self.peer,self.ttl) 97 # yield True 98