def configurable_default(cls):
return BlockingResolver
- def getaddrinfo(self, *args, **kwargs):
+ def resolve(self, host, port, family=socket.AF_UNSPEC, callback=None):
"""Resolves an address.
- The arguments to this function are the same as to
- `socket.getaddrinfo`, with the addition of an optional
- keyword-only ``callback`` argument.
+ The ``host`` argument is a string which may be a hostname or a
+ literal IP address.
- Returns a `Future` whose result is the same as the return
- value of `socket.getaddrinfo`. If a callback is passed,
- it will be run with the `Future` as an argument when it
- is complete.
+ Returns a `Future` whose result is a list of (family, address)
+ pairs, where address is a tuple suitable to pass to
+ `socket.connect` (i.e. a (host, port) pair for IPv4;
+ additional fields may be present for IPv6). If a callback is
+ passed, it will be run with the `Future` as an argument when
+ it is complete.
"""
raise NotImplementedError()
self.executor = executor or dummy_executor
@run_on_executor
- def getaddrinfo(self, *args, **kwargs):
- return socket.getaddrinfo(*args, **kwargs)
+ def resolve(self, host, port, family=socket.AF_UNSPEC):
+ addrinfo = socket.getaddrinfo(host, port, family)
+ results = []
+ for family, socktype, proto, canonname, address in addrinfo:
+ results.append((family, address))
+ return results
class BlockingResolver(ExecutorResolver):
def initialize(self, io_loop=None):
self.resolver = resolver
self.mapping = mapping
- def getaddrinfo(self, host, port, *args, **kwargs):
+ def resolve(self, host, port, *args, **kwargs):
if (host, port) in self.mapping:
host, port = self.mapping[(host, port)]
elif host in self.mapping:
host = self.mapping[host]
- return self.resolver.getaddrinfo(host, port, *args, **kwargs)
+ return self.resolver.resolve(host, port, *args, **kwargs)
@return_future
@gen.engine
- def getaddrinfo(self, host, port, family=0, socktype=0, proto=0,
- flags=0, callback=None):
+ def resolve(self, host, port, family=0, callback=None):
if is_valid_ip(host):
addresses = [host]
else:
if family != socket.AF_UNSPEC and family != address_family:
raise Exception('Requested socket family %d but got %d' %
(family, address_family))
- addrinfo.append((address_family, socktype, proto, '', (address, port)))
+ addrinfo.append((address_family, (address, port)))
callback(addrinfo)
@return_future
@gen.engine
- def getaddrinfo(self, host, port, family=0, socktype=0, proto=0,
- flags=0, callback=None):
+ def resolve(self, host, port, family=0, callback=None):
# getHostByName doesn't accept IP addresses, so if the input
# looks like an IP address just return it immediately.
if twisted.internet.abstract.isIPAddress(host):
raise Exception('Requested socket family %d but got %d' %
(family, resolved_family))
result = [
- (resolved_family, socktype, proto, '', (resolved, port)),
+ (resolved_family, (resolved, port)),
]
self.io_loop.add_callback(callback, result)
# so restrict to ipv4 by default.
af = socket.AF_INET
- self.resolver.getaddrinfo(
- host, port, af, socket.SOCK_STREAM, 0, 0,
- callback=self._on_resolve)
+ self.resolver.resolve(host, port, af, callback=self._on_resolve)
def _on_resolve(self, future):
- af, socktype, proto, canonname, sockaddr = future.result()[0]
+ af, sockaddr = future.result()[0]
if self.parsed.scheme == "https":
ssl_options = {}
# information.
ssl_options["ssl_version"] = ssl.PROTOCOL_SSLv3
- self.stream = SSLIOStream(socket.socket(af, socktype, proto),
+ self.stream = SSLIOStream(socket.socket(af),
io_loop=self.io_loop,
ssl_options=ssl_options,
max_buffer_size=self.max_buffer_size)
else:
- self.stream = IOStream(socket.socket(af, socktype, proto),
+ self.stream = IOStream(socket.socket(af),
io_loop=self.io_loop,
max_buffer_size=self.max_buffer_size)
timeout = min(self.request.connect_timeout, self.request.request_timeout)
class _ResolverTestMixin(object):
def test_localhost(self):
- # Note that windows returns IPPROTO_IP unless we specifically
- # ask for IPPROTO_TCP (either will work to create a socket,
- # but this test looks for an exact match)
- self.resolver.getaddrinfo('localhost', 80, socket.AF_UNSPEC,
- socket.SOCK_STREAM,
- socket.IPPROTO_TCP,
- callback=self.stop)
+ self.resolver.resolve('localhost', 80, callback=self.stop)
future = self.wait()
- self.assertIn(
- (socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP, '',
- ('127.0.0.1', 80)),
- future.result())
+ self.assertIn((socket.AF_INET, ('127.0.0.1', 80)),
+ future.result())
@gen_test
def test_future_interface(self):
- addrinfo = yield self.resolver.getaddrinfo(
- 'localhost', 80, socket.AF_UNSPEC,
- socket.SOCK_STREAM, socket.IPPROTO_TCP)
- self.assertIn(
- (socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP, '',
- ('127.0.0.1', 80)),
- addrinfo)
-
+ addrinfo = yield self.resolver.resolve('localhost', 80,
+ socket.AF_UNSPEC)
+ self.assertIn((socket.AF_INET, ('127.0.0.1', 80)),
+ addrinfo)
class BlockingResolverTest(AsyncTestCase, _ResolverTestMixin):