rex-core 0.1.1 → 0.1.2
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
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +3 -2
- data/lib/rex/core/version.rb +1 -1
- data/lib/rex/exceptions.rb +307 -0
- data/lib/rex/io/datagram_abstraction.rb +26 -0
- data/lib/rex/io/ring_buffer.rb +369 -0
- data/lib/rex/io/socket_abstraction.rb +205 -0
- data/lib/rex/io/stream.rb +312 -0
- data/lib/rex/io/stream_abstraction.rb +32 -0
- data/lib/rex/io/stream_server.rb +221 -0
- data/lib/rex/sync.rb +6 -0
- data/lib/rex/sync/event.rb +85 -0
- data/lib/rex/sync/read_write_lock.rb +177 -0
- data/lib/rex/sync/ref.rb +58 -0
- data/lib/rex/sync/thread_safe.rb +83 -0
- metadata +14 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63a58cfcf3d6b9062c2bdca3eefca305eca585c7
|
4
|
+
data.tar.gz: 4185786772da9b7207faac16ad71fc808914ca83
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a0a38f7fd810b004bec6aca74ed6101fd01c3d2473256c1c510acd840047e8887560a4c6cca8c0f7d03650a2e33d6b2eae39cf588704cb6ff177da0282b50b46
|
7
|
+
data.tar.gz: e977b465922469f9682a6c91065ce5fc2c0cf50a356f0f643a986166689dea6499e96e6421cb752df62b644c1797d9c633e54ecb1d32c379ded339a66fed92ba
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
@@ -1,2 +1,3 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
�+�^e�L��Ĺ��_�� �kj�N迒�T$Rr3]�t�36x� "�DJ*��%B���b���O���æh��R*YS�|�r�����<��r
|
2
|
+
�-^��`��n��`f�{�-K}��P�]���B�\FtBD5���z��M�)�X�l�����\�N'�Q��
|
3
|
+
P���)46�P1 N⮏�V�h���B
|
data/lib/rex/core/version.rb
CHANGED
@@ -0,0 +1,307 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
|
3
|
+
module Rex
|
4
|
+
|
5
|
+
###
|
6
|
+
#
|
7
|
+
# Base mixin for all exceptions that can be thrown from inside Rex.
|
8
|
+
#
|
9
|
+
###
|
10
|
+
module Exception
|
11
|
+
end
|
12
|
+
|
13
|
+
###
|
14
|
+
#
|
15
|
+
# This exception is raised when a timeout occurs.
|
16
|
+
#
|
17
|
+
###
|
18
|
+
class TimeoutError < Interrupt
|
19
|
+
include Exception
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"Operation timed out."
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
###
|
27
|
+
#
|
28
|
+
# This exception is raised when a method is called or a feature is used that
|
29
|
+
# is not implemented.
|
30
|
+
#
|
31
|
+
###
|
32
|
+
class NotImplementedError < ::NotImplementedError
|
33
|
+
include Exception
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
"The requested method is not implemented."
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
###
|
41
|
+
#
|
42
|
+
# This exception is raised when a generalized runtime error occurs.
|
43
|
+
#
|
44
|
+
###
|
45
|
+
class RuntimeError < ::RuntimeError
|
46
|
+
include Exception
|
47
|
+
end
|
48
|
+
|
49
|
+
###
|
50
|
+
#
|
51
|
+
# This exception is raised when an invalid argument is supplied to a method.
|
52
|
+
#
|
53
|
+
###
|
54
|
+
class ArgumentError < ::ArgumentError
|
55
|
+
include Exception
|
56
|
+
|
57
|
+
def initialize(message = nil)
|
58
|
+
@message = message
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_s
|
62
|
+
str = 'An invalid argument was specified.'
|
63
|
+
if @message
|
64
|
+
str << " #{@message}"
|
65
|
+
end
|
66
|
+
str
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
###
|
71
|
+
#
|
72
|
+
# This exception is raised when an argument that was supplied to a method
|
73
|
+
# could not be parsed correctly.
|
74
|
+
#
|
75
|
+
###
|
76
|
+
class ArgumentParseError < ::ArgumentError
|
77
|
+
include Exception
|
78
|
+
|
79
|
+
def to_s
|
80
|
+
"The argument could not be parsed correctly."
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
###
|
85
|
+
#
|
86
|
+
# This exception is raised when an argument is ambiguous.
|
87
|
+
#
|
88
|
+
###
|
89
|
+
class AmbiguousArgumentError < ::RuntimeError
|
90
|
+
include Exception
|
91
|
+
|
92
|
+
def initialize(name = nil)
|
93
|
+
@name = name
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_s
|
97
|
+
"The name #{@name} is ambiguous."
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
###
|
102
|
+
#
|
103
|
+
# This error is thrown when a stream is detected as being closed.
|
104
|
+
#
|
105
|
+
###
|
106
|
+
class StreamClosedError < ::IOError
|
107
|
+
include Exception
|
108
|
+
|
109
|
+
def initialize(stream)
|
110
|
+
@stream = stream
|
111
|
+
end
|
112
|
+
|
113
|
+
def stream
|
114
|
+
@stream
|
115
|
+
end
|
116
|
+
|
117
|
+
def to_s
|
118
|
+
"Stream #{@stream} is closed."
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
##
|
123
|
+
#
|
124
|
+
# Socket exceptions
|
125
|
+
#
|
126
|
+
##
|
127
|
+
|
128
|
+
###
|
129
|
+
#
|
130
|
+
# This exception is raised when a general socket error occurs.
|
131
|
+
#
|
132
|
+
###
|
133
|
+
module SocketError
|
134
|
+
include Exception
|
135
|
+
|
136
|
+
def to_s
|
137
|
+
"A socket error occurred."
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
###
|
142
|
+
#
|
143
|
+
# This exception is raised when there is some kind of error related to
|
144
|
+
# communication with a host.
|
145
|
+
#
|
146
|
+
###
|
147
|
+
module HostCommunicationError
|
148
|
+
def initialize(addr = nil, port = nil)
|
149
|
+
self.host = addr
|
150
|
+
self.port = port
|
151
|
+
end
|
152
|
+
|
153
|
+
#
|
154
|
+
# This method returns a printable address and optional port associated
|
155
|
+
# with the host that triggered the exception.
|
156
|
+
#
|
157
|
+
def addr_to_s
|
158
|
+
if host and port
|
159
|
+
"(#{host}:#{port})"
|
160
|
+
elsif host
|
161
|
+
"(#{host})"
|
162
|
+
else
|
163
|
+
""
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
attr_accessor :host, :port
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
###
|
172
|
+
#
|
173
|
+
# This is a generic exception for errors that cause a connection to fail.
|
174
|
+
#
|
175
|
+
###
|
176
|
+
class ConnectionError < ::IOError
|
177
|
+
include SocketError
|
178
|
+
include HostCommunicationError
|
179
|
+
end
|
180
|
+
|
181
|
+
###
|
182
|
+
#
|
183
|
+
# This exception is raised when a connection attempt fails because the remote
|
184
|
+
# side refused the connection.
|
185
|
+
#
|
186
|
+
###
|
187
|
+
class ConnectionRefused < ConnectionError
|
188
|
+
def to_s
|
189
|
+
"The connection was refused by the remote host #{addr_to_s}."
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
###
|
194
|
+
#
|
195
|
+
# This exception is raised when a connection attempt fails because the remote
|
196
|
+
# side is unreachable.
|
197
|
+
#
|
198
|
+
###
|
199
|
+
class HostUnreachable < ConnectionError
|
200
|
+
def to_s
|
201
|
+
"The host #{addr_to_s} was unreachable."
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
###
|
206
|
+
#
|
207
|
+
# This exception is raised when a connection attempt times out.
|
208
|
+
#
|
209
|
+
###
|
210
|
+
class ConnectionTimeout < ConnectionError
|
211
|
+
def to_s
|
212
|
+
"The connection timed out #{addr_to_s}."
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
###
|
217
|
+
#
|
218
|
+
# This connection error is raised when an attempt is made to connect
|
219
|
+
# to a broadcast or network address.
|
220
|
+
#
|
221
|
+
###
|
222
|
+
class InvalidDestination < ConnectionError
|
223
|
+
include SocketError
|
224
|
+
include HostCommunicationError
|
225
|
+
|
226
|
+
def to_s
|
227
|
+
"The destination is invalid: #{addr_to_s}."
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
###
|
232
|
+
#
|
233
|
+
# This exception is raised when an attempt to use an address or port that is
|
234
|
+
# already in use or onot available occurs. such as binding to a host on a
|
235
|
+
# given port that is already in use, or when a bind address is specified that
|
236
|
+
# is not available to the host.
|
237
|
+
#
|
238
|
+
###
|
239
|
+
class BindFailed < ::ArgumentError
|
240
|
+
include SocketError
|
241
|
+
include HostCommunicationError
|
242
|
+
|
243
|
+
def to_s
|
244
|
+
"The address is already in use or unavailable: #{addr_to_s}."
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
##
|
249
|
+
#
|
250
|
+
# This exception is listed for backwards compatibility. We had been
|
251
|
+
# using AddressInUse as the exception for both bind errors and connection
|
252
|
+
# errors triggered by connection attempts to broadcast and network addresses.
|
253
|
+
# The two classes above have split this into their respective sources, but
|
254
|
+
# callers may still expect the old behavior.
|
255
|
+
#
|
256
|
+
##
|
257
|
+
class AddressInUse < ConnectionError
|
258
|
+
include SocketError
|
259
|
+
include HostCommunicationError
|
260
|
+
|
261
|
+
def to_s
|
262
|
+
"The address is already in use or unavailable: #{addr_to_s}."
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
|
267
|
+
###
|
268
|
+
#
|
269
|
+
# This exception is raised when an unsupported internet protocol is specified.
|
270
|
+
#
|
271
|
+
###
|
272
|
+
class UnsupportedProtocol < ::ArgumentError
|
273
|
+
include SocketError
|
274
|
+
|
275
|
+
def initialize(proto = nil)
|
276
|
+
self.proto = proto
|
277
|
+
end
|
278
|
+
|
279
|
+
def to_s
|
280
|
+
"The protocol #{proto} is not supported."
|
281
|
+
end
|
282
|
+
|
283
|
+
attr_accessor :proto
|
284
|
+
end
|
285
|
+
|
286
|
+
|
287
|
+
###
|
288
|
+
#
|
289
|
+
# This exception is raised when a proxy fails to pass a connection
|
290
|
+
#
|
291
|
+
###
|
292
|
+
class ConnectionProxyError < ConnectionError
|
293
|
+
def initialize(host,port,ptype,reason)
|
294
|
+
super(host,port)
|
295
|
+
self.ptype = ptype
|
296
|
+
self.reason = reason
|
297
|
+
end
|
298
|
+
|
299
|
+
def to_s
|
300
|
+
self.ptype + ": " + self.reason
|
301
|
+
end
|
302
|
+
|
303
|
+
attr_accessor :ptype, :reason
|
304
|
+
end
|
305
|
+
|
306
|
+
end
|
307
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
|
3
|
+
require 'rex/io/socket_abstraction'
|
4
|
+
|
5
|
+
module Rex
|
6
|
+
module IO
|
7
|
+
|
8
|
+
###
|
9
|
+
#
|
10
|
+
# This class provides an abstraction to a datagram based
|
11
|
+
# connection through the use of a datagram socketpair.
|
12
|
+
#
|
13
|
+
###
|
14
|
+
module DatagramAbstraction
|
15
|
+
include Rex::IO::SocketAbstraction
|
16
|
+
|
17
|
+
#
|
18
|
+
# Creates a streaming socket pair
|
19
|
+
#
|
20
|
+
def initialize_abstraction
|
21
|
+
self.lsock, self.rsock = Rex::Socket.udp_socket_pair
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end; end
|
@@ -0,0 +1,369 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
#
|
3
|
+
# This class implements a ring buffer with "cursors" in the form of sequence numbers.
|
4
|
+
# To use this class, pass in a file descriptor and a ring size, the class will read
|
5
|
+
# data from the file descriptor and store it in the ring. If the ring becomes full,
|
6
|
+
# the oldest item will be overwritten. To emulate a stream interface, call read_data
|
7
|
+
# to grab the last sequence number and any buffered data, call read_data again,
|
8
|
+
# passing in the sequence number and all data newer than that sequence will be
|
9
|
+
# returned, along with a new sequence to read from.
|
10
|
+
#
|
11
|
+
|
12
|
+
require 'rex/socket'
|
13
|
+
|
14
|
+
module Rex
|
15
|
+
module IO
|
16
|
+
|
17
|
+
class RingBuffer
|
18
|
+
|
19
|
+
attr_accessor :queue # The data queue, essentially an array of two-element arrays, containing a sequence and data buffer
|
20
|
+
attr_accessor :seq # The next available sequence number
|
21
|
+
attr_accessor :fd # The associated socket or IO object for this ring buffer
|
22
|
+
attr_accessor :size # The number of available slots in the queue
|
23
|
+
attr_accessor :mutex # The mutex locking access to the queue
|
24
|
+
attr_accessor :beg # The index of the earliest data fragment in the ring
|
25
|
+
attr_accessor :cur # The sequence number of the earliest data fragment in the ring
|
26
|
+
attr_accessor :monitor # The thread handle of the built-in monitor when used
|
27
|
+
attr_accessor :monitor_thread_error # :nodoc: #
|
28
|
+
|
29
|
+
#
|
30
|
+
# Create a new ring buffer
|
31
|
+
#
|
32
|
+
def initialize(socket, opts={})
|
33
|
+
self.size = opts[:size] || (1024 * 4)
|
34
|
+
self.fd = socket
|
35
|
+
self.seq = 0
|
36
|
+
self.beg = 0
|
37
|
+
self.cur = 0
|
38
|
+
self.queue = Array.new( self.size )
|
39
|
+
self.mutex = Mutex.new
|
40
|
+
end
|
41
|
+
|
42
|
+
def inspect
|
43
|
+
"#<Rex::IO::RingBuffer @size=#{size} @fd=#{fd} @seq=#{seq} @beg=#{beg} @cur=#{cur}>"
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Start the built-in monitor, not called when used in a larger framework
|
48
|
+
#
|
49
|
+
def start_monitor
|
50
|
+
self.monitor = monitor_thread if not self.monitor
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# Stop the built-in monitor
|
55
|
+
#
|
56
|
+
def stop_monitor
|
57
|
+
self.monitor.kill if self.monitor
|
58
|
+
self.monitor = nil
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# The built-in monitor thread (normally unused with Metasploit)
|
63
|
+
#
|
64
|
+
def monitor_thread
|
65
|
+
Thread.new do
|
66
|
+
begin
|
67
|
+
while self.fd
|
68
|
+
buff = self.fd.get_once(-1, 1.0)
|
69
|
+
next if not buff
|
70
|
+
store_data(buff)
|
71
|
+
end
|
72
|
+
rescue ::Exception => e
|
73
|
+
self.monitor_thread_error = e
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# Push data back into the associated stream socket. Logging must occur
|
80
|
+
# elsewhere, this function is simply a passthrough.
|
81
|
+
#
|
82
|
+
def put(data, opts={})
|
83
|
+
self.fd.put(data, opts={})
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
# The clear_data method wipes the ring buffer
|
88
|
+
#
|
89
|
+
def clear_data
|
90
|
+
self.mutex.synchronize do
|
91
|
+
self.seq = 0
|
92
|
+
self.beg = 0
|
93
|
+
self.cur = 0
|
94
|
+
self.queue = Array.new( self.size )
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
#
|
99
|
+
# The store_data method is used to insert data into the ring buffer.
|
100
|
+
#
|
101
|
+
def store_data(data)
|
102
|
+
self.mutex.synchronize do
|
103
|
+
# self.cur points to the array index of queue containing the last item
|
104
|
+
# adding data will result in cur + 1 being used to store said data
|
105
|
+
# if cur is larger than size - 1, it will wrap back around. If cur
|
106
|
+
# is *smaller* beg, beg is increemnted to cur + 1 (and wrapped if
|
107
|
+
# necessary
|
108
|
+
|
109
|
+
loc = 0
|
110
|
+
if self.seq > 0
|
111
|
+
loc = ( self.cur + 1 ) % self.size
|
112
|
+
|
113
|
+
if loc <= self.beg
|
114
|
+
self.beg = (self.beg + 1) % self.size
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
self.queue[loc] = [self.seq += 1, data]
|
119
|
+
self.cur = loc
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
#
|
124
|
+
# The read_data method returns a two element array with the new reader cursor (a sequence number)
|
125
|
+
# and the returned data buffer (if any). A result of nil/nil indicates that no data is available
|
126
|
+
#
|
127
|
+
def read_data(ptr=nil)
|
128
|
+
self.mutex.synchronize do
|
129
|
+
|
130
|
+
# Verify that there is data in the queue
|
131
|
+
return [nil,nil] if not self.queue[self.beg]
|
132
|
+
|
133
|
+
# Configure the beginning read pointer (sequence number, not index)
|
134
|
+
ptr ||= self.queue[self.beg][0]
|
135
|
+
return [nil,nil] if not ptr
|
136
|
+
|
137
|
+
# If the pointer is below our baseline, we lost some data, so jump forward
|
138
|
+
if ptr < self.queue[self.beg][0]
|
139
|
+
ptr = self.queue[self.beg][0]
|
140
|
+
end
|
141
|
+
|
142
|
+
# Calculate how many blocks exist between the current sequence number
|
143
|
+
# and the requested pointer, this becomes the number of blocks we will
|
144
|
+
# need to read to satisfy the result. Due to the mutex block, we do
|
145
|
+
# not need to scan to find the sequence of the starting block or
|
146
|
+
# check the sequence of the ending block.
|
147
|
+
dis = self.seq - ptr
|
148
|
+
|
149
|
+
# If the requested sequnce number is less than our base pointer, it means
|
150
|
+
# that no new data is available and we should return empty.
|
151
|
+
return [nil,nil] if dis < 0
|
152
|
+
|
153
|
+
# Calculate the beginning block index and number of blocks to read
|
154
|
+
off = ptr - self.queue[self.beg][0]
|
155
|
+
set = (self.beg + off) % self.size
|
156
|
+
|
157
|
+
|
158
|
+
# Build the buffer by reading forward by the number of blocks needed
|
159
|
+
# and return the last read sequence number, plus one, as the new read
|
160
|
+
# pointer.
|
161
|
+
buff = ""
|
162
|
+
cnt = 0
|
163
|
+
lst = ptr
|
164
|
+
ptr.upto(self.seq) do |i|
|
165
|
+
block = self.queue[ (set + cnt) % self.size ]
|
166
|
+
lst,data = block[0],block[1]
|
167
|
+
buff += data
|
168
|
+
cnt += 1
|
169
|
+
end
|
170
|
+
|
171
|
+
return [lst + 1, buff]
|
172
|
+
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
#
|
177
|
+
# The base_sequence method returns the earliest sequence number in the queue. This is zero until
|
178
|
+
# all slots are filled and the ring rotates.
|
179
|
+
#
|
180
|
+
def base_sequence
|
181
|
+
self.mutex.synchronize do
|
182
|
+
return 0 if not self.queue[self.beg]
|
183
|
+
return self.queue[self.beg][0]
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
#
|
188
|
+
# The last_sequence method returns the "next" sequence number where new data will be
|
189
|
+
# available.
|
190
|
+
#
|
191
|
+
def last_sequence
|
192
|
+
self.seq
|
193
|
+
end
|
194
|
+
|
195
|
+
#
|
196
|
+
# The create_steam method assigns a IO::Socket compatible object to the ringer buffer
|
197
|
+
#
|
198
|
+
def create_stream
|
199
|
+
Stream.new(self)
|
200
|
+
end
|
201
|
+
|
202
|
+
#
|
203
|
+
# The select method returns when there is a chance of new data
|
204
|
+
# XXX: This is mostly useless and requires a rewrite to use a
|
205
|
+
# real select or notify mechanism
|
206
|
+
#
|
207
|
+
def select
|
208
|
+
::IO.select([ self.fd ], nil, [ self.fd ], 0.10)
|
209
|
+
end
|
210
|
+
|
211
|
+
#
|
212
|
+
# The wait method blocks until new data is available
|
213
|
+
#
|
214
|
+
def wait(seq)
|
215
|
+
nseq = nil
|
216
|
+
while not nseq
|
217
|
+
nseq,data = read_data(seq)
|
218
|
+
select
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
#
|
223
|
+
# The wait_for method blocks until new data is available or the timeout is reached
|
224
|
+
#
|
225
|
+
def wait_for(seq,timeout=1)
|
226
|
+
begin
|
227
|
+
::Timeout.timeout(timeout) do
|
228
|
+
wait(seq)
|
229
|
+
end
|
230
|
+
rescue ::Timeout::Error
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
#
|
235
|
+
# This class provides a backwards compatible "stream" socket that uses
|
236
|
+
# the parents ring buffer.
|
237
|
+
#
|
238
|
+
class Stream
|
239
|
+
attr_accessor :ring
|
240
|
+
attr_accessor :seq
|
241
|
+
attr_accessor :buff
|
242
|
+
|
243
|
+
def initialize(ring)
|
244
|
+
self.ring = ring
|
245
|
+
self.seq = ring.base_sequence
|
246
|
+
self.buff = ''
|
247
|
+
end
|
248
|
+
|
249
|
+
def read(len=nil)
|
250
|
+
if len and self.buff.length >= len
|
251
|
+
data = self.buff.slice!(0,len)
|
252
|
+
return data
|
253
|
+
end
|
254
|
+
|
255
|
+
while true
|
256
|
+
lseq, data = self.ring.read_data( self.seq )
|
257
|
+
return if not lseq
|
258
|
+
|
259
|
+
self.seq = lseq
|
260
|
+
self.buff << data
|
261
|
+
if len
|
262
|
+
if self.buff.length >= len
|
263
|
+
return self.buff.slice!(0,len)
|
264
|
+
else
|
265
|
+
IO.select(nil, nil, nil, 0.25)
|
266
|
+
next
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
data = self.buff
|
271
|
+
self.buff = ''
|
272
|
+
|
273
|
+
return data
|
274
|
+
|
275
|
+
# Not reached
|
276
|
+
break
|
277
|
+
end
|
278
|
+
|
279
|
+
end
|
280
|
+
|
281
|
+
def write(data)
|
282
|
+
self.ring.write(data)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
end
|
287
|
+
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
=begin
|
292
|
+
|
293
|
+
server = Rex::Socket.create_tcp_server('LocalPort' => 0)
|
294
|
+
lport = server.getsockname[2]
|
295
|
+
client = Rex::Socket.create_tcp('PeerHost' => '127.0.0.1', 'PeerPort' => lport)
|
296
|
+
conn = server.accept
|
297
|
+
|
298
|
+
r = Rex::IO::RingBuffer.new(conn, {:size => 1024*1024})
|
299
|
+
client.put("1")
|
300
|
+
client.put("2")
|
301
|
+
client.put("3")
|
302
|
+
|
303
|
+
s,d = r.read_data
|
304
|
+
|
305
|
+
client.put("4")
|
306
|
+
client.put("5")
|
307
|
+
client.put("6")
|
308
|
+
s,d = r.read_data(s)
|
309
|
+
|
310
|
+
client.put("7")
|
311
|
+
client.put("8")
|
312
|
+
client.put("9")
|
313
|
+
s,d = r.read_data(s)
|
314
|
+
|
315
|
+
client.put("0")
|
316
|
+
s,d = r.read_data(s)
|
317
|
+
|
318
|
+
test_counter = 11
|
319
|
+
1.upto(100) do
|
320
|
+
client.put( "X" )
|
321
|
+
test_counter += 1
|
322
|
+
end
|
323
|
+
|
324
|
+
sleep(1)
|
325
|
+
|
326
|
+
s,d = r.read_data
|
327
|
+
p s
|
328
|
+
p d
|
329
|
+
|
330
|
+
fdata = ''
|
331
|
+
File.open("/bin/ls", "rb") do |fd|
|
332
|
+
fdata = fd.read(fd.stat.size)
|
333
|
+
fdata = fdata * 10
|
334
|
+
client.put(fdata)
|
335
|
+
end
|
336
|
+
|
337
|
+
sleep(1)
|
338
|
+
|
339
|
+
s,vdata = r.read_data(s)
|
340
|
+
|
341
|
+
if vdata != fdata
|
342
|
+
puts "DATA FAILED"
|
343
|
+
else
|
344
|
+
puts "DATA VERIFIED"
|
345
|
+
end
|
346
|
+
|
347
|
+
r.clear_data
|
348
|
+
|
349
|
+
a = r.create_stream
|
350
|
+
b = r.create_stream
|
351
|
+
|
352
|
+
client.put("ABC123")
|
353
|
+
sleep(1)
|
354
|
+
|
355
|
+
p a.read
|
356
|
+
p b.read
|
357
|
+
|
358
|
+
client.put("$$$$$$")
|
359
|
+
sleep(1)
|
360
|
+
|
361
|
+
p a.read
|
362
|
+
p b.read
|
363
|
+
|
364
|
+
c = r.create_stream
|
365
|
+
p c.read
|
366
|
+
|
367
|
+
=end
|
368
|
+
|
369
|
+
|