Class: Plum::Frame

Inherits:
Object
  • Object
show all
Extended by:
FrameFactory
Includes:
FrameUtils
Defined in:
lib/plum/frame.rb

Constant Summary collapse

FRAME_TYPES =
{
  data:           0x00,
  headers:        0x01,
  priority:       0x02,
  rst_stream:     0x03,
  settings:       0x04,
  push_promise:   0x05,
  ping:           0x06,
  goaway:         0x07,
  window_update:  0x08,
  continuation:   0x09
}.freeze
FRAME_FLAGS =
{
  data: {
    end_stream:   0x01,
    padded:       0x08
  }.freeze,
  headers: {
    end_stream:   0x01,
    end_headers:  0x04,
    padded:       0x08,
    priority:     0x20
  }.freeze,
  priority: {}.freeze,
  rst_stream: {}.freeze,
  settings: {
    ack:          0x01
  }.freeze,
  push_promise: {
    end_headers:  0x04,
    padded:       0x08
  }.freeze,
  ping: {
    ack:          0x01
  }.freeze,
  goaway: {}.freeze,
  window_update: {}.freeze,
  continuation: {
    end_headers:  0x04
  }.freeze
}.freeze
SETTINGS_TYPE =
{
  header_table_size:      0x01,
  enable_push:            0x02,
  max_concurrent_streams: 0x03,
  initial_window_size:    0x04,
  max_frame_size:         0x05,
  max_header_list_size:   0x06
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from FrameFactory

continuation, data, goaway, headers, ping, push_promise, rst_stream, settings

Methods included from FrameUtils

#parse_settings, #split

Constructor Details

#initialize(type: nil, type_value: nil, flags: nil, flags_value: nil, stream_id: nil, payload: nil) ⇒ Frame

Returns a new instance of Frame.



87
88
89
90
91
92
93
# File 'lib/plum/frame.rb', line 87

def initialize(type: nil, type_value: nil, flags: nil, flags_value: nil, stream_id: nil, payload: nil)
  @payload = payload || ""
  @length = @payload.bytesize
  @type_value = type_value or self.type = type
  @flags_value = flags_value or self.flags = flags
  @stream_id = stream_id or raise ArgumentError.new("stream_id is necessary")
end

Instance Attribute Details

#flags_valueObject

Integer

Flags. 8-bit



81
82
83
# File 'lib/plum/frame.rb', line 81

def flags_value
  @flags_value
end

#payloadObject (readonly)

String

The payload. Value is frozen.



85
86
87
# File 'lib/plum/frame.rb', line 85

def payload
  @payload
end

#stream_idObject (readonly)

Integer

Stream Identifier. Unsigned 31-bit integer



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

def stream_id
  @stream_id
end

#type_valueObject

Integer

Frame type. 8-bit



79
80
81
# File 'lib/plum/frame.rb', line 79

def type_value
  @type_value
end

Class Method Details

.parse!(buffer) ⇒ Frame?

Parses a frame from given buffer. It changes given buffer.

Parameters:

  • buffer (String)

    The buffer stored the data received from peer. Encoding must be Encoding::BINARY.

Returns:

  • (Frame, nil)

    The parsed frame or nil if the buffer is imcomplete.



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/plum/frame.rb', line 158

def self.parse!(buffer)
  return nil if buffer.bytesize < 9 # header: 9 bytes
  length = buffer.uint24
  return nil if buffer.bytesize < 9 + length

  cur = buffer.byteshift(9 + length)
  type_value, flags_value, r_sid = cur.byteslice(3, 6).unpack("CCN")
  # r = r_sid >> 31 # currently not used
  stream_id = r_sid # & ~(1 << 31)

  self.new(type_value: type_value,
           flags_value: flags_value,
           stream_id: stream_id,
           payload: cur.byteslice(9, length)).freeze
end

Instance Method Details

#assembleString

Assembles the frame into binary representation.

Returns:

  • (String)

    Binary representation of this frame.



143
144
145
146
147
148
# File 'lib/plum/frame.rb', line 143

def assemble
  [length / 0x100, length % 0x100,
   @type_value,
   @flags_value,
   @stream_id].pack("nCCCN") << @payload
end

#flagsArray<Symbol>

Returns the set flags on the frame.

Returns:

  • (Array<Symbol>)

    The flags.



115
116
117
118
119
120
# File 'lib/plum/frame.rb', line 115

def flags
  fs = FRAME_FLAGS[type]
  [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80]
    .select {|v| @flags_value & v > 0 }
    .map {|val| fs && fs.key(val) || ("unknown_%02x" % val).to_sym }
end

#flags=(values) ⇒ Object

Sets the frame flags.

Parameters:

  • values (Array<Symbol>)

    The flags.



124
125
126
127
128
129
130
# File 'lib/plum/frame.rb', line 124

def flags=(values)
  val = 0
  FRAME_FLAGS_MAP.values_at(*values).each { |c|
    val |= c if c
  }
  @flags_value = val
end

#inspectObject



151
152
153
# File 'lib/plum/frame.rb', line 151

def inspect
  "#<Plum::Frame:0x%04x} length=%d, type=%p, flags=%p, stream_id=0x%04x, payload=%p>" % [__id__, length, type, flags, stream_id, payload]
end

#lengthInteger

Returns the length of payload.

Returns:

  • (Integer)

    The length.



97
98
99
# File 'lib/plum/frame.rb', line 97

def length
  @length
end

#typeSymbol

Returns the type of the frame in Symbol.

Returns:

  • (Symbol)

    The type.



103
104
105
# File 'lib/plum/frame.rb', line 103

def type
  FRAME_TYPES_INVERSE[@type_value] || ("unknown_%02x" % @type_value).to_sym
end

#type=(value) ⇒ Object

Sets the frame type.

Parameters:

  • value (Symbol)

    The type.



109
110
111
# File 'lib/plum/frame.rb', line 109

def type=(value)
  @type_value = FRAME_TYPES[value] or raise ArgumentError.new("unknown frame type: #{value}")
end