| Home | Trees | Indices | Help |
|---|
|
|
1 # Software License Agreement (BSD License)
2 #
3 # Copyright (c) 2012, Fraunhofer FKIE/US, Alexander Tiderko
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 #
10 # * Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # * Redistributions in binary form must reproduce the above
13 # copyright notice, this list of conditions and the following
14 # disclaimer in the documentation and/or other materials provided
15 # with the distribution.
16 # * Neither the name of Fraunhofer nor the names of its
17 # contributors may be used to endorse or promote products derived
18 # from this software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 # POSSIBILITY OF SUCH DAMAGE.
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 = {} # hostname : address
44
46 self.masteruri = masteruri
47 self._masternames = []
48 self.add_mastername(mastername)
49 self.mutex = RLock()
50 # addresses: hostname (at first place if available), IPv4 or IPv6
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
63 return mastername in self._masternames
64
68
72
74 if address and not self.has_address(address):
75 if self.is_legal_ip(address):
76 # it is an IP, try to get the hostname
77 with self.mutex:
78 self._addresses.append(address)
79 # resolve the name in a thread
80 thread = Thread(target=self._get_hostname, args=((address,)))
81 thread.daemon = True
82 thread.start()
83 else:
84 # it is a hostname: add at the fist place and try to get an IP for this host
85 with self.mutex:
86 self._addresses.insert(0, address)
87 # resolve the name in a thread
88 thread = Thread(target=self._get_address, args=((address,)))
89 thread.daemon = True
90 thread.start()
91
92 @classmethod
94 result = False
95 try:
96 socket.inet_pton(socket.AF_INET, addr)
97 # ok, it is a legal IPv4 address
98 result = True
99 except socket.error:
100 # try for IPv6
101 try:
102 socket.inet_pton(socket.AF_INET6, addr)
103 # ok, it is a legal IPv6 address
104 result = True
105 except socket.error:
106 # not legal IP address
107 pass
108 return result
109
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 # no suitable address found
121 pass
122
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 # no suitable address found
135 pass
136
142
145
152
155
161
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 = [] # sets with masters
178 self._hosts = [] # sets with hosts
179 self._address = [] # avoid the mixing of ip and name as address
180
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
189 with self.mutex:
190 for m in self._masters:
191 if m.has_mastername(mastername) and m.has_address(address):
192 m.remove_mastername(mastername)
193 m.remove_address(address)
194 return
195
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
212 with self.mutex:
213 for m in self._masters:
214 if m.has_mastername(mastername):
215 m.add_mastername(mastername)
216 m.add_address(address)
217 return
218 if mastername is not None:
219 self._masters.append(MasterEntry(None, 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
244 with self.mutex:
245 for m in self._masters:
246 if m.masteruri == masteruri:
247 if address is not None:
248 if m.has_address(address):
249 return m.get_mastername()
250 else:
251 return m.get_mastername()
252 return None
253
255 with self.mutex:
256 for m in self._masters:
257 if m.masteruri == masteruri:
258 return m.get_masternames()
259 return list()
260
262 with self.mutex:
263 for m in self._masters:
264 if m.has_address(address):
265 return m.get_mastername()
266 return None
267
269 with self.mutex:
270 for m in self._masters:
271 if m.has_mastername(mastername):
272 return m.masteruri
273 return None
274
276 with self.mutex:
277 result = []
278 for m in self._masters:
279 if m.has_address(address) and m.masteruri and m.masteruri not in result:
280 result.append(m.masteruri)
281 return result
282
284 with self.mutex:
285 for m in self._masters:
286 if m.masteruri == masteruri or m.has_mastername(masteruri):
287 return m.get_address()
288 return None
289
291 with self.mutex:
292 for m in self._masters:
293 if m.masteruri == masteruri or m.has_mastername(masteruri):
294 return m.addresses()
295 return []
296
298 with self.mutex:
299 for m in self._masters:
300 if m.has_address(address) or m.has_mastername(address):
301 result = m.get_address()
302 if result and not MasterEntry.is_legal_ip(result):
303 return result
304 else:
305 break
306 try:
307 if MasterEntry.is_legal_ip(address):
308 (hostname, _, _) = socket.gethostbyaddr(address)
309 return hostname
310 except:
311 import traceback
312 print traceback.format_exc()
313 return address
314
315 @classmethod
317 result = masteruri
318 try:
319 url = urlparse(masteruri)
320 if url.port == 11311:
321 result = '%s' % url.hostname
322 else:
323 result = '%s_%d' % (url.hostname, url.port)
324 except:
325 pass
326 return cls.normalize_name(result)
327
328 @classmethod
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 # ROS resolves the 'localhost' to local hostname
360 local_hostname = socket.gethostname()
361 except:
362 pass
363 if hostname != local_hostname:
364 return hostname
365 return ''
366
| Home | Trees | Indices | Help |
|---|
| Generated by Epydoc 3.0.1 on Thu Apr 27 02:41:58 2017 | http://epydoc.sourceforge.net |