Module: Biryani::Frame

Defined in:
lib/biryani/frame.rb,
lib/biryani/frame.rb,
lib/biryani/frame/data.rb,
lib/biryani/frame/ping.rb,
lib/biryani/frame/goaway.rb,
lib/biryani/frame/headers.rb,
lib/biryani/frame/unknown.rb,
lib/biryani/frame/priority.rb,
lib/biryani/frame/settings.rb,
lib/biryani/frame/rst_stream.rb,
lib/biryani/frame/continuation.rb,
lib/biryani/frame/push_promise.rb,
lib/biryani/frame/window_update.rb

Defined Under Namespace

Classes: Continuation, Data, Goaway, Headers, Ping, Priority, PushPromise, RstStream, Settings, Unknown, WindowUpdate

Class Method Summary collapse

Class Method Details

.read(io) ⇒ Object, ...

Returns frame or error.

Parameters:

  • io (IO)

Returns:



137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/biryani/frame.rb', line 137

def self.read(io)
  s = io.read(9)
  return nil if s.nil?
  return ConnectionError.new(ErrorCode::FRAME_SIZE_ERROR, 'invalid header length') if s.bytesize != 9

  payload_length, f_type, flags, stream_id = read_header(s)
  payload = io.read(payload_length)
  return ConnectionError.new(ErrorCode::PROTOCOL_ERROR, 'invalid frame') if payload.bytesize != payload_length
  return Frame::Unknown.new(f_type, flags, stream_id, payload) unless FRAME_MAP.key?(f_type)

  FRAME_MAP[f_type].read(payload, flags, stream_id)
rescue StandardError
  ConnectionError.new(ErrorCode::FRAME_SIZE_ERROR, 'invalid frame')
end

.read_ack(uint8) ⇒ Boolean

Parameters:

  • uint8 (Integer)

Returns:

  • (Boolean)


83
84
85
# File 'lib/biryani/frame.rb', line 83

def self.read_ack(uint8)
  (uint8 & 0b00000001).positive?
end

.read_end_headers(uint8) ⇒ Boolean

Parameters:

  • uint8 (Integer)

Returns:

  • (Boolean)


69
70
71
# File 'lib/biryani/frame.rb', line 69

def self.read_end_headers(uint8)
  (uint8 & 0b00000100).positive?
end

.read_end_stream(uint8) ⇒ Boolean

Parameters:

  • uint8 (Integer)

Returns:

  • (Boolean)


76
77
78
# File 'lib/biryani/frame.rb', line 76

def self.read_end_stream(uint8)
  (uint8 & 0b00000001).positive?
end

.read_header(s) ⇒ Integer

Parameters:

  • s (String)

Returns:

  • (Integer)
  • (Integer)
  • (Integer)
  • (Integer)


44
45
46
47
48
49
50
# File 'lib/biryani/frame.rb', line 44

def self.read_header(s)
  b0, b1, b2, f_type, flags, stream_id = s.unpack('CCCCCN')
  payload_length = (b0 << 16) | (b1 << 8) | b2
  stream_id %= 2**31 # Stream Identifier (31)

  [payload_length, f_type, flags, stream_id]
end

.read_padded(uint8) ⇒ Boolean

Parameters:

  • uint8 (Integer)

Returns:

  • (Boolean)


62
63
64
# File 'lib/biryani/frame.rb', line 62

def self.read_padded(uint8)
  (uint8 & 0b00001000).positive?
end

.read_priority(uint8) ⇒ Boolean

Parameters:

  • uint8 (Integer)

Returns:

  • (Boolean)


55
56
57
# File 'lib/biryani/frame.rb', line 55

def self.read_priority(uint8)
  (uint8 & 0b00100000).positive?
end

.to_binary_s_header(payload_length, f_type, flags, stream_id) ⇒ String

Parameters:

  • payload_length (Integer)
  • f_type (Integer)
  • flags (Integer)
  • stream_id

Returns:

  • (String)


98
99
100
# File 'lib/biryani/frame.rb', line 98

def self.to_binary_s_header(payload_length, f_type, flags, stream_id)
  [payload_length, f_type, flags, stream_id].pack('NCCN')[1..]
end

.to_flags(priority: false, padded: false, end_headers: false, end_stream: false, ack: false) ⇒ Integer

Returns:

  • (Integer)


88
89
90
# File 'lib/biryani/frame.rb', line 88

def self.to_flags(priority: false, padded: false, end_headers: false, end_stream: false, ack: false)
  (priority ? 32 : 0) + (padded ? 8 : 0) + (end_headers ? 4 : 0) + (end_stream || ack ? 1 : 0)
end