Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

# -*- coding: utf-8 -*- 

 

# extended from https://github.com/tornadoweb/tornado/blob/master/tornado/platform/caresresolver.py 

 

import pycares 

import socket 

 

from tornado import gen 

from tornado.ioloop import IOLoop 

from tornado.netutil import Resolver, is_valid_ip 

 

class AsyncResolver(Resolver): 

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) 

 

@gen.coroutine 

def gethostbyaddr(self, host): 

if is_valid_ip(host): 

self.channel.gethostbyaddr(host, (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)) 

raise gen.Return(result.name) 

else: 

raise gen.Return(host)