Class: Lumberjack::Parser
- Inherits:
-
Object
- Object
- Lumberjack::Parser
- Defined in:
- lib/lumberjack/server.rb
Overview
class Server
Constant Summary collapse
- FRAME_WINDOW =
def need
"W".ord
- FRAME_DATA =
"D".ord
- FRAME_COMPRESSED =
"C".ord
Instance Method Summary collapse
-
#compressed_lead(&block) ⇒ Object
def data_field_value.
- #compressed_payload(&block) ⇒ Object
- #data_field_key(&block) ⇒ Object
- #data_field_key_len(&block) ⇒ Object
- #data_field_value(&block) ⇒ Object
- #data_field_value_len(&block) ⇒ Object
-
#data_lead(&block) ⇒ Object
def window_size.
-
#feed(data, &block) ⇒ String?
Feed data to this parser.
-
#get(length = nil) ⇒ Object
Get ‘length’ string from the buffer.
-
#have?(length) ⇒ Boolean
Do we have at least ‘length’ bytes in the buffer?.
- #header(&block) ⇒ Object
-
#initialize ⇒ Parser
constructor
A new instance of Parser.
-
#need(length) ⇒ Object
Set the minimum number of bytes we need in the buffer for the next read.
-
#transition(state, next_length) ⇒ Object
def initialize.
- #window_size {|:window_size, @window_size| ... } ⇒ Object
Constructor Details
#initialize ⇒ Parser
Returns a new instance of Parser.
66 67 68 69 70 71 |
# File 'lib/lumberjack/server.rb', line 66 def initialize @buffer_offset = 0 @buffer = "" @buffer.force_encoding("BINARY") transition(:header, 2) end |
Instance Method Details
#compressed_lead(&block) ⇒ Object
def data_field_value
188 189 190 191 |
# File 'lib/lumberjack/server.rb', line 188 def compressed_lead(&block) length = get.unpack("N").first transition(:compressed_payload, length) end |
#compressed_payload(&block) ⇒ Object
193 194 195 196 197 198 199 |
# File 'lib/lumberjack/server.rb', line 193 def compressed_payload(&block) original = Zlib::Inflate.inflate(get) transition(:header, 2) # Parse the uncompressed payload. feed(original, &block) end |
#data_field_key(&block) ⇒ Object
163 164 165 166 |
# File 'lib/lumberjack/server.rb', line 163 def data_field_key(&block) @key = get transition(:data_field_value_len, 4) end |
#data_field_key_len(&block) ⇒ Object
158 159 160 161 |
# File 'lib/lumberjack/server.rb', line 158 def data_field_key_len(&block) key_len = get.unpack("N").first transition(:data_field_key, key_len) end |
#data_field_value(&block) ⇒ Object
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/lumberjack/server.rb', line 172 def data_field_value(&block) @value = get @data_count -= 1 @data[@key] = @value if @data_count > 0 transition(:data_field_key_len, 4) else # emit the whole map now that we found the end of the data fields list. yield :data, @sequence, @data transition(:header, 2) end end |
#data_field_value_len(&block) ⇒ Object
168 169 170 |
# File 'lib/lumberjack/server.rb', line 168 def data_field_value_len(&block) transition(:data_field_value, get.unpack("N").first) end |
#data_lead(&block) ⇒ Object
def window_size
152 153 154 155 156 |
# File 'lib/lumberjack/server.rb', line 152 def data_lead(&block) @sequence, @data_count = get.unpack("NN") @data = {} transition(:data_field_key_len, 4) end |
#feed(data, &block) ⇒ String?
Feed data to this parser.
Currently, it will return the raw payload of websocket messages. Otherwise, it returns nil if no complete message has yet been consumed.
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/lumberjack/server.rb', line 89 def feed(data, &block) @buffer << data #p :need => @need while have?(@need) send(@state, &block) #case @state #when :header; header(&block) #when :window_size; window_size(&block) #when :data_lead; data_lead(&block) #when :data_field_key_len; data_field_key_len(&block) #when :data_field_key; data_field_key(&block) #when :data_field_value_len; data_field_value_len(&block) #when :data_field_value; data_field_value(&block) #when :data_field_value; data_field_value(&block) #when :compressed_lead; compressed_lead(&block) #when :compressed_payload; compressed_payload(&block) #end # case @state end return nil end |
#get(length = nil) ⇒ Object
Get ‘length’ string from the buffer.
116 117 118 119 120 121 122 123 124 125 |
# File 'lib/lumberjack/server.rb', line 116 def get(length=nil) length = @need if length.nil? data = @buffer[@buffer_offset ... @buffer_offset + length] @buffer_offset += length if @buffer_offset > 16384 @buffer = @buffer[@buffer_offset .. -1] @buffer_offset = 0 end return data end |
#have?(length) ⇒ Boolean
Do we have at least ‘length’ bytes in the buffer?
111 112 113 |
# File 'lib/lumberjack/server.rb', line 111 def have?(length) return length <= (@buffer.size - @buffer_offset) end |
#header(&block) ⇒ Object
135 136 137 138 139 140 141 142 143 144 |
# File 'lib/lumberjack/server.rb', line 135 def header(&block) version, frame_type = get.bytes.to_a[0..1] case frame_type when FRAME_WINDOW; transition(:window_size, 4) when FRAME_DATA; transition(:data_lead, 8) when FRAME_COMPRESSED; transition(:compressed_lead, 4) else; raise "Unknown frame type: #{frame_type}" end end |
#need(length) ⇒ Object
Set the minimum number of bytes we need in the buffer for the next read.
128 129 130 |
# File 'lib/lumberjack/server.rb', line 128 def need(length) @need = length end |
#transition(state, next_length) ⇒ Object
def initialize
73 74 75 76 77 78 79 80 |
# File 'lib/lumberjack/server.rb', line 73 def transition(state, next_length) @state = state #puts :transition => state # TODO(sissel): Assert this self.respond_to?(state) # TODO(sissel): Assert state is in STATES # TODO(sissel): Assert next_length is a number need(next_length) end |
#window_size {|:window_size, @window_size| ... } ⇒ Object
146 147 148 149 150 |
# File 'lib/lumberjack/server.rb', line 146 def window_size(&block) @window_size = get.unpack("N").first transition(:header, 2) yield :window_size, @window_size end |