http-2 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,6 +7,8 @@ module HTTP2
7
7
  module FlowBuffer
8
8
  include Error
9
9
 
10
+ attr_reader :send_buffer
11
+
10
12
  MAX_WINDOW_SIZE = (2 << 30) - 1
11
13
 
12
14
  # Amount of buffered data. Only DATA payloads are subject to flow stream
@@ -14,7 +16,7 @@ module HTTP2
14
16
  #
15
17
  # @return [Integer]
16
18
  def buffered_amount
17
- send_buffer.bytesize
19
+ @send_buffer.bytesize
18
20
  end
19
21
 
20
22
  def flush
@@ -23,13 +25,9 @@ module HTTP2
23
25
 
24
26
  private
25
27
 
26
- def send_buffer
27
- @send_buffer ||= FrameBuffer.new
28
- end
29
-
30
28
  def update_local_window(frame)
31
29
  frame_size = frame[:payload].bytesize
32
- frame_size += frame[:padding] || 0
30
+ frame_size += frame.fetch(:padding, 0)
33
31
  @local_window -= frame_size
34
32
  end
35
33
 
@@ -69,31 +67,47 @@ module HTTP2
69
67
  # @param frame [Hash]
70
68
  # @param encode [Boolean] set to true by connection
71
69
  def send_data(frame = nil, encode = false)
72
- send_buffer << frame unless frame.nil?
70
+ if frame
71
+ if @send_buffer.empty?
72
+ frame_size = frame[:payload].bytesize
73
+ end_stream = frame[:flags].include?(:end_stream)
74
+ # if buffer is empty, and frame is either end 0 length OR
75
+ # is within available window size, skip buffering and send immediately.
76
+ if @remote_window.positive?
77
+ return send_frame(frame, encode) if frame_size <= @remote_window
78
+ elsif frame_size.zero? && end_stream
79
+ return send_frame(frame, encode)
80
+ end
81
+ end
73
82
 
74
- while (frame = send_buffer.retrieve(@remote_window))
83
+ @send_buffer << frame
84
+ end
75
85
 
76
- # puts "#{self.class} -> #{@remote_window}"
77
- sent = frame[:payload].bytesize
86
+ while (frame = @send_buffer.retrieve(@remote_window))
87
+ send_frame(frame, encode)
88
+ end
89
+ end
78
90
 
79
- manage_state(frame) do
80
- if encode
81
- encode(frame).each { |f| emit(:frame, f) }
82
- else
83
- emit(:frame, frame)
84
- end
85
- @remote_window -= sent
91
+ def send_frame(frame, encode)
92
+ sent = frame[:payload].bytesize
93
+
94
+ manage_state(frame) do
95
+ if encode
96
+ encode(frame)
97
+ else
98
+ emit(:frame, frame)
86
99
  end
100
+ @remote_window -= sent
87
101
  end
88
102
  end
89
103
 
90
104
  def process_window_update(frame:, encode: false)
91
105
  return if frame[:ignore]
92
106
 
93
- if frame[:increment]
94
- raise ProtocolError, "increment MUST be higher than zero" if frame[:increment].zero?
107
+ if (increment = frame[:increment])
108
+ raise ProtocolError, "increment MUST be higher than zero" if increment.zero?
95
109
 
96
- @remote_window += frame[:increment]
110
+ @remote_window += increment
97
111
  error(:flow_control_error, msg: "window size too large") if @remote_window > MAX_WINDOW_SIZE
98
112
  end
99
113
  send_data(nil, encode)
@@ -114,45 +128,41 @@ module HTTP2
114
128
  end
115
129
 
116
130
  def empty?
117
- @bytesize.zero?
131
+ @buffer.empty?
118
132
  end
119
133
 
120
134
  def retrieve(window_size)
121
135
  frame = @buffer.first or return
122
136
 
123
137
  frame_size = frame[:payload].bytesize
124
- end_stream = frame[:flags].include? :end_stream
138
+ end_stream = frame[:flags].include?(:end_stream)
125
139
 
126
140
  # Frames with zero length with the END_STREAM flag set (that
127
141
  # is, an empty DATA frame) MAY be sent if there is no available space
128
142
  # in either flow control window.
129
- return if window_size <= 0 && !(frame_size == 0 && end_stream)
130
-
131
- @buffer.shift
143
+ return if window_size <= 0 && !(frame_size.zero? && end_stream)
132
144
 
133
145
  if frame_size > window_size
