1 # -*- coding: utf-8 -*-
6 __all__ = [ 'OutPeers', 'outpeers_from_config' ]
10 from time import time as get_timestamp
17 def __init__(self, str_addrport):
18 colpos = str_addrport.rfind(':')
21 'Missing column in host:port string for %s' % str_addrport
22 self.host = str_addrport[:colpos]
23 if self.host.startswith('['):
24 assert self.host[-1] == ']'
25 self.host = self.host[1:-1]
26 self.port = int(str_addrport[colpos+1:])
27 self.possibles_addrinfo = None
30 self.timestamp_getaddrinfo = 0
34 return '%s:%s' % (self.host, self.port)
36 def _reinit_socket(self):
38 Remove last known addrinfo for that host:port, if any.
39 If addrinfo is empty, fetch a new one.
40 Initialise self.sock and self.addr
43 if self.possibles_addrinfo:
44 # remove current (0th) addrinfo
45 del self.possibles_addrinfo[0]
47 if not self.possibles_addrinfo:
48 timestamp = get_timestamp()
49 if timestamp > self.timestamp_getaddrinfo + 60:
51 logging.debug('Calling socket.getaddrinfo for %s:%s',
53 self.possibles_addrinfo = socket.getaddrinfo(self.host,
54 self.port, socket.AF_UNSPEC, socket.SOCK_DGRAM)
55 logging.info('%s possibles addrinfo for %s:%s.',
56 len(self.possibles_addrinfo), self.host, self.port)
57 logging.debug('possibles_addrinfo: %s ',
58 self.possibles_addrinfo)
59 except socket.gaierror, err:
60 logging.error("Can't resolve %s:%s: %s. "
61 "Will retry in a minute.",
62 self.host, self.port, err)
65 self.timestamp_getaddrinfo = timestamp
66 if not self.possibles_addrinfo:
67 logging.error("Can't resolve %s:%s. "
68 "Will retry in a minute.",
72 return False # waiting
74 addrinfo = self.possibles_addrinfo[0]
75 logging.info('Prepared socket to %s', addrinfo)
76 af_, socktype, proto = addrinfo[:3]
77 self.addr = addrinfo[4]
79 self.sock = socket.socket(af_, socktype, proto)
81 except socket.error, msg:
82 logging.error("Can't open socket to %s: %s", self.addr, msg)
84 def send_line(self, line):
86 Sends a AIVDM line to that peer.
87 CRLF will be added automatically.
89 while self.sock or self._reinit_socket():
91 self.sock.sendto(line+'\r\n', self.addr)
93 except socket.error, err:
94 logging.error('socket.sendto(%s) failed: %s', self.addr, err)
100 A group of UDP peers for output.
107 return '(' + ', '.join([ repr(peer) for peer in self.peers]) + ')'
109 def send_line(self, line):
111 Send a line to all the output peers registered.
113 for outpeer in self.peers:
114 logging.debug('OUT %s %s', outpeer, repr(line))
115 outpeer.send_line(line)
117 def outpeers_from_config(list_from_config):
119 Just give the list of strings from config.
120 Returns an OutPeers object.
122 outpeers = OutPeers()
123 for str_config in list_from_config:
124 assert str_config.startswith('udp:'), \
125 'Unsupported output peer protocol %s' % str_config
126 peer = OutPeer(str_config[4:])
127 outpeers.peers.append(peer)