34 lines
1.2 KiB
Ruby
34 lines
1.2 KiB
Ruby
module Msf::Exploit::Retry
|
|
# Retry the block until it returns a truthy value. Each iteration attempt will
|
|
# be performed with an exponential backoff. If the timeout period surpasses,
|
|
# nil is returned.
|
|
#
|
|
# @param Integer timeout the number of seconds to wait before the operation times out
|
|
# @return the truthy value of the block is returned or nil if it timed out
|
|
def retry_until_truthy(timeout:)
|
|
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
|
|
ending_time = start_time + timeout
|
|
retry_count = 0
|
|
while Process.clock_gettime(Process::CLOCK_MONOTONIC, :second) < ending_time
|
|
result = yield
|
|
return result if result
|
|
|
|
retry_count += 1
|
|
remaining_time_budget = ending_time - Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
|
|
break if remaining_time_budget <= 0
|
|
|
|
delay = 2**retry_count
|
|
if delay >= remaining_time_budget
|
|
delay = remaining_time_budget
|
|
vprint_status("Final attempt. Sleeping for the remaining #{delay} seconds out of total timeout #{timeout}")
|
|
else
|
|
vprint_status("Sleeping for #{delay} seconds before attempting again")
|
|
end
|
|
|
|
sleep delay
|
|
end
|
|
|
|
nil
|
|
end
|
|
end
|