caresresolver.py
Go to the documentation of this file.
00001 from __future__ import absolute_import, division, print_function, with_statement
00002 import pycares
00003 import socket
00004 
00005 from tornado import gen
00006 from tornado.ioloop import IOLoop
00007 from tornado.netutil import Resolver, is_valid_ip
00008 
00009 
00010 class CaresResolver(Resolver):
00011     """Name resolver based on the c-ares library.
00012 
00013     This is a non-blocking and non-threaded resolver.  It may not produce
00014     the same results as the system resolver, but can be used for non-blocking
00015     resolution when threads cannot be used.
00016 
00017     c-ares fails to resolve some names when ``family`` is ``AF_UNSPEC``,
00018     so it is only recommended for use in ``AF_INET`` (i.e. IPv4).  This is
00019     the default for ``tornado.simple_httpclient``, but other libraries
00020     may default to ``AF_UNSPEC``.
00021     """
00022     def initialize(self, io_loop=None):
00023         self.io_loop = io_loop or IOLoop.current()
00024         self.channel = pycares.Channel(sock_state_cb=self._sock_state_cb)
00025         self.fds = {}
00026 
00027     def _sock_state_cb(self, fd, readable, writable):
00028         state = ((IOLoop.READ if readable else 0) |
00029                  (IOLoop.WRITE if writable else 0))
00030         if not state:
00031             self.io_loop.remove_handler(fd)
00032             del self.fds[fd]
00033         elif fd in self.fds:
00034             self.io_loop.update_handler(fd, state)
00035             self.fds[fd] = state
00036         else:
00037             self.io_loop.add_handler(fd, self._handle_events, state)
00038             self.fds[fd] = state
00039 
00040     def _handle_events(self, fd, events):
00041         read_fd = pycares.ARES_SOCKET_BAD
00042         write_fd = pycares.ARES_SOCKET_BAD
00043         if events & IOLoop.READ:
00044             read_fd = fd
00045         if events & IOLoop.WRITE:
00046             write_fd = fd
00047         self.channel.process_fd(read_fd, write_fd)
00048 
00049     @gen.coroutine
00050     def resolve(self, host, port, family=0):
00051         if is_valid_ip(host):
00052             addresses = [host]
00053         else:
00054             # gethostbyname doesn't take callback as a kwarg
00055             self.channel.gethostbyname(host, family, (yield gen.Callback(1)))
00056             callback_args = yield gen.Wait(1)
00057             assert isinstance(callback_args, gen.Arguments)
00058             assert not callback_args.kwargs
00059             result, error = callback_args.args
00060             if error:
00061                 raise Exception('C-Ares returned error %s: %s while resolving %s' %
00062                                 (error, pycares.errno.strerror(error), host))
00063             addresses = result.addresses
00064         addrinfo = []
00065         for address in addresses:
00066             if '.' in address:
00067                 address_family = socket.AF_INET
00068             elif ':' in address:
00069                 address_family = socket.AF_INET6
00070             else:
00071                 address_family = socket.AF_UNSPEC
00072             if family != socket.AF_UNSPEC and family != address_family:
00073                 raise Exception('Requested socket family %d but got %d' %
00074                                 (family, address_family))
00075             addrinfo.append((address_family, (address, port)))
00076         raise gen.Return(addrinfo)


rosbridge_tools
Author(s): Jonathan Mace
autogenerated on Sat Dec 27 2014 11:25:59