def gethostbyname(hostname): """:func:`socket.gethostbyname` implemented using :mod:`gevent.dns`. Differs in the following ways: * raises :class:`DNSError` (a subclass of :class:`socket.gaierror`) with dns error codes instead of standard socket error codes * does not support ``/etc/hosts`` but calls the original :func:`socket.gethostbyname` if *hostname* has no dots * does not iterate through all addresses, instead picks a random one each time """ # TODO: this is supposed to iterate through all the addresses # could use a global dict(hostname, iter) # - fix these nasty hacks for localhost, ips, etc. if not isinstance(hostname, str) or '.' not in hostname: return _socket.gethostbyname(hostname) if _ip4_re.match(hostname): return hostname if hostname == _socket.gethostname(): return _socket.gethostbyname(hostname) addrs = None try: _ttl, addrs = resolve_ipv4(hostname) except: _ttl, addrs = resolve_ipv6(hostname) return inet_ntop(AF_INET6, random.choice(addrs)) else: return inet_ntop(AF_INET, random.choice(addrs))
def getaddrinfo(host, port, *args, **kwargs): """*Some* approximation of :func:`socket.getaddrinfo` implemented using :mod:`gevent.dns`. If *host* is not a string, does not has any dots or is a numeric IP address, then the standard :func:`socket.getaddrinfo` is called. Otherwise, calls either :func:`resolve_ipv4` or :func:`resolve_ipv6` and formats the result the way :func:`socket.getaddrinfo` does it. Differs in the following ways: * raises :class:`DNSError` (a subclass of :class:`gaierror`) with libevent-dns error codes instead of standard socket error codes * IPv6 support is untested. * AF_UNSPEC only tries IPv4 * only supports TCP, UDP, IP protocols * port must be numeric, does not support string service names. see socket.getservbyname * *flags* argument is ignored Additionally, supports *evdns_flags* keyword arguments (default ``0``) that is passed to :mod:`dns` functions. """ family, socktype, proto, _flags = args + (None, ) * (4 - len(args)) if not isinstance(host, str) or '.' not in host or _ip4_re.match(host): return _socket.getaddrinfo(host, port, *args) evdns_flags = kwargs.pop('evdns_flags', 0) if kwargs: raise TypeError('Unsupported keyword arguments: %s' % (kwargs.keys(), )) if family in (None, AF_INET, AF_UNSPEC): family = AF_INET # TODO: AF_UNSPEC means try both AF_INET and AF_INET6 _ttl, addrs = resolve_ipv4(host, evdns_flags) elif family == AF_INET6: _ttl, addrs = resolve_ipv6(host, evdns_flags) else: raise NotImplementedError( 'family is not among AF_UNSPEC/AF_INET/AF_INET6: %r' % (family, )) socktype_proto = [(SOCK_STREAM, 6), (SOCK_DGRAM, 17), (SOCK_RAW, 0)] if socktype is not None: socktype_proto = [(x, y) for (x, y) in socktype_proto if socktype == x] if proto is not None: socktype_proto = [(x, y) for (x, y) in socktype_proto if proto == y] result = [] for addr in addrs: for socktype, proto in socktype_proto: result.append( (family, socktype, proto, '', (inet_ntop(family, addr), port))) return result
def getaddrinfo(host, port, *args, **kwargs): """*Some* approximation of :func:`socket.getaddrinfo` implemented using :mod:`gevent.dns`. If *host* is not a string, does not has any dots or is a numeric IP address, then the standard :func:`socket.getaddrinfo` is called. Otherwise, calls either :func:`resolve_ipv4` or :func:`resolve_ipv6` and formats the result the way :func:`socket.getaddrinfo` does it. Differs in the following ways: * raises :class:`DNSError` (a subclass of :class:`gaierror`) with libevent-dns error codes instead of standard socket error codes * IPv6 support is untested. * AF_UNSPEC only tries IPv4 * only supports TCP, UDP, IP protocols * port must be numeric, does not support string service names. see socket.getservbyname * *flags* argument is ignored Additionally, supports *evdns_flags* keyword arguments (default ``0``) that is passed to :mod:`dns` functions. """ family, socktype, proto, _flags = args + (None, ) * (4 - len(args)) if isinstance(host, unicode): host = host.encode('idna') if not isinstance(host, str) or '.' not in host or _ip4_re.match(host): return _socket.getaddrinfo(host, port, *args) evdns_flags = kwargs.pop('evdns_flags', 0) if kwargs: raise TypeError('Unsupported keyword arguments: %s' % (kwargs.keys(), )) if family in (None, AF_INET, AF_UNSPEC): family = AF_INET # TODO: AF_UNSPEC means try both AF_INET and AF_INET6 _ttl, addrs = resolve_ipv4(host, evdns_flags) elif family == AF_INET6: _ttl, addrs = resolve_ipv6(host, evdns_flags) else: raise NotImplementedError('family is not among AF_UNSPEC/AF_INET/AF_INET6: %r' % (family, )) socktype_proto = [(SOCK_STREAM, 6), (SOCK_DGRAM, 17), (SOCK_RAW, 0)] if socktype: socktype_proto = [(x, y) for (x, y) in socktype_proto if socktype == x] if proto: socktype_proto = [(x, y) for (x, y) in socktype_proto if proto == y] result = [] for addr in addrs: for socktype, proto in socktype_proto: result.append((family, socktype, proto, '', (inet_ntop(family, addr), port))) return result
if socktype: socktype_proto = [(x, y) for (x, y) in socktype_proto if socktype == x] if proto: socktype_proto = [(x, y) for (x, y) in socktype_proto if proto == y] result = [] if family == AF_INET: for res in resolve_ipv4(host, evdns_flags)[1]: sockaddr = (inet_ntop(family, res), port) for socktype, proto in socktype_proto: result.append((family, socktype, proto, '', sockaddr)) elif family == AF_INET6: for res in resolve_ipv6(host, evdns_flags)[1]: sockaddr = (inet_ntop(family, res), port, 0, 0) for socktype, proto in socktype_proto: result.append((family, socktype, proto, '', sockaddr)) else: ipv4_res = None ipv6_res = None try: ipv4_res = resolve_ipv4(host, evdns_flags)[1] except: pass if not ipv4_res: ipv4_res = None ipv6_res = resolve_ipv6(host, evdns_flags)[1]
socktype_proto = [(SOCK_STREAM, 6), (SOCK_DGRAM, 17), (SOCK_RAW, 0)] if socktype: socktype_proto = [(x, y) for (x, y) in socktype_proto if socktype == x] if proto: socktype_proto = [(x, y) for (x, y) in socktype_proto if proto == y] result = [] if family == AF_INET: for res in resolve_ipv4(host, evdns_flags)[1]: sockaddr = (inet_ntop(family, res), port) for socktype, proto in socktype_proto: result.append((family, socktype, proto, '', sockaddr)) elif family == AF_INET6: for res in resolve_ipv6(host, evdns_flags)[1]: sockaddr = (inet_ntop(family, res), port, 0, 0) for socktype, proto in socktype_proto: result.append((family, socktype, proto, '', sockaddr)) else: failure = None job = spawn(wrap_errors(gaierror, resolve_ipv6), host, evdns_flags) try: try: ipv4_res = resolve_ipv4(host, evdns_flags)[1] except gaierror, failure: ipv4_res = None ipv6_res = job.get() if isinstance(ipv6_res, gaierror): ipv6_res = None if failure is not None: