rex-core 0.1.36 → 0.1.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/rex/core/version.rb +1 -1
- data/lib/rex/io/fiber_scheduler.rb +46 -21
- data/lib/rex/io/relay_manager.rb +70 -13
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c1b69ef9a2e48921a8f6102041c3ee29b4de5004e74874966827cc6707d0eb13
|
|
4
|
+
data.tar.gz: e6b9f06e4e58e33e448b4119e337bcc36a1a23724655119ffef9dba983c910b1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fbda8aea3da6fd99b2a80ffb0164d3af1f156f1b36823ed5e3816bd65583b280e7d51651a5f89d9702cdb5fe8b086d9393e8ece32606b89a7cd2822a6ad34b25
|
|
7
|
+
data.tar.gz: e521512ef7be86e68d46afb39497c2d128033a5642140327a7d723b391dc848a40579112c2c2a7d8acea12ab8a7b8f7a5bf79510f489f50094c1725588adaa37
|
data/lib/rex/core/version.rb
CHANGED
|
@@ -15,29 +15,25 @@ module IO
|
|
|
15
15
|
@ready = []
|
|
16
16
|
@pending = []
|
|
17
17
|
@blocking = 0
|
|
18
|
-
@urgent =
|
|
18
|
+
@urgent = nil
|
|
19
19
|
@mutex = Mutex.new
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
# This allows the fiber to be scheduled in the #run thread from another thread
|
|
23
23
|
def schedule_fiber(&block)
|
|
24
24
|
@mutex.synchronize do
|
|
25
|
+
@urgent ||= Rex::Compat.pipe
|
|
25
26
|
@pending << block
|
|
27
|
+
# Wake up the scheduler while holding the same lock used by #reset! so
|
|
28
|
+
# the signaling pipe cannot be replaced between lookup and write.
|
|
29
|
+
@urgent.last.write_nonblock('.', exception: false)
|
|
26
30
|
end
|
|
27
|
-
# Wake up the scheduler
|
|
28
|
-
@urgent.last.write_nonblock('.') rescue nil
|
|
29
31
|
end
|
|
30
32
|
|
|
31
33
|
def run
|
|
32
34
|
while @readable.any? or @writable.any? or @waiting.any? or @blocking.positive? or @ready.any? or @pending.any?
|
|
33
35
|
# Start any pending fibers
|
|
34
|
-
|
|
35
|
-
@mutex.synchronize do
|
|
36
|
-
pending_blocks = @pending.dup
|
|
37
|
-
@pending.clear
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
pending_blocks.each do |block|
|
|
36
|
+
while (block = @mutex.synchronize { @pending.shift })
|
|
41
37
|
fiber = Fiber.new(blocking: false, &block)
|
|
42
38
|
fiber.resume
|
|
43
39
|
end
|
|
@@ -75,8 +71,7 @@ module IO
|
|
|
75
71
|
end
|
|
76
72
|
end
|
|
77
73
|
|
|
78
|
-
|
|
79
|
-
ready.each do |fiber|
|
|
74
|
+
while (fiber = @mutex.synchronize { @ready.shift })
|
|
80
75
|
fiber.resume
|
|
81
76
|
end
|
|
82
77
|
end
|
|
@@ -118,19 +113,40 @@ module IO
|
|
|
118
113
|
end
|
|
119
114
|
|
|
120
115
|
def unblock(blocker, fiber)
|
|
121
|
-
@
|
|
122
|
-
|
|
123
|
-
|
|
116
|
+
@mutex.synchronize do
|
|
117
|
+
return false unless @urgent
|
|
118
|
+
|
|
119
|
+
@ready << fiber
|
|
120
|
+
@urgent.last.write_nonblock('.', exception: false)
|
|
121
|
+
end
|
|
124
122
|
end
|
|
125
123
|
|
|
126
124
|
def close
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
125
|
+
first_error = nil
|
|
126
|
+
|
|
127
|
+
loop do
|
|
128
|
+
begin
|
|
129
|
+
run
|
|
130
|
+
break
|
|
131
|
+
rescue StandardError => e
|
|
132
|
+
first_error ||= e
|
|
133
|
+
break unless work_pending?
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
raise first_error if first_error
|
|
138
|
+
ensure
|
|
139
|
+
close_urgent_pipe
|
|
130
140
|
end
|
|
131
141
|
|
|
132
142
|
def closed?
|
|
133
|
-
@urgent.nil?
|
|
143
|
+
@mutex.synchronize { @urgent.nil? }
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def work_pending?
|
|
147
|
+
@mutex.synchronize do
|
|
148
|
+
@readable.any? || @writable.any? || @waiting.any? || @blocking.positive? || @ready.any? || @pending.any?
|
|
149
|
+
end
|
|
134
150
|
end
|
|
135
151
|
|
|
136
152
|
def reset!
|
|
@@ -141,7 +157,7 @@ module IO
|
|
|
141
157
|
@ready.clear
|
|
142
158
|
@pending.clear
|
|
143
159
|
@blocking = 0
|
|
144
|
-
|
|
160
|
+
close_urgent_pipe_without_lock
|
|
145
161
|
end
|
|
146
162
|
end
|
|
147
163
|
|
|
@@ -153,6 +169,15 @@ module IO
|
|
|
153
169
|
|
|
154
170
|
private
|
|
155
171
|
|
|
172
|
+
def close_urgent_pipe
|
|
173
|
+
@mutex.synchronize { close_urgent_pipe_without_lock }
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def close_urgent_pipe_without_lock
|
|
177
|
+
@urgent&.each { |io| io.close unless io.closed? }
|
|
178
|
+
@urgent = nil
|
|
179
|
+
end
|
|
180
|
+
|
|
156
181
|
def current_time
|
|
157
182
|
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
158
183
|
end
|
|
@@ -165,4 +190,4 @@ module IO
|
|
|
165
190
|
end
|
|
166
191
|
|
|
167
192
|
end
|
|
168
|
-
end
|
|
193
|
+
end
|
data/lib/rex/io/relay_manager.rb
CHANGED
|
@@ -11,6 +11,10 @@ class RelayManager
|
|
|
11
11
|
def initialize
|
|
12
12
|
@thread = nil
|
|
13
13
|
@scheduler = FiberScheduler.new
|
|
14
|
+
@mutex = Mutex.new
|
|
15
|
+
@teardown_condition = ConditionVariable.new
|
|
16
|
+
@tearing_down = false
|
|
17
|
+
@running = false
|
|
14
18
|
end
|
|
15
19
|
|
|
16
20
|
# Add a IO relay to the manager. This will start relaying data from the source
|
|
@@ -26,11 +30,24 @@ class RelayManager
|
|
|
26
30
|
# @param name [String] A human-friendly name for the relay used in debug output.
|
|
27
31
|
# @param on_exit [#call] A callback to be invoked when sink can no longer be read from.
|
|
28
32
|
def add_relay(sock, sink: nil, name: nil, on_exit: nil)
|
|
29
|
-
@
|
|
30
|
-
|
|
33
|
+
@mutex.synchronize do
|
|
34
|
+
# An external caller that arrives during worker teardown waits until the
|
|
35
|
+
# scheduler is reusable. A callback on the worker itself must remain
|
|
36
|
+
# nonblocking; the scheduler's final run will process its accepted work.
|
|
37
|
+
while @tearing_down && Thread.current != @thread
|
|
38
|
+
@teardown_condition.wait(@mutex)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
start_gate = start unless running?
|
|
42
|
+
|
|
43
|
+
begin
|
|
44
|
+
@scheduler.schedule_fiber do
|
|
45
|
+
relay_fiber(sock, sink, name, on_exit: on_exit)
|
|
46
|
+
end
|
|
47
|
+
ensure
|
|
48
|
+
start_gate << true if start_gate
|
|
49
|
+
end
|
|
31
50
|
end
|
|
32
|
-
|
|
33
|
-
start unless running?
|
|
34
51
|
end
|
|
35
52
|
|
|
36
53
|
# Write all data to the specified IO. This is intended to be used in scenarios
|
|
@@ -51,26 +68,66 @@ class RelayManager
|
|
|
51
68
|
private
|
|
52
69
|
|
|
53
70
|
def running?
|
|
54
|
-
@
|
|
71
|
+
@running
|
|
55
72
|
end
|
|
56
73
|
|
|
57
74
|
def start
|
|
58
|
-
return
|
|
75
|
+
return nil if running?
|
|
59
76
|
|
|
60
|
-
|
|
61
|
-
true
|
|
77
|
+
start_gate = Queue.new
|
|
78
|
+
@running = true
|
|
79
|
+
@thread = Thread.new do
|
|
80
|
+
start_gate.pop
|
|
81
|
+
run
|
|
82
|
+
end
|
|
83
|
+
start_gate
|
|
84
|
+
rescue StandardError
|
|
85
|
+
@running = false
|
|
86
|
+
raise
|
|
62
87
|
end
|
|
63
88
|
|
|
64
89
|
def run
|
|
90
|
+
teardown_started = false
|
|
65
91
|
old_scheduler = Fiber.scheduler
|
|
66
92
|
# A fiber scheduler can be set per-thread
|
|
67
93
|
Fiber.set_scheduler(@scheduler)
|
|
68
94
|
|
|
69
|
-
|
|
70
|
-
|
|
95
|
+
loop do
|
|
96
|
+
# Run the scheduler (blocks here)
|
|
97
|
+
@scheduler.run
|
|
98
|
+
|
|
99
|
+
# #add_relay schedules and tests @running while holding this same lock.
|
|
100
|
+
# If it won the race after the scheduler observed an empty queue, process
|
|
101
|
+
# its accepted work before committing this worker to teardown.
|
|
102
|
+
teardown_started = @mutex.synchronize do
|
|
103
|
+
if @scheduler.work_pending?
|
|
104
|
+
false
|
|
105
|
+
else
|
|
106
|
+
@tearing_down = true
|
|
107
|
+
true
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
break if teardown_started
|
|
111
|
+
end
|
|
71
112
|
ensure
|
|
72
|
-
|
|
73
|
-
|
|
113
|
+
# On an exceptional exit, commit to teardown before removing the scheduler.
|
|
114
|
+
# External submissions then wait; callbacks on this worker remain able to
|
|
115
|
+
# schedule work for the scheduler's final run.
|
|
116
|
+
@mutex.synchronize { @tearing_down = true } unless teardown_started
|
|
117
|
+
|
|
118
|
+
begin
|
|
119
|
+
Fiber.set_scheduler(old_scheduler)
|
|
120
|
+
ensure
|
|
121
|
+
begin
|
|
122
|
+
@scheduler.reset!
|
|
123
|
+
ensure
|
|
124
|
+
@mutex.synchronize do
|
|
125
|
+
@running = false
|
|
126
|
+
@tearing_down = false
|
|
127
|
+
@teardown_condition.broadcast
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
74
131
|
end
|
|
75
132
|
|
|
76
133
|
def relay_fiber(sock, sink, name, on_exit: nil)
|
|
@@ -111,4 +168,4 @@ class RelayManager
|
|
|
111
168
|
end
|
|
112
169
|
|
|
113
170
|
end
|
|
114
|
-
end
|
|
171
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rex-core
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.37
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Metasploit Hackers
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-10-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rake
|