class PacketIO

The PacketIO class implements a mechanism to send and recv packets delimited by a length prefix which is assumed to be a 4 bytes integer in network byte order.

Public Class Methods

new(sock, bufsize=16380) click to toggle source

Creates a new PackIO object

sock

The socket which will be used

bufsize

The size of the buffer to use (default is 16K)

# File lib/network/packetio.rb, line 29
def initialize(sock, bufsize=16380)
  @sock = sock
  @bufsize = bufsize + 4 # round out with prefix bytes
  @inbuffer = ""
  @outbuffer = ""
  @packet_size = 0
  @prefix_found = false
end

Public Instance Methods

read() click to toggle source

read will receive a data from the socket.

return

The data read

IOError

A sockets error occurred.

EOFError

The connection has closed normally.

# File lib/network/packetio.rb, line 43
def read
  @inbuffer << @sock.recv(@bufsize)
  if !@prefix_found
    # start of packet
    if @inbuffer.size >= 4
      sizest = @inbuffer.slice!(0..3)
      @packet_size = sizest.unpack("N")[0]
      @prefix_found = true
      if @packet_size > @bufsize
        @inbuffer = ""
        @packet_size = 0
        @prefix_found = false
        log.warn "Discarding packet: Buffer size exceeded (PACKETSIZE=#{@packet_size} STRING='#{sizest}')"
        return nil
      end
    else
      return nil # not enough data yet
    end
  end

  if @prefix_found
    if @inbuffer.size >= @packet_size
      # We have it
      @prefix_found = false
      ps = @packet_size
      @packet_size = 0
      return @inbuffer.slice!(0...ps).chop  # chop off NUL
    else
      # Dont have it all yet.
      return nil
    end
  end
end
write(msg) click to toggle source

write will transmit a packet to the socket, we calculated the size here

msg

The message string to be sent.

return

false if more data to be written, true if all data written

IOError

A sockets error occurred.

EOFError

The connection has closed normally.

# File lib/network/packetio.rb, line 83
def write(msg)
  if !msg.nil? && !msg.empty?
    @outbuffer << [msg.length].pack("N") << msg
  end
  n = @sock.send(@outbuffer, 0)
  # save unsent data for next call
  @outbuffer.slice!(0...n)
  @outbuffer.size == 0
rescue Exception
  @outbuffer = ""  # Does it really matter?
  raise
end