134
- payload = frame[:payload]
135
146
  chunk = frame.dup
147
+ payload = frame[:payload]
136
148
 
137
149
  # Split frame so that it fits in the window
138
150
  # TODO: consider padding!
139
- frame_bytes = payload.byteslice(0, window_size)
140
- payload = payload.byteslice(window_size..-1)
141
151
 
142
- frame[:payload] = frame_bytes
143
- frame[:length] = frame_bytes.bytesize
144
- chunk[:payload] = payload
145
- chunk[:length] = payload.bytesize
152
+ chunk[:payload] = payload.byteslice(0, window_size)
153
+ chunk[:length] = window_size
154
+ frame[:payload] = payload.byteslice(window_size..-1)
155
+ frame[:length] = frame_size - window_size
146
156
 
147
157
  # if no longer last frame in sequence...
148
- frame[:flags] -= [:end_stream] if end_stream
158
+ chunk[:flags] -= [:end_stream] if end_stream
149
159
 
150
- @buffer.unshift(chunk)
151
160
  @bytesize -= window_size
161
+ chunk
152
162
  else
153
163
  @bytesize -= frame_size
164
+ @buffer.shift
154
165
  end
155
- frame
156
166
  end
157
167
  end
158
168
  end
data/lib/http/2/framer.rb CHANGED
@@ -4,10 +4,9 @@ module HTTP2
4
4
  # Performs encoding, decoding, and validation of binary HTTP/2 frames.
5
5
  #
6
6
  class Framer
7
- using StringExtensions
8
-
9
7
  include Error
10
8
  include PackingExtensions
9
+ include BufferUtils
11
10
 
12
11
  # Default value of max frame size (16384 bytes)
13
12
  DEFAULT_MAX_FRAME_SIZE = 2 << 13
@@ -37,6 +36,8 @@ module HTTP2
37
36
  origin: 0xc
38
37
  }.freeze
39
38
 
39
+ FRAME_TYPES_BY_NAME = FRAME_TYPES.invert.freeze
40
+
40
41
  FRAME_TYPES_WITH_PADDING = %i[data headers push_promise].freeze
41
42
 
42
43
  # Per frame flags as defined by the spec
@@ -127,30 +128,43 @@ module HTTP2
127
128
  # @param buffer [String] buffer to pack bytes into
128
129
  # @return [String]
129
130
  def common_header(frame, buffer:)
130
- raise CompressionError, "Invalid frame type (#{frame[:type]})" unless FRAME_TYPES[frame[:type]]
131
+ type = frame[:type]
132
+
133
+ raise CompressionError, "Invalid frame type (#{type})" unless FRAME_TYPES[type]
134
+
135
+ length = frame[:length]
131
136
 
132
- raise CompressionError, "Frame size is too large: #{frame[:length]}" if frame[:length] > @remote_max_frame_size
137
+ raise CompressionError, "Frame size is too large: #{length}" if length > @remote_max_frame_size
133
138
 
134
- raise CompressionError, "Frame size is invalid: #{frame[:length]}" if frame[:length] < 0
139
+ raise CompressionError, "Frame size is invalid: #{length}" if length < 0
135
140
 
136
- raise CompressionError, "Stream ID (#{frame[:stream]}) is too large" if frame[:stream] > MAX_STREAM_ID
141
+ stream_id = frame.fetch(:stream, 0)
137
142
 
138
- if frame[:type] == :window_update && frame[:increment] > MAX_WINDOWINC
143
+ raise CompressionError, "Stream ID (#{stream_id}) is too large" if stream_id > MAX_STREAM_ID
144
+
145
+ if type == :window_update && frame[:increment] > MAX_WINDOWINC
139
146
  raise CompressionError, "Window increment (#{frame[:increment]}) is too large"
140
147
  end
141
148
 
149
+ header = buffer
150
+
151
+ if buffer.frozen?
152
+ header = String.new("", encoding: Encoding::BINARY, capacity: buffer.bytesize + 9) # header length
153
+ header << buffer
154
+ end
155
+
142
156
  pack([
143
- (frame[:length] >> FRAME_LENGTH_HISHIFT),
144
- (frame[:length] & FRAME_LENGTH_LOMASK),
145
- FRAME_TYPES[frame[:type]],
157
+ (length >> FRAME_LENGTH_HISHIFT),
158
+ (length & FRAME_LENGTH_LOMASK),
159
+ FRAME_TYPES[type],
146
160
  frame[:flags].reduce(0) do |acc, f|
147
- position = FRAME_FLAGS[frame[:type]][f]
148
- raise CompressionError, "Invalid frame flag (#{f}) for #{frame[:type]}" unless position
161
+ position = FRAME_FLAGS[type][f]
162
+ raise CompressionError, "Invalid frame flag (#{f}) for #{type}" unless position
149
163
 
150
164
  acc | (1 << position)
151
165
  end,
152
- frame[:stream]
153
- ], HEADERPACK, buffer: buffer, offset: 0) # 8+16,8,8,32
166
+ stream_id
167
+ ], HEADERPACK, buffer: header, offset: 0) # 8+16,8,8,32
154
168
  end
