2005-07-24 20:53:54 +00:00
|
|
|
require 'rex/thread_safe'
|
|
|
|
|
2005-05-31 12:56:36 +00:00
|
|
|
module Rex
|
|
|
|
module IO
|
|
|
|
|
|
|
|
###
|
|
|
|
#
|
|
|
|
# Stream
|
|
|
|
# ------
|
|
|
|
#
|
|
|
|
# This mixin is an abstract representation of a streaming connection.
|
|
|
|
#
|
|
|
|
###
|
|
|
|
module Stream
|
|
|
|
|
|
|
|
##
|
|
|
|
#
|
|
|
|
# Abstract methods
|
|
|
|
#
|
|
|
|
##
|
|
|
|
|
|
|
|
#
|
|
|
|
# Set the stream to blocking or non-blocking
|
|
|
|
#
|
|
|
|
def blocking=(tf)
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Check to see if the stream is blocking or non-blocking
|
|
|
|
#
|
|
|
|
def blocking
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Writes data to the stream.
|
|
|
|
#
|
|
|
|
def write(buf, opts = {})
|
2005-07-19 04:21:15 +00:00
|
|
|
fd.syswrite(buf)
|
2005-05-31 12:56:36 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Reads data from the stream.
|
|
|
|
#
|
|
|
|
def read(length = nil, opts = {})
|
2005-07-19 04:21:15 +00:00
|
|
|
length = 16384 unless length
|
|
|
|
|
|
|
|
fd.sysread(length)
|
2005-05-31 12:56:36 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Shuts down the stream for reading, writing, or both.
|
|
|
|
#
|
|
|
|
def shutdown(how = SW_BOTH)
|
2005-07-19 04:21:15 +00:00
|
|
|
fd.shutdown(how)
|
2005-05-31 12:56:36 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Closes the stream and allows for resource cleanup
|
|
|
|
#
|
|
|
|
def close
|
2005-07-19 04:21:15 +00:00
|
|
|
fd.close
|
2005-05-31 12:56:36 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
2005-06-03 07:13:15 +00:00
|
|
|
# Polls the stream to see if there is any read data available. Returns
|
|
|
|
# true if data is available for reading, otherwise false is returned.
|
2005-05-31 12:56:36 +00:00
|
|
|
#
|
2005-06-03 07:13:15 +00:00
|
|
|
def has_read_data?(timeout = nil)
|
2005-07-19 04:21:15 +00:00
|
|
|
Rex::ThreadSafe.select([ fd ], nil, nil, timeout)
|
2005-06-02 07:52:17 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Returns the file descriptor that can be polled via select, if any.
|
|
|
|
#
|
|
|
|
def poll_fd
|
2005-07-16 07:32:11 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Wrapper for poll_fd
|
|
|
|
#
|
|
|
|
def fd
|
|
|
|
poll_fd
|
2005-05-31 12:56:36 +00:00
|
|
|
end
|
|
|
|
|
2005-07-16 08:12:58 +00:00
|
|
|
#
|
|
|
|
# Returns peer information, such as host and port.
|
|
|
|
#
|
|
|
|
def peerinfo
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Returns local information, such as host and port.
|
|
|
|
#
|
|
|
|
def localinfo
|
|
|
|
end
|
|
|
|
|
2005-05-31 12:56:36 +00:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Common methods
|
|
|
|
#
|
|
|
|
##
|
|
|
|
|
|
|
|
#
|
|
|
|
# Writes data to the stream
|
|
|
|
#
|
|
|
|
def <<(buf)
|
2005-06-03 22:56:36 +00:00
|
|
|
return write(buf.to_s)
|
2005-05-31 12:56:36 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Writes to the stream, optionally timing out after a period of time
|
|
|
|
#
|
|
|
|
def timed_write(buf, wait = def_write_timeout, opts = {})
|
|
|
|
if (wait and wait > 0)
|
|
|
|
timeout(wait) {
|
|
|
|
return write(buf, opts)
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return write(buf, opts)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Reads from the stream, optionally timing out after a period of time
|
|
|
|
#
|
|
|
|
def timed_read(length = nil, wait = def_read_timeout, opts = {})
|
|
|
|
if (wait and wait > 0)
|
|
|
|
timeout(wait) {
|
|
|
|
return read(length, opts)
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return read(length, opts)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Write the full contents of the supplied buffer
|
|
|
|
#
|
|
|
|
def put(buf, opts = {})
|
|
|
|
send_buf = buf.dup()
|
|
|
|
send_len = send_buf.length
|
|
|
|
wait = opts['Timeout'] || 0
|
|
|
|
|
|
|
|
# Keep writing until our send length drops to zero
|
|
|
|
while (send_len > 0)
|
|
|
|
curr_len = timed_write(send_buf, wait, opts)
|
|
|
|
send_len -= curr_len
|
|
|
|
send_buf.slice!(0, curr_len)
|
|
|
|
end
|
|
|
|
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Read as much data as possible from the pipe
|
|
|
|
#
|
2005-06-04 07:51:59 +00:00
|
|
|
def get(timeout = nil, ltimeout = def_read_loop_timeout, opts = {})
|
2005-06-03 22:56:36 +00:00
|
|
|
# For those people who are used to being able to use a negative timeout!
|
2005-06-04 06:19:42 +00:00
|
|
|
if (timeout and timeout.to_i < 0)
|
2005-06-03 22:56:36 +00:00
|
|
|
timeout = nil
|
|
|
|
end
|
|
|
|
|
2005-05-31 12:56:36 +00:00
|
|
|
# No data in the first place? bust.
|
2005-07-16 07:32:11 +00:00
|
|
|
if (has_read_data?(timeout) == false)
|
2005-05-31 12:56:36 +00:00
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
|
|
|
buf = ""
|
|
|
|
lps = 0
|
2005-07-24 20:53:54 +00:00
|
|
|
eof = false
|
2005-05-31 12:56:36 +00:00
|
|
|
|
|
|
|
# Keep looping until there is no more data to be gotten..
|
2005-07-16 07:32:11 +00:00
|
|
|
while (has_read_data?(ltimeout) == true)
|
2005-07-24 20:53:54 +00:00
|
|
|
# Catch EOF errors so that we can handle them properly.
|
|
|
|
begin
|
|
|
|
temp = read(def_block_size)
|
|
|
|
rescue EOFError
|
|
|
|
eof = true
|
|
|
|
end
|
|
|
|
|
2005-07-16 07:32:11 +00:00
|
|
|
# If we read zero bytes and we had data, then we've hit EOF
|
|
|
|
if (temp and temp.length == 0)
|
2005-07-24 20:53:54 +00:00
|
|
|
eof = true
|
|
|
|
end
|
|
|
|
|
|
|
|
# If we reached EOF and there are no bytes in the buffer we've been
|
|
|
|
# reading into, then throw an EOF error.
|
|
|
|
if (eof)
|
|
|
|
# If we've already read at least some data, then it's time to
|
|
|
|
# break out and let it be processed before throwing an EOFError.
|
|
|
|
if (buf.length > 0)
|
|
|
|
break
|
|
|
|
else
|
|
|
|
raise EOFError
|
|
|
|
end
|
2005-07-16 07:32:11 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
break if (temp == nil or temp.empty? == true)
|
2005-05-31 12:56:36 +00:00
|
|
|
|
|
|
|
buf += temp
|
|
|
|
lps += 1
|
|
|
|
|
|
|
|
break if (lps >= def_max_loops)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Return the entire buffer we read in
|
|
|
|
return buf
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
#
|
|
|
|
# Defaults
|
|
|
|
#
|
|
|
|
##
|
|
|
|
|
|
|
|
def def_write_timeout
|
|
|
|
return 10
|
|
|
|
end
|
|
|
|
|
|
|
|
def def_read_timeout
|
|
|
|
return 10
|
|
|
|
end
|
|
|
|
|
|
|
|
def def_read_loop_timeout
|
|
|
|
return 0.5
|
|
|
|
end
|
|
|
|
|
|
|
|
def def_max_loops
|
|
|
|
return 1024
|
|
|
|
end
|
|
|
|
|
|
|
|
def def_block_size
|
|
|
|
return 16384
|
|
|
|
end
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end end
|