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
40 RESOLVE_CACHE = {}
41
42
43 -class MasterEntry(object):
44
45 - def __init__(self, masteruri=None, mastername=None, address=None):
46 self.masteruri = masteruri
47 self._masternames = []
48 self.add_mastername(mastername)
49 self.mutex = RLock()
50
51 self._addresses = []
52 self.add_address(address)
53
55 return ''.join([str(self.masteruri), ':\n',
56 ' masternames: ', str(self._masternames), '\n',
57 ' addresses: ', str(self._addresses), '\n'])
58
60 return (self.masteruri, list(self._masternames), list(self._addresses))
61
62 - def has_mastername(self, mastername):
63 return mastername in self._masternames
64
65 - def has_address(self, address):
66 with self.mutex:
67 return address in self._addresses
68
69 - def add_mastername(self, mastername):
70 if mastername and mastername not in self._masternames:
71 self._masternames.append(mastername)
72
73 - def add_address(self, address):
74 if address and not self.has_address(address):
75 if self.is_legal_ip(address):
76
77 with self.mutex:
78 self._addresses.append(address)
79
80 thread = Thread(target=self._get_hostname, args=((address,)))
81 thread.daemon = True
82 thread.start()
83 else:
84
85 with self.mutex:
86 self._addresses.insert(0, address)
87
88 thread = Thread(target=self._get_address, args=((address,)))
89 thread.daemon = True
90 thread.start()
91
92 @classmethod
93 - def is_legal_ip(cls, addr):
94 result = False
95 try:
96 socket.inet_pton(socket.AF_INET, addr)
97
98 result = True
99 except socket.error:
100
101 try:
102 socket.inet_pton(socket.AF_INET6, addr)
103
104 result = True
105 except socket.error:
106
107 pass
108 return result
109
110 - def _get_address(self, hostname):
111 try:
112 (_, _, ipaddrlist) = socket.gethostbyaddr(hostname)
113 with self.mutex:
114 if ipaddrlist:
115 RESOLVE_CACHE[hostname] = ipaddrlist
116 for addr in ipaddrlist:
117 if not self.has_address(addr):
118 self._addresses.append(addr)
119 except socket.gaierror:
120
121 pass
122
123 - def _get_hostname(self, address):
124 try:
125 (hostname, _, _) = socket.gethostbyaddr(address)
126 with self.mutex:
127 name_splitted = hostname.split('.')
128 RESOLVE_CACHE[address] = [name_splitted[0], hostname]
129 if not self.has_address(hostname):
130 self._addresses.insert(0, hostname)
131 if not self.has_address(name_splitted[0]):
132 self._addresses.insert(0, name_splitted[0])
133 except socket.gaierror:
134
135 pass
136
137 - def get_mastername(self):
138 try:
139 return self._masternames[0]
140 except:
141 return None
142
143 - def get_masternames(self):
144 return list(self._masternames)
145
146 - def get_address(self):
147 with self.mutex:
148 try:
149 return self._addresses[0]
150 except:
151 return None
152
153 - def addresses(self):
154 return list(self._addresses)
155
156 - def remove_mastername(self, mastername):
157 try:
158 self._masternames.remove(mastername)
159 except:
160 pass
161
162 - def remove_address(self, address):
163 try:
164 self._addresses.remove(address)
165 except:
166 pass
167
170 '''
171 This class stores the association between master URI, master name and
172 host name or IP. Both the setter and the getter methods are thread safe.
173 '''
174
176 self.mutex = RLock()
177 self._masters = []
178 self._hosts = []
179 self._address = []
180
181 - def remove_master_entry(self, masteruri):
182 with self.mutex:
183 for m in self._masters:
184 if masteruri and m.masteruri == masteruri:
185 self._masters.remove(m)
186 return
187
195
196 - def add_master_entry(self, masteruri, mastername, address):
197 with self.mutex:
198 mastername = self._validate_mastername(mastername, masteruri)
199 for m in self._masters:
200 if m.masteruri and m.masteruri == masteruri:
201 m.add_mastername(mastername)
202 m.add_address(address)
203 return
204 elif m.masteruri is None and m.has_mastername(mastername):
205 m.masteruri = masteruri
206 m.add_mastername(mastername)
207 m.add_address(address)
208 return
209 self._masters.append(MasterEntry(masteruri, mastername, address))
210
211 - def add_info(self, mastername, address):
220
222 '''
223 Not thead safe
224 '''
225 mm = self.masteruri(mastername)
226 if mm and mm != masteruri:
227 nr = 2
228 new_name = '%s_%d' % (mastername, nr)
229 while mm and mm != masteruri:
230 new_name = '%s_%d' % (mastername, nr)
231 nr = nr + 1
232 rospy.logwarn("master name '%s' is already assigned to '%s', rename to '%s'"(mastername, mm, new_name))
233 return new_name
234 return mastername
235
237 with self.mutex:
238 for m in self._masters:
239 if m.masteruri == masteruri:
240 return True
241 return False
242
253
260
267
274
282
289
296
297 - def hostname(self, address, resolve=False):
314
315 @classmethod
327
328 @classmethod
330 result = name.replace('-', '_').replace('.', '_')
331 return result
332
333 @classmethod
336
343
344 @classmethod
346 '''
347 Returns the host name used in a url, if it is a name. If it is an IP an
348 empty string will be returned.
349
350 @return: host or '' if url is an IP or invalid
351 @rtype: C{str}
352 '''
353 hostname = get_hostname(url)
354 if hostname is not None:
355 if hostname != 'localhost':
356 if '.' not in hostname and ':' not in hostname:
357 local_hostname = 'localhost'
358 try:
359
360 local_hostname = socket.gethostname()
361 except:
362 pass
363 if hostname != local_hostname:
364 return hostname
365 return ''
366