Class: UringMachine::DNSResolver

Inherits:
Object
  • Object
show all
Defined in:
lib/uringmachine/dns_resolver.rb

Instance Method Summary collapse

Constructor Details

#initialize(machine) ⇒ DNSResolver

Returns a new instance of DNSResolver.



7
8
9
10
11
12
13
# File 'lib/uringmachine/dns_resolver.rb', line 7

def initialize(machine)
  @machine = machine
  @requests = UM::Queue.new
  @nameservers = get_nameservers
  @fiber = @machine.spin { handle_requests_loop }
  @last_id = 0
end

Instance Method Details

#do_resolve(hostname, type, try_count = 0) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/uringmachine/dns_resolver.rb', line 49

def do_resolve(hostname, type, try_count = 0)
  fd = socket_fd
  req = prepare_request_packet(hostname, type)
  msg = req.encode
  @machine.send(fd, msg, msg.bytesize, 0)

  buf = +''
  @machine.recv(fd, buf, 16384, 0)

  msg = Resolv::DNS::Message.decode buf
  addrs = []
  msg.each_answer do |name, ttl, data|
    # p [name, ttl, data]
    if data.kind_of?(Resolv::DNS::Resource::IN::A) ||
      data.kind_of?(Resolv::DNS::Resource::IN::AAAA)
      addrs << data.address.to_s
    end
  end
  addrs
end

#get_nameserversObject



28
29
30
31
32
33
34
35
36
# File 'lib/uringmachine/dns_resolver.rb', line 28

def get_nameservers
  nameservers = []
  IO.readlines('/etc/resolv.conf').each do |line|
    if line =~ /^nameserver (.+)$/
      nameservers << $1.split(/\s+/).first
    end
  end
  nameservers
end

#handle_requests_loopObject



20
21
22
23
24
25
26
# File 'lib/uringmachine/dns_resolver.rb', line 20

def handle_requests_loop
  while true
    hostname, type, fiber = @machine.shift(@requests)
    res = do_resolve(hostname, type)
    @machine.schedule(fiber, res)
  end
end

#msg_type(type) ⇒ Object



78
79
80
81
# File 'lib/uringmachine/dns_resolver.rb', line 78

def msg_type(type)
  # TODO: add support for other types
  Resolv::DNS::Resource::IN::A
end

#prepare_request_packet(hostname, type) ⇒ Object



70
71
72
73
74
75
76
# File 'lib/uringmachine/dns_resolver.rb', line 70

def prepare_request_packet(hostname, type)
  msg = Resolv::DNS::Message.new
  msg.id = (@last_id += 1)
  msg.rd = 1
  msg.add_question hostname, msg_type(type)
  msg
end

#prepare_socketObject



42
43
44
45
46
47
# File 'lib/uringmachine/dns_resolver.rb', line 42

def prepare_socket
  fd = @machine.socket(UM::AF_INET, UM::SOCK_DGRAM, 0, 0)
  @machine.bind(fd, '0.0.0.0', 0)
  @machine.connect(fd, @nameservers.sample, 53)
  fd
end

#resolve(hostname, type) ⇒ Object



15
16
17
18
# File 'lib/uringmachine/dns_resolver.rb', line 15

def resolve(hostname, type)
  @machine.push(@requests, [hostname, type, Fiber.current])
  @machine.yield
end

#socket_fdObject



38
39
40
# File 'lib/uringmachine/dns_resolver.rb', line 38

def socket_fd
  @socket_fd ||= prepare_socket
end