| 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 from node_manager_fkie.common import utf8
40
41 RESOLVE_CACHE = {} # hostname : address
45
47 self.masteruri = masteruri
48 self._masternames = []
49 self.add_mastername(mastername)
50 self.mutex = RLock()
51 # addresses: hostname (at first place if available), IPv4 or IPv6
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
64 return mastername in self._masternames
65
69
73
75 if address and not self.has_address(address):
76 if self.is_legal_ip(address):
77 # it is an IP, try to get the hostname
78 with self.mutex:
79 self._addresses.append(address)
80 # resolve the name in a thread
81 thread = Thread(target=self._get_hostname, args=((address,)))
82 thread.daemon = True
83 thread.start()
84 else:
85 # it is a hostname: add at the fist place and try to get an IP for this host
86 with self.mutex:
87 self._addresses.insert(0, address)
88 # resolve the name in a thread
89 thread = Thread(target=self._get_address, args=((address,)))
90 thread.daemon = True
91 thread.start()
92
93 @classmethod
95 result = False
96 try:
97 socket.inet_pton(socket.AF_INET, addr)
98 # ok, it is a legal IPv4 address
99 result = True
100 except socket.error:
101 # try for IPv6
102 try:
103 socket.inet_pton(socket.AF_INET6, addr)
104 # ok, it is a legal IPv6 address
105 result = True
106 except socket.error:
107 # not legal IP address
108 pass
109 return result
110
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 # no suitable address found
122 pass
123
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 # no suitable address found
136 pass
137
143
146
153
156
162
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 = [] # sets with masters
179 self._hosts = [] # sets with hosts
180 self._address = [] # avoid the mixing of ip and name as address
181
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
190 with self.mutex:
191 for m in self._masters:
192 if m.has_mastername(mastername) and m.has_address(address):
193 m.remove_mastername(mastername)
194 m.remove_address(address)
195 return
196
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
213 with self.mutex:
214 for m in self._masters:
215 if m.has_mastername(mastername):
216 m.add_mastername(mastername)
217 m.add_address(address)
218 return
219 if mastername is not None:
220 self._masters.append(MasterEntry(None, mastername, address))
221
223 '''
224 Not thread safe
225 '''
226 mm = self.masteruri(mastername)
227 if mm and mm != masteruri:
228 nr = 2
229 new_name = '%s_%d' % (mastername, nr)
230 mm = self.masteruri(new_name)
231 while mm and mm != masteruri:
232 nr = nr + 1
233 new_name = '%s_%d' % (mastername, nr)
234 mm = self.masteruri(new_name)
235 rospy.logwarn("master name '%s' is already assigned to '%s', rename to '%s'" % (mastername, mm, new_name))
236 return new_name
237 return mastername
238
240 with self.mutex:
241 for m in self._masters:
242 if m.masteruri == masteruri:
243 return True
244 return False
245
247 with self.mutex:
248 for m in self._masters:
249 if m.masteruri == masteruri:
250 if address is not None:
251 if m.has_address(address):
252 return m.get_mastername()
253 else:
254 return m.get_mastername()
255 return get_hostname(masteruri)
256
258 with self.mutex:
259 for m in self._masters:
260 if m.masteruri == masteruri:
261 return m.get_masternames()
262 return list()
263
265 with self.mutex:
266 for m in self._masters:
267 if m.has_address(address):
268 return m.get_mastername()
269 return None
270
272 with self.mutex:
273 for m in self._masters:
274 if m.has_mastername(mastername):
275 return m.masteruri
276 return None
277
279 with self.mutex:
280 result = []
281 for m in self._masters:
282 if m.has_address(address) and m.masteruri and m.masteruri not in result:
283 result.append(m.masteruri)
284 return result
285
287 with self.mutex:
288 for m in self._masters:
289 if m.masteruri == masteruri or m.has_mastername(masteruri):
290 return m.get_address()
291 return get_hostname(masteruri)
292
294 with self.mutex:
295 for m in self._masters:
296 if m.masteruri == masteruri or m.has_mastername(masteruri):
297 return m.addresses()
298 return []
299
301 with self.mutex:
302 for m in self._masters:
303 if m.has_address(address) or m.has_mastername(address):
304 result = m.get_address()
305 if result and not MasterEntry.is_legal_ip(result):
306 return result
307 else:
308 break
309 try:
310 if MasterEntry.is_legal_ip(address):
311 (hostname, _, _) = socket.gethostbyaddr(address)
312 return hostname
313 except:
314 import traceback
315 print traceback.format_exc()
316 return address
317
318 @classmethod
320 result = masteruri
321 try:
322 url = urlparse(masteruri)
323 if url.port == 11311:
324 result = '%s' % url.hostname
325 else:
326 result = '%s_%d' % (url.hostname, url.port)
327 except:
328 pass
329 return cls.normalize_name(result)
330
331 @classmethod
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 # ROS resolves the 'localhost' to local hostname
363 local_hostname = socket.gethostname()
364 except:
365 pass
366 if hostname != local_hostname:
367 return hostname
368 return ''
369
| Home | Trees | Indices | Help |
|---|
| Generated by Epydoc 3.0.1 on Fri May 3 02:27:58 2019 | http://epydoc.sourceforge.net |