예제 #1
0
    def getaddrinfo(self, host, port, family=0, socktype=0, proto=0, flags=0):
        if ((host in (u'localhost', b'localhost')
             or (is_ipv6_addr(host) and host.startswith('fe80')))
                or not isinstance(host, str) or (flags & AI_NUMERICHOST)):
            # this handles cases which do not require network access
            # 1) host is None
            # 2) host is of an invalid type
            # 3) host is localhost or a link-local ipv6; dnspython returns the wrong
            #    scope-id for those.
            # 3) AI_NUMERICHOST flag is set

            return _socket.getaddrinfo(host, port, family, socktype, proto, flags)

        if family == AF_UNSPEC:
            # This tends to raise in the case that a v6 address did not exist
            # but a v4 does. So we break it into two parts.

            # Note that if there is no ipv6 in the hosts file, but there *is*
            # an ipv4, and there *is* an ipv6 in the nameservers, we will return
            # both (from the first call). The system resolver on OS X only returns
            # the results from the hosts file. doubleclick.com is one example.

            # See also https://github.com/gevent/gevent/issues/1012
            try:
                return _getaddrinfo(host, port, family, socktype, proto, flags)
            except socket.gaierror:
                try:
                    return _getaddrinfo(host, port, AF_INET6, socktype, proto, flags)
                except socket.gaierror:
                    return _getaddrinfo(host, port, AF_INET, socktype, proto, flags)
        else:
            return _getaddrinfo(host, port, family, socktype, proto, flags)
예제 #2
0
    def load(self):  # pylint:disable=too-many-locals
        # Load hosts file

        # This will (re)load the data from the hosts
        # file if it has changed.

        try:
            load_time = os.stat(self.fname).st_mtime
            needs_load = load_time > self._last_load
        except (IOError, OSError):
            from gevent import get_hub
            get_hub().handle_error(self, *sys.exc_info())
            needs_load = False

        if not needs_load:
            return

        v4 = {}
        v6 = {}
        aliases = {}
        reverse = {}

        for line in self._readlines():
            parts = line.split()
            if len(parts) < 2:
                continue
            ip = parts.pop(0)
            if is_ipv4_addr(ip):
                ipmap = v4
            elif is_ipv6_addr(ip):
                if ip.startswith('fe80'):
                    # Do not use link-local addresses, OSX stores these here
                    continue
                ipmap = v6
            else:
                continue
            cname = parts.pop(0).lower()
            ipmap[cname] = ip
            for alias in parts:
                alias = alias.lower()
                ipmap[alias] = ip
                aliases[alias] = cname

            # XXX: This is wrong for ipv6
            if ipmap is v4:
                ptr = '.'.join(reversed(ip.split('.'))) + '.in-addr.arpa'
            else:
                ptr = ip + '.ip6.arpa.'
            if ptr not in reverse:
                reverse[ptr] = cname

        self._last_load = load_time
        self.v4 = v4
        self.v6 = v6
        self.aliases = aliases
        self.reverse = reverse
예제 #3
0
    def getaddrinfo(self, host, port, family=0, socktype=0, proto=0, flags=0):
        host = self._hostname_to_bytes(host) if host is not None else None

        if (not isinstance(host, bytes)  # 1, 2
                or (flags & AI_NUMERICHOST)  # 3
                or host in self._LOCAL_HOSTNAMES  # 4
                or (is_ipv6_addr(host) and host.startswith(b'fe80'))  # 5
            ):
            # This handles cases which do not require network access
            # 1) host is None
            # 2) host is of an invalid type
            # 3) AI_NUMERICHOST flag is set
            # 4) It's a well-known alias. TODO: This is special casing for c-ares that we don't
            #    really want to do. It's here because it resolves a discrepancy with the system
            #    resolvers caught by test cases. In gevent 20.4.0, this only worked correctly on
            #    Python 3 and not Python 2, by accident.
            # 5) host is a link-local ipv6; dnspython returns the wrong
            #    scope-id for those.
            return native_getaddrinfo(host, port, family, socktype, proto,
                                      flags)

        return self._getaddrinfo(host, port, family, socktype, proto, flags)