bbf6d9b026
Bugfix for feeds - removed categories related and up - load new books now working - category random now working login page is free of non accessible elements boolean custom column is vivible in UI books with only with certain languages can be shown book shelfs can be deleted from UI Anonymous user view is more resticted Added browse of series in sidebar Dependencys in vendor folder are updated to newer versions (licencs files are now present) Bugfix editing Authors names Made upload on windows working
80 lines
3.0 KiB
Python
80 lines
3.0 KiB
Python
from __future__ import absolute_import, division, print_function, with_statement
|
|
import pycares
|
|
import socket
|
|
|
|
from tornado import gen
|
|
from tornado.ioloop import IOLoop
|
|
from tornado.netutil import Resolver, is_valid_ip
|
|
|
|
|
|
class CaresResolver(Resolver):
|
|
"""Name resolver based on the c-ares library.
|
|
|
|
This is a non-blocking and non-threaded resolver. It may not produce
|
|
the same results as the system resolver, but can be used for non-blocking
|
|
resolution when threads cannot be used.
|
|
|
|
c-ares fails to resolve some names when ``family`` is ``AF_UNSPEC``,
|
|
so it is only recommended for use in ``AF_INET`` (i.e. IPv4). This is
|
|
the default for ``tornado.simple_httpclient``, but other libraries
|
|
may default to ``AF_UNSPEC``.
|
|
|
|
.. versionchanged:: 4.1
|
|
The ``io_loop`` argument is deprecated.
|
|
"""
|
|
def initialize(self, io_loop=None):
|
|
self.io_loop = io_loop or IOLoop.current()
|
|
self.channel = pycares.Channel(sock_state_cb=self._sock_state_cb)
|
|
self.fds = {}
|
|
|
|
def _sock_state_cb(self, fd, readable, writable):
|
|
state = ((IOLoop.READ if readable else 0) |
|
|
(IOLoop.WRITE if writable else 0))
|
|
if not state:
|
|
self.io_loop.remove_handler(fd)
|
|
del self.fds[fd]
|
|
elif fd in self.fds:
|
|
self.io_loop.update_handler(fd, state)
|
|
self.fds[fd] = state
|
|
else:
|
|
self.io_loop.add_handler(fd, self._handle_events, state)
|
|
self.fds[fd] = state
|
|
|
|
def _handle_events(self, fd, events):
|
|
read_fd = pycares.ARES_SOCKET_BAD
|
|
write_fd = pycares.ARES_SOCKET_BAD
|
|
if events & IOLoop.READ:
|
|
read_fd = fd
|
|
if events & IOLoop.WRITE:
|
|
write_fd = fd
|
|
self.channel.process_fd(read_fd, write_fd)
|
|
|
|
@gen.coroutine
|
|
def resolve(self, host, port, family=0):
|
|
if is_valid_ip(host):
|
|
addresses = [host]
|
|
else:
|
|
# gethostbyname doesn't take callback as a kwarg
|
|
self.channel.gethostbyname(host, family, (yield gen.Callback(1)))
|
|
callback_args = yield gen.Wait(1)
|
|
assert isinstance(callback_args, gen.Arguments)
|
|
assert not callback_args.kwargs
|
|
result, error = callback_args.args
|
|
if error:
|
|
raise Exception('C-Ares returned error %s: %s while resolving %s' %
|
|
(error, pycares.errno.strerror(error), host))
|
|
addresses = result.addresses
|
|
addrinfo = []
|
|
for address in addresses:
|
|
if '.' in address:
|
|
address_family = socket.AF_INET
|
|
elif ':' in address:
|
|
address_family = socket.AF_INET6
|
|
else:
|
|
address_family = socket.AF_UNSPEC
|
|
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, (address, port)))
|
|
raise gen.Return(addrinfo)
|