Class: LittleGhost::Providers::Bedrock::EventStreamDecoder

Inherits:
Object
  • Object
show all
Defined in:
lib/little_ghost/providers/bedrock/aws_protocol.rb

Overview

Incrementally decodes the AWS EventStream binary framing protocol.

Constant Summary collapse

DEFAULT_MAX_FRAME_BYTES =

:nodoc:

16 * 1024 * 1024
DEFAULT_MAX_HEADERS_BYTES =
128 * 1024

Instance Method Summary collapse

Constructor Details

#initialize(max_frame_bytes: DEFAULT_MAX_FRAME_BYTES, max_headers_bytes: DEFAULT_MAX_HEADERS_BYTES) ⇒ EventStreamDecoder

Returns a new instance of EventStreamDecoder.



64
65
66
67
68
# File 'lib/little_ghost/providers/bedrock/aws_protocol.rb', line 64

def initialize(max_frame_bytes: DEFAULT_MAX_FRAME_BYTES, max_headers_bytes: DEFAULT_MAX_HEADERS_BYTES)
  @buffer = String.new(encoding: Encoding::BINARY)
  @max_frame_bytes = Integer(max_frame_bytes)
  @max_headers_bytes = Integer(max_headers_bytes)
end

Instance Method Details

#<<(chunk) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/little_ghost/providers/bedrock/aws_protocol.rb', line 70

def <<(chunk)
  @buffer << chunk.b
  events = []
  loop do
    break if @buffer.bytesize < 12

    total_length, headers_length, prelude_crc = @buffer.unpack("NNN")
    raise ProtocolError, "AWS EventStream frame length is invalid" if total_length < 16 || headers_length > total_length - 16
    raise ProtocolError, "AWS EventStream frame exceeds the configured limit" if total_length > @max_frame_bytes
    raise ProtocolError, "AWS EventStream headers exceed the configured limit" if headers_length > @max_headers_bytes
    break if @buffer.bytesize < total_length

    frame = @buffer.slice!(0, total_length)
    raise ProtocolError, "AWS EventStream prelude checksum is invalid" unless Zlib.crc32(frame.byteslice(0, 8)) == prelude_crc
    expected_crc = frame.byteslice(total_length - 4, 4).unpack1("N")
    raise ProtocolError, "AWS EventStream message checksum is invalid" unless Zlib.crc32(frame.byteslice(0, total_length - 4)) == expected_crc

    headers = decode_headers(frame.byteslice(12, headers_length))
    payload = frame.byteslice(12 + headers_length, total_length - headers_length - 16)
    events << [headers, payload]
  end
  events
end

#finishObject

Raises:



94
95
96
# File 'lib/little_ghost/providers/bedrock/aws_protocol.rb', line 94

def finish
  raise ProtocolError, "AWS EventStream ended with an incomplete frame" unless @buffer.empty?
end