155
169
 
156
170
  # Decodes common 9-byte header.
@@ -158,19 +172,21 @@ module HTTP2
158
172
  # @param buf [Buffer]
159
173
  # @return [Hash] the corresponding frame
160
174
  def read_common_header(buf)
161
- frame = {}
162
175
  len_hi, len_lo, type, flags, stream = buf.byteslice(0, 9).unpack(HEADERPACK)
163
176
 
164
- frame[:length] = (len_hi << FRAME_LENGTH_HISHIFT) | len_lo
165
- frame[:type], = FRAME_TYPES.find { |_t, pos| type == pos }
166
- if frame[:type]
167
- frame[:flags] = FRAME_FLAGS[frame[:type]].each_with_object([]) do |(name, pos), acc|
168
- acc << name if (flags & (1 << pos)) > 0
169
- end
170
- end
177
+ type = FRAME_TYPES_BY_NAME[type]
178
+ length = (len_hi << FRAME_LENGTH_HISHIFT) | len_lo
171
179
 
172
- frame[:stream] = stream & RBIT
173
- frame
180
+ return { length: length } unless type
181
+
182
+ {
183
+ type: type,
184
+ flags: FRAME_FLAGS[type].filter_map do |name, pos|
185
+ name if flags.anybits?((1 << pos))
186
+ end,
187
+ length: length,
188
+ stream: stream & RBIT
189
+ }
174
190
  end
175
191
 
176
192
  # Generates encoded HTTP/2 frame.
@@ -178,53 +194,60 @@ module HTTP2
178
194
  #
179
195
  # @param frame [Hash]
180
196
  def generate(frame)
181
- bytes = "".b
182
197
  length = 0
183
-
184
- frame[:flags] ||= []
185
- frame[:stream] ||= 0
198
+ frame[:flags] ||= EMPTY
186
199
 
187
200
  case frame[:type]
188
- when :data
189
- bytes << frame[:payload]
190
- bytes.force_encoding(Encoding::BINARY)
191
- length += frame[:payload].bytesize
201
+ when :data, :continuation
202
+ bytes = frame[:payload]
203
+ length = bytes.bytesize
192
204
 
193
205
  when :headers
206
+ headers = frame[:payload]
207
+
194
208
  if frame[:weight] || frame[:dependency] || !frame[:exclusive].nil?
195
209
  unless frame[:weight] && frame[:dependency] && !frame[:exclusive].nil?
196
210
  raise CompressionError, "Must specify all of priority parameters for #{frame[:type]}"
197
211
  end
198
212
 
199
- frame[:flags] += [:priority] unless frame[:flags].include? :priority
213
+ frame[:flags] += [:priority] unless frame[:flags].include?(:priority)
200
214
  end
201
215
 
202
- if frame[:flags].include? :priority
216
+ if frame[:flags].include?(:priority)
217
+ length = 5 + headers.bytesize
218
+ bytes = String.new("", encoding: Encoding::BINARY, capacity: length)
203
219
  pack([(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT)], UINT32, buffer: bytes)
204
220
  pack([frame[:weight] - 1], UINT8, buffer: bytes)
205
- length += 5
221
+ append_str(bytes, headers)
222
+ else
223
+ length = headers.bytesize
224
+ bytes = headers
206
225
  end
207
226
 
208
- bytes << frame[:payload]
209
- length += frame[:payload].bytesize
210
-
211
227
  when :priority
212
228
  unless frame[:weight] && frame[:dependency] && !frame[:exclusive].nil?
213
229
  raise CompressionError, "Must specify all of priority parameters for #{frame[:type]}"
214
230
  end
215
231
 
232
+ length = 5
233
+ bytes = String.new("", encoding: Encoding::BINARY, capacity: length)
216
234
  pack([(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT)], UINT32, buffer: bytes)
