forked from rapid7/metasploit-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpacket_response_waiter.rb
104 lines (87 loc) · 2.33 KB
/
packet_response_waiter.rb
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# -*- coding: binary -*-
require 'timeout'
require 'thread'
module Rex
module Post
module Meterpreter
###
#
# This class handles waiting for a response to a given request
# and the subsequent response association.
#
###
class PacketResponseWaiter
# Arbitrary argument to {#completion_routine}
#
# @return [Object,nil]
attr_accessor :completion_param
# A callback to be called when this waiter is notified of a packet's
# arrival. If not nil, this will be called with the response packet as first
# parameter and {#completion_param} as the second.
#
# @return [Proc,nil]
attr_accessor :completion_routine
# @return [ConditionVariable]
attr_accessor :cond
# @return [Mutex]
attr_accessor :mutex
# @return [Packet]
attr_accessor :response
# @return [Integer] request ID to wait for
attr_accessor :rid
#
# Initializes a response waiter instance for the supplied request
# identifier.
#
def initialize(rid, completion_routine = nil, completion_param = nil)
self.rid = rid.dup
self.response = nil
if (completion_routine)
self.completion_routine = completion_routine
self.completion_param = completion_param
else
self.mutex = Mutex.new
self.cond = ConditionVariable.new
end
end
#
# Checks to see if this waiter instance is waiting for the supplied
# packet based on its request identifier.
#
def waiting_for?(packet)
return (packet.rid == rid)
end
#
# Notifies the waiter that the supplied response packet has arrived.
#
# @param response [Packet]
# @return [void]
def notify(response)
if (self.completion_routine)
self.response = response
self.completion_routine.call(response, self.completion_param)
else
self.mutex.synchronize do
self.response = response
self.cond.signal
end
end
end
#
# Wait for a given time interval for the response packet to arrive.
#
# @param interval [Integer,nil] number of seconds to wait, or nil to wait
# forever
# @return [Packet,nil] the response, or nil if the interval elapsed before
# receiving one
def wait(interval)
interval = nil if interval and interval == -1
self.mutex.synchronize do
if self.response.nil?
self.cond.wait(self.mutex, interval)
end
end
return self.response
end
end
end; end; end