class UnixRack::Socket

Attributes

hdr_method[RW]
headers[RW]
sock[RW]

Public Class Methods

close(io) click to toggle source
# File lib/unixrack.rb, line 69
def self.close(io)
  io.close
end
new(sock) click to toggle source
# File lib/unixrack.rb, line 44
def initialize(sock)
  TCPSocket.do_not_reverse_lookup = true
  @sock = sock
  @buff = ""
end
read_sock_num_bytes(sock, num, log = lambda { |x| x }) click to toggle source
# File lib/unixrack.rb, line 73
def self.read_sock_num_bytes(sock, num, log = lambda { |x| x })
  retval = [false, '']
  buff = ""
  num_left = num
  while true
    begin
      #log("PRE Doing sysread")
      numr = num_left < 32768 ? num_left : 32768
      dat = sock.sysread(numr)
      #log("Doing sysread #{dat.inspect}")
      buff = buff + dat
      if buff.length == num
        retval = [true, buff]
        break
      else
        num_left = num_left - dat.length
      end
    rescue Errno::EINTR # Ruby threading can cause an alarm/timer interrupt on a syscall
      retry
    rescue EOFError
      retval = [false, "EOF", buff]
      break
    rescue Errno::ECONNRESET, Errno::EPIPE, Errno::EINVAL, Errno::EBADF
      retval = [false, "Exception occurred on socket read"]
      #log("Got an #{$!} from socket read")
      break
    end
  end
  retval
end
write_buff(io, buff) click to toggle source
# File lib/unixrack.rb, line 54
def self.write_buff(io, buff)
  nwritten = 0

  out_buff = buff

  # buff could be UTF-8
  while true
    nw = io.syswrite(out_buff)
    nwritten = nwritten + nw
    break if nw == out_buff.bytesize
    out_buff = out_buff.byteslice(nw..-1)
  end
  nwritten
end

Public Instance Methods

do_read() click to toggle source
# File lib/unixrack.rb, line 105
def do_read
  begin
    dat = @sock.sysread(16384)
  rescue Errno::EINTR # Ruby threading can cause an alarm/timer interrupt on a syscall
    retry
  rescue EOFError
    puts "#{$$}: Got an EOF from socket read"
    $stdout.flush
    return nil
  rescue Errno::ECONNRESET, Errno::EPIPE, Errno::EINVAL, Errno::EBADF
    puts "#{$$}: Got an #{$!} from socket read"
    $stdout.flush
    exit! 0
  end
  @buff = @buff + dat
  return @buff
end
peeraddr() click to toggle source
# File lib/unixrack.rb, line 50
def peeraddr
  @sock.peeraddr
end
read_content() click to toggle source
# File lib/unixrack.rb, line 123
def read_content
  cont_len = @headers['Content-Length'].to_i

  #if cont_len < (8 * 1024 * 1024)
  if cont_len < (1024 * 1024)
    # Small file, just use mem
    while true
      if @buff.length == cont_len
        f = StringIO.new(@buff)
        @buff = ""
        return f
      end
      return nil if not do_read
    end
  else
    # Large file, use disk
    f = nil
    tmpname = "./.__tmp__unixrack_upload__#{$$}.tmp"
    begin
      tmpfd = IO.sysopen(tmpname, File::RDWR | File::CREAT | File::EXCL, 0600)
      f = IO.new(tmpfd, "w+")
      File.unlink(tmpname)
    rescue
      p $!
      $stdout.flush
      return nil
    end

    # Write what we already have
    len = @buff.length
    if len > 0
      f.syswrite(@buff)
      @buff = ""
    end

    while true
      if len == cont_len
        f.rewind
        return f
      end

      return nil if not do_read

      len += @buff.length
      f.syswrite(@buff)
      @buff = ""
    end
  end
end
read_headers() click to toggle source
# File lib/unixrack.rb, line 173
def read_headers
  while true
    r = do_read
    break if @buff.index "\r\n\r\n"
    return false if r == nil
  end

  a, b = @buff.split("\r\n\r\n", 2)

  @buff = b
  @hdr_buff = a
  @hdr_lines = @hdr_buff.split("\r\n")

  @hdr_method_line = @hdr_lines[0]
  @hdr_method = @hdr_method_line.split(" ")

  @hdr_field_lines = @hdr_lines.slice(1..-1) # would prefer first, and rest
  headers = @hdr_field_lines.inject({}) { |h, line| k, v = line.split(": "); h[k] = v; h }
  @headers = canonicalize_headers(headers)
  true
end

Private Instance Methods

canonicalize_headers(headers) click to toggle source
# File lib/unixrack.rb, line 197
def canonicalize_headers(headers)
  headers.keys.each do |key|
    headers[key.split(/-/).map(&:capitalize).join('-')] = headers.delete(key)
  end
  headers
end