Class: Gelfd2::ChunkedParser

Inherits:
Object
  • Object
show all
Defined in:
lib/gelfd2/chunked_parser.rb

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.chunksObject

Returns the value of attribute chunks.



5
6
7
# File 'lib/gelfd2/chunked_parser.rb', line 5

def chunks
  @chunks
end

.decoded_dataObject

Returns the value of attribute decoded_data.



5
6
7
# File 'lib/gelfd2/chunked_parser.rb', line 5

def decoded_data
  @decoded_data
end

.max_chunksObject

Returns the value of attribute max_chunks.



5
6
7
# File 'lib/gelfd2/chunked_parser.rb', line 5

def max_chunks
  @max_chunks
end

.message_idObject

Returns the value of attribute message_id.



5
6
7
# File 'lib/gelfd2/chunked_parser.rb', line 5

def message_id
  @message_id
end

.seenObject

Returns the value of attribute seen.



5
6
7
# File 'lib/gelfd2/chunked_parser.rb', line 5

def seen
  @seen
end

Class Method Details

.assemble_chunks(msg_id) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/gelfd2/chunked_parser.rb', line 17

def assemble_chunks(msg_id)
  buff = ''
  chunks = @chunk_map[msg_id][:chunks]
  chunks.keys.sort.each do |k|
    buff += chunks[k]
  end
  begin
    # TODO
    # This has a chance for an DoS
    # you can send a chunked message as a chunked message
    t = Parser.parse(buff.clone)
    @chunk_map.delete(msg_id)
    t
  rescue Exception => e
    "Exception: #{e.message}"
  end
end

.cleanup_chunksObject



50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/gelfd2/chunked_parser.rb', line 50

def cleanup_chunks
  # Run check every @msg_timeout seconds
  now = Time.now.to_i
  return unless now > @last_cleanup + @msg_timeout
  begin
    @last_cleanup = now
    @chunk_map.each do |msg_id, msg|
      next if msg[:ttl] > now
      @chunk_map.delete(msg_id)
    end
  end
end

.parse(data) ⇒ Object



7
8
9
10
11
12
13
14
15
# File 'lib/gelfd2/chunked_parser.rb', line 7

def parse(data)
  @chunk_map ||= Hash.new { |hash, key| hash[key] = { total_chunks: 0, msg_ttl: 0, chunks: {} } }
  @msg_timeout ||= 20
  @last_cleanup ||= 0
  msg_id = parse_chunk(data)
  return unless @chunk_map[msg_id][:chunks].size == @chunk_map[msg_id][:total_chunks]
  cleanup_chunks
  assemble_chunks(msg_id)
end

.parse_chunk(data) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/gelfd2/chunked_parser.rb', line 35

def parse_chunk(data)
  header = data[0..1]
  raise NotChunkedDataError, "This doesn't look like a Chunked GELF message!" if header != CHUNKED_MAGIC
  begin
    msg_id = data[2..9].unpack('C*').join
    seq_number, total_number = data[10].ord, data[11].ord
    zlib_chunk = data[12..-1]
    raise TooManyChunksError, "#{total_number} greater than #{MAX_CHUNKS}" if total_number > MAX_CHUNKS
    @chunk_map[msg_id][:total_chunks] = total_number.to_i
    @chunk_map[msg_id][:chunks][seq_number.to_i] = zlib_chunk
    @chunk_map[msg_id][:ttl] = Time.now.to_i + @msg_timeout
    msg_id
  end
end