2022-11-01 12:33:17 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
class FinalDestination::Resolver
|
|
|
|
@mutex = Mutex.new
|
|
|
|
def self.lookup(addr, timeout: nil)
|
|
|
|
timeout ||= 2
|
|
|
|
@mutex.synchronize do
|
|
|
|
@result = nil
|
|
|
|
|
|
|
|
@queue ||= Queue.new
|
|
|
|
ensure_lookup_thread
|
|
|
|
|
|
|
|
@lookup = addr
|
|
|
|
@parent = Thread.current
|
|
|
|
|
2022-12-21 11:02:24 -05:00
|
|
|
# Wakeup the worker thread
|
|
|
|
@queue << ""
|
|
|
|
|
2022-11-01 12:33:17 -04:00
|
|
|
# This sleep will be interrupted by the lookup thread
|
|
|
|
# if completed within timeout
|
|
|
|
sleep timeout
|
|
|
|
if !@result
|
|
|
|
@thread.kill
|
|
|
|
@thread.join
|
|
|
|
@thread = nil
|
|
|
|
if @error
|
|
|
|
@error.backtrace.push(*caller)
|
|
|
|
raise @error
|
|
|
|
else
|
|
|
|
raise Timeout::Error
|
|
|
|
end
|
|
|
|
end
|
|
|
|
@result
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def self.ensure_lookup_thread
|
|
|
|
return if @thread&.alive?
|
|
|
|
|
|
|
|
@thread = Thread.new do
|
|
|
|
while true
|
|
|
|
@queue.deq
|
|
|
|
@error = nil
|
|
|
|
begin
|
|
|
|
@result = Addrinfo.getaddrinfo(@lookup, 80, nil, :STREAM).map(&:ip_address)
|
|
|
|
rescue => e
|
|
|
|
@error = e
|
|
|
|
end
|
|
|
|
@parent.wakeup
|
|
|
|
end
|
|
|
|
end
|
|
|
|
@thread.name = "final-destination_resolver_thread"
|
|
|
|
end
|
|
|
|
end
|