217
235
  pack([frame[:weight] - 1], UINT8, buffer: bytes)
218
- length += 5
219
236
 
220
237
  when :rst_stream
238
+ length = 4
239
+ bytes = String.new("", encoding: Encoding::BINARY, capacity: length)
221
240
  pack_error(frame[:error], buffer: bytes)
222
- length += 4
223
241
 
224
242
  when :settings
225
- raise CompressionError, "Invalid stream ID (#{frame[:stream]})" if (frame[:stream]).nonzero?
243
+ if (stream_id = frame[:stream]) && stream_id.nonzero?
244
+ raise CompressionError, "Invalid stream ID (#{stream_id})"
245
+ end
226
246
 
227
- frame[:payload].each do |(k, v)|
247
+ settings = frame[:payload]
248
+ bytes = String.new("", encoding: Encoding::BINARY, capacity: length)
249
+
250
+ settings.each do |(k, v)|
228
251
  if k.is_a? Integer # rubocop:disable Style/GuardClause
229
252
  DEFINED_SETTINGS.value?(k) || next
230
253
  else
@@ -239,42 +262,42 @@ module HTTP2
239
262
  end
240
263
 
241
264
  when :push_promise
265
+ length = 4 + frame[:payload].bytesize
266
+ bytes = String.new("", encoding: Encoding::BINARY, capacity: length)
242
267
  pack([frame[:promise_stream] & RBIT], UINT32, buffer: bytes)
243
- bytes << frame[:payload]
244
- length += 4 + frame[:payload].bytesize
268
+ append_str(bytes, frame[:payload])
245
269
 
246
270
  when :ping
247
- raise CompressionError, "Invalid payload size (#{frame[:payload].size} != 8 bytes)" if frame[:payload].bytesize != 8
271
+ bytes = frame[:payload]
272
+ raise CompressionError, "Invalid payload size (#{bytes.size} != 8 bytes)" if bytes.bytesize != 8
248
273
 
249
- bytes << frame[:payload]
250
- length += 8
274
+ length = 8
251
275
 
252
276
  when :goaway
277
+ data = frame[:payload]
278
+ length = 8
279
+ length += data.bytesize if data
280
+ bytes = String.new("", encoding: Encoding::BINARY, capacity: length)
281
+
253
282
  pack([frame[:last_stream] & RBIT], UINT32, buffer: bytes)
254
283
  pack_error(frame[:error], buffer: bytes)
255
- length += 8
256
284
 
257
- if frame[:payload]
258
- bytes << frame[:payload]
259
- length += frame[:payload].bytesize
260
- end
285
+ append_str(bytes, data) if data
261
286
 
262
287
  when :window_update
288
+ length = 4
289
+ bytes = String.new("", encoding: Encoding::BINARY, capacity: length)
263
290
  pack([frame[:increment] & RBIT], UINT32, buffer: bytes)
264
- length += 4
265
-
266
- when :continuation
267
- bytes << frame[:payload]
268
- length += frame[:payload].bytesize
269
291
 
270
292
  when :altsvc
293
+ length = 6
294
+ bytes = String.new("", encoding: Encoding::BINARY, capacity: length)
271
295
  pack([frame[:max_age], frame[:port]], UINT32 + UINT16, buffer: bytes)
272
- length += 6
273
296
  if frame[:proto]
274
297
  raise CompressionError, "Proto too long" if frame[:proto].bytesize > 255
275
298
 
276
299
  pack([frame[:proto].bytesize], UINT8, buffer: bytes)
277
- bytes << frame[:proto]
300
+ append_str(bytes, frame[:proto])
278
301
  length += 1 + frame[:proto].bytesize
279
302
  else
280
303
  pack([0], UINT8, buffer: bytes)
@@ -284,24 +307,25 @@ module HTTP2
284
307
  raise CompressionError, "Host too long" if frame[:host].bytesize > 255
285
308
 
286
309
  pack([frame[:host].bytesize], UINT8, buffer: bytes)
287
- bytes << frame[:host]
310
+ append_str(bytes, frame[:host])
288
311
  length += 1 + frame[:host].bytesize
289
312
  else
290
313
  pack([0], UINT8, buffer: bytes)
291
314
  length += 1
292
315
  end
293
316
  if frame[:origin]
294
- bytes << frame[:origin]
317
+ append_str(bytes, frame[:origin])
295
318
  length += frame[:origin].bytesize
296
319
  end
297
320
 
298
321
  when :origin
