summaryrefslogtreecommitdiff
path: root/sleekxmpp/xmlstream/resolver.py
diff options
context:
space:
mode:
Diffstat (limited to 'sleekxmpp/xmlstream/resolver.py')
-rw-r--r--sleekxmpp/xmlstream/resolver.py79
1 files changed, 54 insertions, 25 deletions
diff --git a/sleekxmpp/xmlstream/resolver.py b/sleekxmpp/xmlstream/resolver.py
index 0d7a8c0d..188e5ac7 100644
--- a/sleekxmpp/xmlstream/resolver.py
+++ b/sleekxmpp/xmlstream/resolver.py
@@ -32,10 +32,10 @@ log = logging.getLogger(__name__)
#: cd dnspython
#: git checkout python3
#: python3 setup.py install
-USE_DNSPYTHON = False
+DNSPYTHON_AVAILABLE = False
try:
import dns.resolver
- USE_DNSPYTHON = True
+ DNSPYTHON_AVAILABLE = True
except ImportError as e:
log.debug("Could not find dnspython package. " + \
"Not all features will be available")
@@ -47,13 +47,13 @@ def default_resolver():
:returns: A :class:`dns.resolver.Resolver` object if dnspython
is available. Otherwise, ``None``.
"""
- if USE_DNSPYTHON:
+ if DNSPYTHON_AVAILABLE:
return dns.resolver.get_default_resolver()
return None
def resolve(host, port=None, service=None, proto='tcp',
- resolver=None, use_ipv6=True):
+ resolver=None, use_ipv6=True, use_dnspython=True):
"""Peform DNS resolution for a given hostname.
Resolution may perform SRV record lookups if a service and protocol
@@ -77,6 +77,9 @@ def resolve(host, port=None, service=None, proto='tcp',
:param use_ipv6: Optionally control the use of IPv6 in situations
where it is either not available, or performance
is degraded. Defaults to ``True``.
+ :param use_dnspython: Optionally control if dnspython is used to make
+ the DNS queries instead of the built-in DNS
+ library.
:type host: string
:type port: int
@@ -84,14 +87,22 @@ def resolve(host, port=None, service=None, proto='tcp',
:type proto: string
:type resolver: :class:`dns.resolver.Resolver`
:type use_ipv6: bool
+ :type use_dnspython: bool
:return: An iterable of IP address, port pairs in the order
dictated by SRV priorities and weights, if applicable.
"""
+
+ if not use_dnspython:
+ if DNSPYTHON_AVAILABLE:
+ log.debug("DNS: Not using dnspython, but dnspython is installed.")
+ else:
+ log.debug("DNS: Not using dnspython.")
+
if not use_ipv6:
log.debug("DNS: Use of IPv6 has been disabled.")
- if resolver is None and USE_DNSPYTHON:
+ if resolver is None and DNSPYTHON_AVAILABLE and use_dnspython:
resolver = dns.resolver.get_default_resolver()
# An IPv6 literal is allowed to be enclosed in square brackets, but
@@ -102,7 +113,7 @@ def resolve(host, port=None, service=None, proto='tcp',
try:
# If `host` is an IPv4 literal, we can return it immediately.
ipv4 = socket.inet_aton(host)
- yield (host, port)
+ yield (host, host, port)
except socket.error:
pass
@@ -112,8 +123,8 @@ def resolve(host, port=None, service=None, proto='tcp',
# it immediately.
if hasattr(socket, 'inet_pton'):
ipv6 = socket.inet_pton(socket.AF_INET6, host)
- yield (host, port)
- except socket.error:
+ yield (host, host, port)
+ except (socket.error, ValueError):
pass
# If no service was provided, then we can just do A/AAAA lookups on the
@@ -122,25 +133,29 @@ def resolve(host, port=None, service=None, proto='tcp',
if not service:
hosts = [(host, port)]
else:
- hosts = get_SRV(host, port, service, proto, resolver=resolver)
+ hosts = get_SRV(host, port, service, proto,
+ resolver=resolver,
+ use_dnspython=use_dnspython)
for host, port in hosts:
results = []
if host == 'localhost':
if use_ipv6:
- results.append(('::1', port))
- results.append(('127.0.0.1', port))
+ results.append((host, '::1', port))
+ results.append((host, '127.0.0.1', port))
if use_ipv6:
- for address in get_AAAA(host, resolver=resolver):
- results.append((address, port))
- for address in get_A(host, resolver=resolver):
- results.append((address, port))
+ for address in get_AAAA(host, resolver=resolver,
+ use_dnspython=use_dnspython):
+ results.append((host, address, port))
+ for address in get_A(host, resolver=resolver,
+ use_dnspython=use_dnspython):
+ results.append((host, address, port))
- for address, port in results:
- yield address, port
+ for host, address, port in results:
+ yield host, address, port
-def get_A(host, resolver=None):
+def get_A(host, resolver=None, use_dnspython=True):
"""Lookup DNS A records for a given host.
If ``resolver`` is not provided, or is ``None``, then resolution will
@@ -148,9 +163,13 @@ def get_A(host, resolver=None):
:param host: The hostname to resolve for A record IPv4 addresses.
:param resolver: Optional DNS resolver object to use for the query.
+ :param use_dnspython: Optionally control if dnspython is used to make
+ the DNS queries instead of the built-in DNS
+ library.
:type host: string
:type resolver: :class:`dns.resolver.Resolver` or ``None``
+ :type use_dnspython: bool
:return: A list of IPv4 literals.
"""
@@ -158,7 +177,7 @@ def get_A(host, resolver=None):
# If not using dnspython, attempt lookup using the OS level
# getaddrinfo() method.
- if resolver is None:
+ if resolver is None or not use_dnspython:
try:
recs = socket.getaddrinfo(host, None, socket.AF_INET,
socket.SOCK_STREAM)
@@ -183,7 +202,7 @@ def get_A(host, resolver=None):
return []
-def get_AAAA(host, resolver=None):
+def get_AAAA(host, resolver=None, use_dnspython=True):
"""Lookup DNS AAAA records for a given host.
If ``resolver`` is not provided, or is ``None``, then resolution will
@@ -191,9 +210,13 @@ def get_AAAA(host, resolver=None):
:param host: The hostname to resolve for AAAA record IPv6 addresses.
:param resolver: Optional DNS resolver object to use for the query.
+ :param use_dnspython: Optionally control if dnspython is used to make
+ the DNS queries instead of the built-in DNS
+ library.
:type host: string
:type resolver: :class:`dns.resolver.Resolver` or ``None``
+ :type use_dnspython: bool
:return: A list of IPv6 literals.
"""
@@ -201,12 +224,15 @@ def get_AAAA(host, resolver=None):
# If not using dnspython, attempt lookup using the OS level
# getaddrinfo() method.
- if resolver is None:
+ if resolver is None or not use_dnspython:
+ if not socket.has_ipv6:
+ log.debug("Unable to query %s for AAAA records: IPv6 is not supported", host)
+ return []
try:
recs = socket.getaddrinfo(host, None, socket.AF_INET6,
socket.SOCK_STREAM)
return [rec[4][0] for rec in recs]
- except socket.gaierror:
+ except (OSError, socket.gaierror):
log.debug("DNS: Error retreiving AAAA address " + \
"info for %s." % host)
return []
@@ -227,7 +253,7 @@ def get_AAAA(host, resolver=None):
return []
-def get_SRV(host, port, service, proto='tcp', resolver=None):
+def get_SRV(host, port, service, proto='tcp', resolver=None, use_dnspython=True):
"""Perform SRV record resolution for a given host.
.. note::
@@ -253,7 +279,7 @@ def get_SRV(host, port, service, proto='tcp', resolver=None):
:return: A list of hostname, port pairs in the order dictacted
by SRV priorities and weights.
"""
- if resolver is None:
+ if resolver is None or not use_dnspython:
log.warning("DNS: dnspython not found. Can not use SRV lookup.")
return [(host, port)]
@@ -297,7 +323,10 @@ def get_SRV(host, port, service, proto='tcp', resolver=None):
for running_sum in sums:
if running_sum >= selected:
rec = sums[running_sum]
- sorted_recs.append((rec.target.to_text(), rec.port))
+ host = rec.target.to_text()
+ if host.endswith('.'):
+ host = host[:-1]
+ sorted_recs.append((host, rec.port))
answers[priority].remove(rec)
break