Methods
Public Instance
Classes and Modules
Constants
| MAX_CACHE_SIZE | = | 512 | ||
| RESOLVE_TIMEOUT | = | [2, 3].freeze |
Public Instance methods
cached_lookup(hostname)
[show source]
# File lib/httpx/resolver.rb 75 def cached_lookup(hostname) 76 now = Utils.now 77 lookup_synchronize do |lookups, hostnames| 78 lookup(hostname, lookups, hostnames, now) 79 end 80 end
cached_lookup_evict(hostname, ip)
[show source]
# File lib/httpx/resolver.rb 110 def cached_lookup_evict(hostname, ip) 111 ip = ip.to_s 112 113 lookup_synchronize do |lookups, hostnames| 114 entries = lookups[hostname] 115 116 return unless entries 117 118 lookups.delete_if { |entry| entry["data"] == ip } 119 120 if lookups.empty? 121 lookups.delete(hostname) 122 hostnames.delete(hostname) 123 end 124 end 125 end
cached_lookup_set(hostname, family, entries)
[show source]
# File lib/httpx/resolver.rb 82 def cached_lookup_set(hostname, family, entries) 83 lookup_synchronize do |lookups, hostnames| 84 # lru cleanup 85 while lookups.size >= MAX_CACHE_SIZE 86 hs = hostnames.shift 87 lookups.delete(hs) 88 end 89 hostnames << hostname 90 91 case family 92 when Socket::AF_INET6 93 lookups[hostname].concat(entries) 94 when Socket::AF_INET 95 lookups[hostname].unshift(*entries) 96 end 97 entries.each do |entry| 98 next unless entry["name"] != hostname 99 100 case family 101 when Socket::AF_INET6 102 lookups[entry["name"]] << entry 103 when Socket::AF_INET 104 lookups[entry["name"]].unshift(entry) 105 end 106 end 107 end 108 end
decode_dns_answer(payload)
[show source]
# File lib/httpx/resolver.rb 164 def decode_dns_answer(payload) 165 begin 166 message = Resolv::DNS::Message.decode(payload) 167 rescue Resolv::DNS::DecodeError => e 168 return :decode_error, e 169 end 170 171 # no domain was found 172 return :no_domain_found if message.rcode == Resolv::DNS::RCode::NXDomain 173 174 return :message_truncated if message.tc == 1 175 176 if message.rcode != Resolv::DNS::RCode::NoError 177 case message.rcode 178 when Resolv::DNS::RCode::ServFail 179 return :retriable_error, message.rcode 180 else 181 return :dns_error, message.rcode 182 end 183 end 184 185 addresses = [] 186 187 now = Utils.now 188 message.each_answer do |question, _, value| 189 case value 190 when Resolv::DNS::Resource::IN::CNAME 191 addresses << { 192 "name" => question.to_s, 193 "TTL" => (now + value.ttl), 194 "alias" => value.name.to_s, 195 } 196 when Resolv::DNS::Resource::IN::A, 197 Resolv::DNS::Resource::IN::AAAA 198 addresses << { 199 "name" => question.to_s, 200 "TTL" => (now + value.ttl), 201 "data" => value.address.to_s, 202 } 203 end 204 end 205 206 [:ok, addresses] 207 end
encode_dns_query(hostname, type: Resolv::DNS::Resource::IN::A, message_id: generate_id)
[show source]
# File lib/httpx/resolver.rb 157 def encode_dns_query(hostname, type: Resolv::DNS::Resource::IN::A, message_id: generate_id) 158 Resolv::DNS::Message.new(message_id).tap do |query| 159 query.rd = 1 160 query.add_question(hostname, type) 161 end.encode 162 end
generate_id()
[show source]
# File lib/httpx/resolver.rb 153 def generate_id 154 id_synchronize { @identifier = (@identifier + 1) & 0xFFFF } 155 end
hosts_resolve(hostname)
matches hostname to entries in the hosts file, returns <tt>nil</nil> if none is found, or there is no hosts file.
[show source]
# File lib/httpx/resolver.rb 67 def hosts_resolve(hostname) 68 ips = @hosts_resolver.getaddresses(hostname) 69 return if ips.empty? 70 71 ips.map { |ip| Entry.new(ip) } 72 rescue IOError 73 end
id_synchronize(&block)
[show source]
# File lib/httpx/resolver.rb 213 def id_synchronize(&block) 214 @identifier_mutex.synchronize(&block) 215 end
ip_resolve(hostname)
tries to convert hostname into an IPAddr, returns nil otherwise.
[show source]
# File lib/httpx/resolver.rb 60 def ip_resolve(hostname) 61 [Entry.new(hostname)] 62 rescue ArgumentError 63 end
lookup(hostname, lookups, hostnames, ttl)
do not use directly!
[show source]
# File lib/httpx/resolver.rb 128 def lookup(hostname, lookups, hostnames, ttl) 129 return unless lookups.key?(hostname) 130 131 entries = lookups[hostname] 132 133 entries.delete_if do |address| 134 address["TTL"] < ttl 135 end 136 137 if entries.empty? 138 lookups.delete(hostname) 139 hostnames.delete(hostname) 140 end 141 142 ips = entries.flat_map do |address| 143 if (als = address["alias"]) 144 lookup(als, lookups, hostnames, ttl) 145 else 146 Entry.new(address["data"], address["TTL"]) 147 end 148 end.compact 149 150 ips unless ips.empty? 151 end
lookup_synchronize()
[show source]
# File lib/httpx/resolver.rb 209 def lookup_synchronize 210 @lookup_mutex.synchronize { yield(@lookups, @hostnames) } 211 end
nolookup_resolve(hostname)
[show source]
# File lib/httpx/resolver.rb 55 def nolookup_resolve(hostname) 56 ip_resolve(hostname) || cached_lookup(hostname) || hosts_resolve(hostname) 57 end
resolver_for(resolver_type, options)
[show source]
# File lib/httpx/resolver.rb 42 def resolver_for(resolver_type, options) 43 case resolver_type 44 when Symbol 45 meth = :"resolver_#{resolver_type}_class" 46 47 return options.__send__(meth) if options.respond_to?(meth) 48 when Class 49 return resolver_type if resolver_type < Resolver 50 end 51 52 raise Error, "unsupported resolver type (#{resolver_type})" 53 end
supported_ip_families()
[show source]
# File lib/httpx/resolver.rb 28 def supported_ip_families 29 @supported_ip_families ||= begin 30 # https://github.com/ruby/resolv/blob/095f1c003f6073730500f02acbdbc55f83d70987/lib/resolv.rb#L408 31 list = Socket.ip_address_list 32 if list.any? { |a| a.ipv6? && !a.ipv6_loopback? && !a.ipv6_linklocal? } 33 [Socket::AF_INET6, Socket::AF_INET] 34 else 35 [Socket::AF_INET] 36 end 37 rescue NotImplementedError 38 [Socket::AF_INET] 39 end.freeze 40 end