299
- frame[:payload].each do |origin|
322
+ origins = frame[:payload]
323
+ length = origins.sum(&:bytesize) + (2 * origins.size)
324
+ bytes = String.new("", encoding: Encoding::BINARY, capacity: length)
325
+ origins.each do |origin|
300
326
  pack([origin.bytesize], UINT16, buffer: bytes)
301
- bytes << origin
302
- length += 2 + origin.bytesize
327
+ append_str(bytes, origin)
303
328
  end
304
-
305
329
  end
306
330
 
307
331
  # Process padding.
@@ -320,12 +344,12 @@ module HTTP2
320
344
 
321
345
  length += padlen
322
346
  pack([padlen -= 1], UINT8, buffer: bytes, offset: 0)
323
- frame[:flags] << :padded
347
+ frame[:flags] += [:padded]
324
348
 
325
349
  # Padding: Padding octets that contain no application semantic value.
326
350
  # Padding octets MUST be set to zero when sending and ignored when
327
351
  # receiving.
328
- bytes << ("\0" * padlen)
352
+ append_str(bytes, ("\0" * padlen))
329
353
  end
330
354
 
331
355
  frame[:length] = length
@@ -340,71 +364,76 @@ module HTTP2
340
364
  return if buf.size < 9
341
365
 
342
366
  frame = read_common_header(buf)
343
- return if buf.size < 9 + frame[:length]
344
367
 
345
- raise ProtocolError, "payload too large" if frame[:length] > @local_max_frame_size
368
+ type = frame[:type]
369
+ length = frame[:length]
370
+ flags = frame[:flags]
371
+
372
+ return if buf.size < 9 + length
346
373
 
347
- buf.read(9)
348
- payload = buf.read(frame[:length])
374
+ raise ProtocolError, "payload too large" if length > @local_max_frame_size
375
+
376
+ read_str(buf, 9)
377
+ payload = read_str(buf, length)
349
378
 
350
379
  # Implementations MUST discard frames
351
380
  # that have unknown or unsupported types.
352
381
  # - http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-5.5
353
- return frame if frame[:type].nil?
382
+ return frame unless type
354
383
 
355
384
  # Process padding
356
385
  padlen = 0
357
- if FRAME_TYPES_WITH_PADDING.include?(frame[:type])
358
- padded = frame[:flags].include?(:padded)
386
+ if FRAME_TYPES_WITH_PADDING.include?(type)
387
+ padded = flags.include?(:padded)
359
388
  if padded
360
- padlen = payload.read(1).unpack1(UINT8)
389
+ padlen = read_str(payload, 1).unpack1(UINT8)
361
390
  frame[:padding] = padlen + 1
362
391
  raise ProtocolError, "padding too long" if padlen > payload.bytesize
363
392
 
364
393
  payload = payload.byteslice(0, payload.bytesize - padlen) if padlen > 0
365
394
  frame[:length] -= frame[:padding]
366
- frame[:flags].delete(:padded)
395
+ flags.delete(:padded)
367
396
  end
368
397
  end
369
398
 
370
- case frame[:type]
399
+ case type
371
400
  when :data, :ping, :continuation
372
- frame[:payload] = payload.read(frame[:length])
401
+ frame[:payload] = read_str(payload, length)
373
402
  when :headers
374
- if frame[:flags].include? :priority
375
- e_sd = payload.read_uint32
403
+ if flags.include?(:priority)
404
+ e_sd = read_uint32(payload)
376
405
  frame[:dependency] = e_sd & RBIT
377
- frame[:exclusive] = (e_sd & EBIT) != 0
406
+ frame[:exclusive] = e_sd.anybits?(EBIT)
378
407
  weight = payload.byteslice(0, 1).ord + 1
379
408
  frame[:weight] = weight
380
409
  payload = payload.byteslice(1..-1)
381
410
  end
382
- frame[:payload] = payload.read(frame[:length])
411
+ frame[:payload] = read_str(payload, length)
383
412
  when :priority
384
- raise FrameSizeError, "Invalid length for PRIORITY_STREAM (#{frame[:length]} != 5)" if frame[:length] != 5
413
+ raise FrameSizeError, "Invalid length for PRIORITY_STREAM (#{length} != 5)" if length != 5
385
414
 
386
- e_sd = payload.read_uint32
415
+ e_sd = read_uint32(payload)
387
416
  frame[:dependency] = e_sd & RBIT
