1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 from threading import Thread, RLock
34 from urlparse import urlparse
35 import socket
36
37 import rospy
38 from master_discovery_fkie.common import get_hostname
39 from node_manager_fkie.common import utf8
40
41 RESOLVE_CACHE = {}
42
43
44 -class MasterEntry(object):
45
46 - def __init__(self, masteruri=None, mastername=None, address=None):
47 self.masteruri = masteruri
48 self._masternames = []
49 self.add_mastername(mastername)
50 self.mutex = RLock()
51
52 self._addresses = []
53 self.add_address(address)
54
56 return ''.join([utf8(self.masteruri), ':\n',
57 ' masternames: ', utf8(self._masternames), '\n',
58 ' addresses: ', utf8(self._addresses), '\n'])
59
61 return (self.masteruri, list(self._masternames), list(self._addresses))
62
63 - def has_mastername(self, mastername):
64 return mastername in self._masternames
65
66 - def has_address(self, address):
67 with self.mutex:
68 return address in self._addresses
69
70 - def add_mastername(self, mastername):
71 if mastername and mastername not in self._masternames:
72 self._masternames.append(mastername)
73
74 - def add_address(self, address):
75 if address and not self.has_address(address):
76 if self.is_legal_ip(address):
77
78 with self.mutex:
79 self._addresses.append(address)
80
81 thread = Thread(target=self._get_hostname, args=((address,)))
82 thread.daemon = True
83 thread.start()
84 else:
85
86 with self.mutex:
87 self._addresses.insert(0, address)
88
89 thread = Thread(target=self._get_address, args=((address,)))
90 thread.daemon = True
91 thread.start()
92
93 @classmethod
94 - def is_legal_ip(cls, addr):
95 result = False
96 try:
97 socket.inet_pton(socket.AF_INET, addr)
98
99 result = True
100 except socket.error:
101
102 try:
103 socket.inet_pton(socket.AF_INET6, addr)
104
105 result = True
106 except socket.error:
107
108 pass
109 return result
110
111 - def _get_address(self, hostname):
112 try:
113 (_, _, ipaddrlist) = socket.gethostbyaddr(hostname)
114 with self.mutex:
115 if ipaddrlist:
116 RESOLVE_CACHE[hostname] = ipaddrlist
117 for addr in ipaddrlist:
118 if not self.has_address(addr):
119 self._addresses.append(addr)
120 except socket.gaierror:
121
122 pass
123
124 - def _get_hostname(self, address):
125 try:
126 (hostname, _, _) = socket.gethostbyaddr(address)
127 with self.mutex:
128 name_splitted = hostname.split('.')
129 RESOLVE_CACHE[address] = [name_splitted[0], hostname]
130 if not self.has_address(hostname):
131 self._addresses.insert(0, hostname)
132 if not self.has_address(name_splitted[0]):
133 self._addresses.insert(0, name_splitted[0])
134 except socket.gaierror:
135
136 pass
137
138 - def get_mastername(self):
139 try:
140 return self._masternames[0]
141 except:
142 return None
143
144 - def get_masternames(self):
145 return list(self._masternames)
146
147 - def get_address(self):
148 with self.mutex:
149 try:
150 return self._addresses[0]
151 except:
152 return None
153
154 - def addresses(self):
155 return list(self._addresses)
156
157 - def remove_mastername(self, mastername):
158 try:
159 self._masternames.remove(mastername)
160 except:
161 pass
162
163 - def remove_address(self, address):
164 try:
165 self._addresses.remove(address)
166 except:
167 pass
168
171 '''
172 This class stores the association between master URI, master name and
173 host name or IP. Both the setter and the getter methods are thread safe.
174 '''
175
177 self.mutex = RLock()
178 self._masters = []
179 self._hosts = []
180 self._address = []
181
182 - def remove_master_entry(self, masteruri):
183 with self.mutex:
184 for m in self._masters:
185 if masteruri and m.masteruri == masteruri:
186 self._masters.remove(m)
187 return
188
196
197 - def add_master_entry(self, masteruri, mastername, address):
198 with self.mutex:
199 mastername = self._validate_mastername(mastername, masteruri)
200 for m in self._masters:
201 if m.masteruri and m.masteruri == masteruri:
202 m.add_mastername(mastername)
203 m.add_address(address)
204 return
205 elif m.masteruri is None and m.has_mastername(mastername):
206 m.masteruri = masteruri
207 m.add_mastername(mastername)
208 m.add_address(address)
209 return
210 self._masters.append(MasterEntry(masteruri, mastername, address))
211
212 - def add_info(self, mastername, address):
221
238
240 with self.mutex:
241 for m in self._masters:
242 if m.masteruri == masteruri:
243 return True
244 return False
245
256
263
270
277
285
292
299
300 - def hostname(self, address, resolve=False):
317
318 @classmethod
330
331 @classmethod
333 result = name.replace('-', '_').replace('.', '_')
334 return result
335
336 @classmethod
339
346
347 @classmethod
349 '''
350 Returns the host name used in a url, if it is a name. If it is an IP an
351 empty string will be returned.
352
353 @return: host or '' if url is an IP or invalid
354 @rtype: C{str}
355 '''
356 hostname = get_hostname(url)
357 if hostname is not None:
358 if hostname != 'localhost':
359 if '.' not in hostname and ':' not in hostname:
360 local_hostname = 'localhost'
361 try:
362
363 local_hostname = socket.gethostname()
364 except:
365 pass
366 if hostname != local_hostname:
367 return hostname
368 return ''
369