File: stomp_frame.rb

package info (click to toggle)
stompserver 0.9.9gem-5
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 424 kB
  • sloc: ruby: 2,765; sh: 162; makefile: 3
file content (96 lines) | stat: -rw-r--r-- 2,216 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

module StompServer
class StompFrame
  attr_accessor :command, :headers, :body
  def initialize(command=nil, headers=nil, body=nil)
    @command = command
    @headers = headers || {}
    @body = body || ''
  end
 
  def to_s
    result = @command + "\n"
    @headers['content-length'] = @body.size.to_s if @body.include?(0.chr)
    @headers.each_pair do |key, value|
      result << "#{key}:#{value}\n"
    end
    result << "\n"
    result << @body.to_s
    result << "\000\n"  
  end
  
  def dest
    #@dest || (@dest = @headers['destination'])
    @headers['destination']
  end
end


class StompFrameRecognizer
  attr_accessor :frames
  
  def initialize
    @buffer = ''
    @body_length = nil
    @frame = StompServer::StompFrame.new
    @frames = []
  end
  
  def parse_body(len)
    raise RuntimeError.new("Invalid stompframe (missing null term)") unless @buffer[len] == 0.chr
    @frame.body = @buffer[0...len]
    @buffer = @buffer[len+1..-1]
    @frames << @frame
    @frame = StompServer::StompFrame.new
  end
  
  def parse_binary_body
    if @buffer.length > @body_length
      parse_body(@body_length)
    end
  end
  
  def parse_text_body
    if pos = @buffer.index(0.chr)
      parse_body(pos)
    end
  end
  
  def parse_header
    if match = @buffer.match(/^\s*(\S+)$\r?\n((?:[ \t]*.*?[ \t]*:[ \t]*.*?[ \t]*$\r?\n)*)\r?\n/)
      @frame.command, headers = match.captures
      @buffer = match.post_match
      headers.split(/\n/).each do |data|
        if data =~ /^\s*(\S+)\s*:\s*(.*?)\s*$/
          @frame.headers[$1] = $2
        end
      end
      
      # body_length is nil, if there is no content-length, otherwise it is the length (as in integer)
      @body_length = @frame.headers['content-length'] && @frame.headers['content-length'].to_i
    end
  end
  
  def parse
    count = @frames.size
    
    parse_header unless @frame.command
    if @frame.command
      if @body_length
        parse_binary_body
      else
        parse_text_body
      end
    end
    
    # parse_XXX_body return the frame if they succeed and nil if they fail
    # the result will fall through
    parse if count != @frames.size
  end
  
  def<< (buf)
    @buffer << buf
    parse
  end    
end
end