class StompOut::Parser
Parser
for converting stream of data from connection into STOMP frames
Public Class Methods
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
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
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 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 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 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 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 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