class StompOut::Parser

Parser for converting stream of data from connection into STOMP frames

Public Class Methods

new() click to toggle source

Create frame parser

# File lib/stomp_out/parser.rb, line 31
def initialize
  @buffer = ""
  @body_length = nil
  @frame = Frame.new
  @frames = []
end

Public Instance Methods

<<(buf) click to toggle source

Add data received from connection to end of buffer

@return [TrueClass] always true

# File lib/stomp_out/parser.rb, line 41
def <<(buf)
  @buffer << buf
  parse
end
next() click to toggle source

Get next frame

@return [Frame, NilClass] frame or nil if none available

# File lib/stomp_out/parser.rb, line 49
def next
  @frames.shift
end

Protected Instance Methods

parse() click to toggle source

Parse the contents of the buffer

@return [TrueClass] always true

# File lib/stomp_out/parser.rb, line 58
def parse
  parse_command_and_headers if @frame.command.nil?
  success = if @frame.command
    if @body_length
      parse_binary_body
    else
      parse_text_body
    end
  elsif (match = @buffer.match(/\A\n|\A\r|\A\r\n/))
    # Ignore heartbeat
    @buffer = match.post_match
    true
  end

  # Keep parsing if making progress and there is more data
  parse if success && !@buffer.empty?
  true
end
parse_binary_body() click to toggle source

Parse binary body at beginning of buffer

@return [Frame, NilClass] frame created or nil if need more data

@raise [ProtocolError] missing frame null terminator

# File lib/stomp_out/parser.rb, line 101
def parse_binary_body
  if @buffer.size > @body_length
    # Also test for 0 here to be compatible with Ruby 1.8 string handling
    unless [NULL, 0].include?(@buffer[@body_length])
      raise ProtocolError, "Invalid frame (missing null terminator)"
    end
    parse_body(@body_length)
  end
end
parse_body(length) click to toggle source

Parse body at beginning of buffer to complete frame

@param [Integer] length of body

@return [Frame] new frame

# File lib/stomp_out/parser.rb, line 125
def parse_body(length)
  @frame.body = @buffer[0...length]
  @buffer = @buffer[length+1..-1]
  @frames << @frame
  @frame = Frame.new
end
parse_command_and_headers() click to toggle source

Parse next command and headers at beginning of buffer

@return [TrueClass] always true

# File lib/stomp_out/parser.rb, line 80
def parse_command_and_headers
  if (match = @buffer.match(/\A\s*(\S+)\r?\n((?:[ \t]*.*?[ \t]*:[ \t]*.*?[ \t]*$\r?\n)*)\r?\n/))
    @frame.command, headers = match.captures
    @buffer = match.post_match
    headers.split(/\r?\n/).each do |data|
      if data.match(/^\s*([^\s:]+)\s*:\s*(.*?\s*)$/)
        @frame.headers[$1] = $2 unless @frame.headers.has_key?($1)
      end
    end
    @body_length = (length = @frame.headers["content-length"]) && length.to_i
  elsif @buffer.rindex(NULL)
    raise ProtocolError, "Invalid frame (malformed headers)"
  end
  true
end
parse_text_body() click to toggle source

Parse text body at beginning of buffer

@return [Frame, NilClass] frame created or nil if need more data

# File lib/stomp_out/parser.rb, line 114
def parse_text_body
  if (length = @buffer.index(NULL))
    parse_body(length)
  end
end