388
- frame[:exclusive] = (e_sd & EBIT) != 0
417
+ frame[:exclusive] = e_sd.anybits?(EBIT)
389
418
  weight = payload.byteslice(0, 1).ord + 1
390
419
  frame[:weight] = weight
391
420
  payload = payload.byteslice(1..-1)
392
421
  when :rst_stream
393
- raise FrameSizeError, "Invalid length for RST_STREAM (#{frame[:length]} != 4)" if frame[:length] != 4
422
+ raise FrameSizeError, "Invalid length for RST_STREAM (#{length} != 4)" if length != 4
394
423
 
395
- frame[:error] = unpack_error payload.read_uint32
424
+ frame[:error] = unpack_error read_uint32(payload)
396
425
 
397
426
  when :settings
398
427
  # NOTE: frame[:length] might not match the number of frame[:payload]
399
428
  # because unknown extensions are ignored.
400
429
  frame[:payload] = []
401
- raise ProtocolError, "Invalid settings payload length" unless (frame[:length] % 6).zero?
430
+ raise ProtocolError, "Invalid settings payload length" unless (length % 6).zero?
402
431
 
403
- raise ProtocolError, "Invalid stream ID (#{frame[:stream]})" if (frame[:stream]).nonzero?
432
+ raise ProtocolError, "Invalid stream ID (#{frame[:stream]})" if frame[:stream].nonzero?
404
433
 
405
434
  (frame[:length] / 6).times do
406
- id = payload.read(2).unpack1(UINT16)
407
- val = payload.read_uint32
435
+ id = read_str(payload, 2).unpack1(UINT16)
436
+ val = read_uint32(payload)
408
437
 
409
438
  # Unsupported or unrecognized settings MUST be ignored.
410
439
  # Here we send it along.
@@ -412,39 +441,37 @@ module HTTP2
412
441
  frame[:payload] << [name, val] if name
413
442
  end
414
443
  when :push_promise
415
- frame[:promise_stream] = payload.read_uint32 & RBIT
416
- frame[:payload] = payload.read(frame[:length])
444
+ frame[:promise_stream] = read_uint32(payload) & RBIT
445
+ frame[:payload] = read_str(payload, length)
417
446
  when :goaway
418
- frame[:last_stream] = payload.read_uint32 & RBIT
419
- frame[:error] = unpack_error payload.read_uint32
447
+ frame[:last_stream] = read_uint32(payload) & RBIT
448
+ frame[:error] = unpack_error read_uint32(payload)
420
449
 
421
- size = frame[:length] - 8 # for last_stream and error
422
- frame[:payload] = payload.read(size) if size > 0
450
+ size = length - 8 # for last_stream and error
451
+ frame[:payload] = read_str(payload, size) if size > 0
423
452
  when :window_update
424
- if frame[:length] % 4 != 0
425
- raise FrameSizeError, "Invalid length for WINDOW_UPDATE (#{frame[:length]} not multiple of 4)"
426
- end
453
+ raise FrameSizeError, "Invalid length for WINDOW_UPDATE (#{length} not multiple of 4)" if length % 4 != 0
427
454
 
428
- frame[:increment] = payload.read_uint32 & RBIT
455
+ frame[:increment] = read_uint32(payload) & RBIT
429
456
  when :altsvc
430
- frame[:max_age], frame[:port] = payload.read(6).unpack(UINT32 + UINT16)
457
+ frame[:max_age], frame[:port] = read_str(payload, 6).unpack(UINT32 + UINT16)
431
458
 
432
459
  len = payload.byteslice(0, 1).ord
433
460
  payload = payload.byteslice(1..-1)
434
- frame[:proto] = payload.read(len) if len > 0
461
+ frame[:proto] = read_str(payload, len) if len > 0
435
462
 
436
463
  len = payload.byteslice(0, 1).ord
437
464
  payload = payload.byteslice(1..-1)
438
- frame[:host] = payload.read(len) if len > 0
465
+ frame[:host] = read_str(payload, len) if len > 0
439
466
 
440
- frame[:origin] = payload.read(payload.size) unless payload.empty?
467
+ frame[:origin] = read_str(payload, payload.size) unless payload.empty?
441
468
 
442
469
  when :origin
443
470
  origins = []
444
471
 
445
472
  until payload.empty?
446
- len = payload.read(2).unpack1(UINT16)
447
- origins << payload.read(len)
473
+ len = read_str(payload, 2).unpack1(UINT16)
474
+ origins << read_str(payload, len)
448
475
  end
449
476
 
450
477
  frame[:payload] = origins