Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
caresresolver.py95 linesDownload Raw Back to platform
1import pycares  # type: ignore
2import socket
3
4from tornado.concurrent import Future
5from tornado import gen
6from tornado.ioloop import IOLoop
7from tornado.netutil import Resolver, is_valid_ip
8
9import typing
10
11if typing.TYPE_CHECKING:
12    from typing import Generator, Any, List, Tuple, Dict  # noqa: F401
13
14
15class CaresResolver(Resolver):
16    """Name resolver based on the c-ares library.
17
18    This is a non-blocking and non-threaded resolver.  It may not produce the
19    same results as the system resolver, but can be used for non-blocking
20    resolution when threads cannot be used.
21
22    ``pycares`` will not return a mix of ``AF_INET`` and ``AF_INET6`` when
23    ``family`` is ``AF_UNSPEC``, so it is only recommended for use in
24    ``AF_INET`` (i.e. IPv4).  This is the default for
25    ``tornado.simple_httpclient``, but other libraries may default to
26    ``AF_UNSPEC``.
27
28    .. versionchanged:: 5.0
29       The ``io_loop`` argument (deprecated since version 4.1) has been removed.
30
31    .. deprecated:: 6.2
32       This class is deprecated and will be removed in Tornado 7.0. Use the default
33       thread-based resolver instead.
34    """
35
36    def initialize(self) -> None:
37        self.io_loop = IOLoop.current()
38        self.channel = pycares.Channel(sock_state_cb=self._sock_state_cb)
39        self.fds = {}  # type: Dict[int, int]
40
41    def _sock_state_cb(self, fd: int, readable: bool, writable: bool) -> None:
42        state = (IOLoop.READ if readable else 0) | (IOLoop.WRITE if writable else 0)
43        if not state:
44            self.io_loop.remove_handler(fd)
45            del self.fds[fd]
46        elif fd in self.fds:
47            self.io_loop.update_handler(fd, state)
48            self.fds[fd] = state
49        else:
50            self.io_loop.add_handler(fd, self._handle_events, state)
51            self.fds[fd] = state
52
53    def _handle_events(self, fd: int, events: int) -> None:
54        read_fd = pycares.ARES_SOCKET_BAD
55        write_fd = pycares.ARES_SOCKET_BAD
56        if events & IOLoop.READ:
57            read_fd = fd
58        if events & IOLoop.WRITE:
59            write_fd = fd
60        self.channel.process_fd(read_fd, write_fd)
61
62    @gen.coroutine
63    def resolve(
64        self, host: str, port: int, family: int = 0
65    ) -> "Generator[Any, Any, List[Tuple[int, Any]]]":
66        if is_valid_ip(host):
67            addresses = [host]
68        else:
69            # gethostbyname doesn't take callback as a kwarg
70            fut = Future()  # type: Future[Tuple[Any, Any]]
71            self.channel.gethostbyname(
72                host, family, lambda result, error: fut.set_result((result, error))
73            )
74            result, error = yield fut
75            if error:
76                raise OSError(
77                    "C-Ares returned error %s: %s while resolving %s"
78                    % (error, pycares.errno.strerror(error), host)
79                )
80            addresses = result.addresses
81        addrinfo = []
82        for address in addresses:
83            if "." in address:
84                address_family = socket.AF_INET
85            elif ":" in address:
86                address_family = socket.AF_INET6
87            else:
88                address_family = socket.AF_UNSPEC
89            if family != socket.AF_UNSPEC and family != address_family:
90                raise OSError(
91                    "Requested socket family %d but got %d" % (family, address_family)
92                )
93            addrinfo.append((typing.cast(int, address_family), (address, port)))
94        return addrinfo
95 
codekingpro/portable-devtools · Team Ai