Class/Module Index [+]

Quicksearch

Rex::IO::Stream

This mixin is an abstract representation of a streaming connection. Streams extend classes that must implement the following methods:

syswrite(buffer)
sysread(length)
shutdown(how)
close
peerinfo
localinfo

Public Instance Methods

<<(buf) click to toggle source

This method writes the supplied buffer to the stream by calling the write routine.

# File lib/rex/io/stream.rb, line 126
def <<(buf)
        return write(buf.to_s)
end
>>() click to toggle source

This method calls get_once() to read pending data from the socket

# File lib/rex/io/stream.rb, line 133
def >>
        get_once
end
def_block_size() click to toggle source

The default block size to read in chunks from the wire.

# File lib/rex/io/stream.rb, line 302
def def_block_size
        16384
end
def_max_loops() click to toggle source

The maximum number of read loops to perform before returning to the caller.

# File lib/rex/io/stream.rb, line 295
def def_max_loops
        1024
end
def_read_loop_timeout() click to toggle source

The default number of seconds to wait while in a read loop after read data has been found.

# File lib/rex/io/stream.rb, line 287
def def_read_loop_timeout
        0.1
end
def_read_timeout() click to toggle source

The default number of seconds to wait for a read operation to timeout.

# File lib/rex/io/stream.rb, line 279
def def_read_timeout
        10
end
def_write_timeout() click to toggle source

The default number of seconds to wait for a write operation to timeout.

# File lib/rex/io/stream.rb, line 272
def def_write_timeout
        10
end
fd() click to toggle source

This method returns the selectable file descriptor, or self by default.

# File lib/rex/io/stream.rb, line 112
def fd
        self
end
get(timeout = nil, ltimeout = def_read_loop_timeout, opts = {}) click to toggle source

This method reads as much data as it can from the wire given a maximum timeout.

# File lib/rex/io/stream.rb, line 210
def get(timeout = nil, ltimeout = def_read_loop_timeout, opts = {})
        # For those people who are used to being able to use a negative timeout!
        if (timeout and timeout.to_i < 0)
                timeout = nil
        end

        # No data in the first place? bust.
        if (has_read_data?(timeout) == false)
                return nil
        end

        buf = ""
        lps = 0
        eof = false

        # Keep looping until there is no more data to be gotten..
        while (has_read_data?(ltimeout) == true)
                # Catch EOF errors so that we can handle them properly.
                begin
                        temp = read(def_block_size)
                rescue EOFError
                        eof = true
                end

                # If we read zero bytes and we had data, then we've hit EOF
                if (temp and temp.length == 0)
                        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
                end

                break if (temp == nil or temp.empty? == true)

                buf += temp
                lps += 1

                break if (lps >= def_max_loops)
        end

        # Return the entire buffer we read in
        return buf
end
get_once(length = -1, timeout = def_read_timeout) click to toggle source

This method emulates the behavior of Pex::Socket::Recv in MSF2

# File lib/rex/io/stream.rb, line 194
def get_once(length = -1, timeout = def_read_timeout)

        if (has_read_data?(timeout) == false)
                return nil
        end

        bsize = (length == -1) ? def_block_size : length
        data  = read(bsize)
        raise EOFError if data.nil?
        data
end
has_read_data?(timeout = nil) click to toggle source

Polls the stream to see if there is any read data available. Returns true if data is available for reading, otherwise false is returned.

# File lib/rex/io/stream.rb, line 86
def has_read_data?(timeout = nil)

        # Allow a timeout of "0" that waits almost indefinitely for input, this
        # mimics the behavior of Rex::ThreadSafe.select() and fixes some corner
        # cases of unintentional no-wait timeouts.
        timeout = 3600 if (timeout and timeout == 0)

        begin
                if ((rv = ::IO.select([ fd ], nil, nil, timeout)) and
                    (rv[0]) and
                    (rv[0][0] == fd))
                        true
                else
                        false
                end
        rescue ::Errno::EBADF, ::Errno::ENOTSOCK
                raise ::EOFError
        rescue StreamClosedError, ::IOError, ::EOFError, ::Errno::EPIPE
                #  Return false if the socket is dead
                return false
        end
end
put(buf, opts = {}) click to toggle source

This method writes the full contents of the supplied buffer, optionally with a timeout.

# File lib/rex/io/stream.rb, line 169
def put(buf, opts = {})
        return 0 if (buf == nil or buf.length == 0)

        send_len = buf.length
        send_idx = 0
        wait     = opts['Timeout'] || 0

        # Keep writing until our send length drops to zero
        while (send_idx < send_len)
                curr_len  = timed_write(buf[send_idx, buf.length-send_idx], wait, opts)

                # If the write operation failed due to an IOError, then we fail.
                return buf.length - send_len if (curr_len == nil)

                send_len -= curr_len
                send_idx += curr_len
        end

        return buf.length - send_len
end
read(length = nil, opts = {}) click to toggle source

This method reads data of the supplied length from the stream.

# File lib/rex/io/stream.rb, line 68
def read(length = nil, opts = {})
        
        begin
                return fd.read_nonblock( length )                            
        rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
                # Sleep for a half a second, or until we can read again
                Rex::ThreadSafe.select( [ fd ], nil, nil, 0.5 )
                # Decrement the block size to handle full sendQs better
                retry
        rescue ::IOError, ::Errno::EPIPE
                return nil
        end
end
timed_read(length = nil, wait = def_read_timeout, opts = {}) click to toggle source

This method reads from the stream, optionally timing out after a period of time.

# File lib/rex/io/stream.rb, line 155
def timed_read(length = nil, wait = def_read_timeout, opts = {})
        if (wait and wait > 0)
                Timeout.timeout(wait) {
                        return read(length, opts)
                }
        else
                return read(length, opts)
        end
end
timed_write(buf, wait = def_write_timeout, opts = {}) click to toggle source

This method writes to the stream, optionally timing out after a period of time.

# File lib/rex/io/stream.rb, line 141
def timed_write(buf, wait = def_write_timeout, opts = {})
        if (wait and wait > 0)
                Timeout.timeout(wait) {
                        return write(buf, opts)
                }
        else
                return write(buf, opts)
        end
end
write(buf, opts = {}) click to toggle source

This method writes the supplied buffer to the stream. This method intelligent reduces the size of supplied buffers so that ruby doesn't get into a potential global thread blocking state when used on blocking sockets. That is, this method will send the supplied buffer in chunks of, at most, 32768 bytes.

# File lib/rex/io/stream.rb, line 34
def write(buf, opts = {})
        total_sent   = 0
        total_length = buf.length
        block_size   = 32768
        
        begin
                while( total_sent < total_length )
                        s = Rex::ThreadSafe.select( nil, [ fd ], nil, 0.2 )
                        if( s == nil || s[0] == nil )
                                next
                        end
                        data = buf[total_sent, block_size]
                        sent = fd.write_nonblock( data )
                        if sent > 0
                                total_sent += sent
                        end
                end
        rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
                # Sleep for a half a second, or until we can write again
                Rex::ThreadSafe.select( nil, [ fd ], nil, 0.5 )
                # Decrement the block size to handle full sendQs better
                block_size = 1024
                # Try to write the data again
                retry
        rescue ::IOError, ::Errno::EPIPE
                return nil
        end
        
        total_sent
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.