http-2 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 96271a021aa473e7c555c6ceca6509f30e4ad457051e3971304c5a841afe4ca6
4
- data.tar.gz: 5f2284ff6211f414291337d4efe260fc52bb9e18ccdb8bf19408ae781469994c
3
+ metadata.gz: c96822381e28e32127984c2dbb7b25b3ad5dd87d69283a752378a9f8778c72ae
4
+ data.tar.gz: beb68a1eb2670d1d0b742224b5ad65bd2bc299656433b120ff31299a481297ce
5
5
  SHA512:
6
- metadata.gz: 6a3f9b4f1a98f232405b85559c91d976c0712defe2cfe1e1ef4468bc81b7e278abd162f3e0de8828dddcdfaff11808a0cab7c794353f5224303eb8b00a4b44ec
7
- data.tar.gz: e14c1ec4652af944dfa791dacae8af519982c04b652b9ef352a1aa2377a15c80f829a2654da7c6e556680d522c7405137e4e5ab24dcb68e196eeb41e5ad54a18
6
+ metadata.gz: 173e0163e2b05ff3eefdfcc420f8c3913c97702873964ef6c653f0329726443c4c10d73d7ffff31583b06567ef12c8f6545eae0f3d32c52d9b13d98322c09e32
7
+ data.tar.gz: 43b38b2bdd3ed6ac90382b98c96b03fd76edefbbf4a385c67c3c8db67e6f755382f09c8a3af848a1d8ed55335ad2925d05793ad71c16c5bb831b07f86e0228be
@@ -52,8 +52,7 @@ module HTTP2
52
52
  include FlowBuffer
53
53
  include Emitter
54
54
  include Error
55
-
56
- using StringExtensions
55
+ include BufferUtils
57
56
 
58
57
  # Connection state (:new, :closed).
59
58
  attr_reader :state
@@ -202,7 +201,7 @@ module HTTP2
202
201
  raise HandshakeError unless CONNECTION_PREFACE_MAGIC.start_with? @recv_buffer
203
202
 
204
203
  return # maybe next time
205
- elsif @recv_buffer.read(24) == CONNECTION_PREFACE_MAGIC
204
+ elsif read_str(@recv_buffer, 24) == CONNECTION_PREFACE_MAGIC
206
205
  # MAGIC is OK. Send our settings
207
206
  @state = :waiting_connection_preface
208
207
  payload = @local_settings.reject { |k, v| v == SPEC_DEFAULT_CONNECTION_SETTINGS[k] }
@@ -1,24 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTP2
4
- module StringExtensions
5
- refine String do
6
- def read(n)
7
- return "".b if n == 0
4
+ module BufferUtils
5
+ def read_str(str, n)
6
+ return "".b if n == 0
8
7
 
9
- chunk = byteslice(0..n - 1)
10
- remaining = byteslice(n..-1)
11
- remaining ? replace(remaining) : clear
12
- chunk
13
- end
8
+ chunk = str.byteslice(0..n - 1)
9
+ remaining = str.byteslice(n..-1)
10
+ remaining ? str.replace(remaining) : str.clear
11
+ chunk
12
+ end
14
13
 
15
- def read_uint32
16
- read(4).unpack1("N")
17
- end
14
+ def read_uint32(str)
15
+ read_str(str, 4).unpack1("N")
16
+ end
18
17
 
19
- def shift_byte
20
- read(1).ord
21
- end
18
+ def shift_byte(str)
19
+ read_str(str, 1).ord
22
20
  end
23
21
  end
24
22
 
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
@@ -165,7 +164,7 @@ module HTTP2
165
164
  frame[:type], = FRAME_TYPES.find { |_t, pos| type == pos }
166
165
  if frame[:type]
167
166
  frame[:flags] = FRAME_FLAGS[frame[:type]].each_with_object([]) do |(name, pos), acc|
168
- acc << name if (flags & (1 << pos)) > 0
167
+ acc << name if flags.anybits?((1 << pos))
169
168
  end
170
169
  end
171
170
 
@@ -344,8 +343,8 @@ module HTTP2
344
343
 
345
344
  raise ProtocolError, "payload too large" if frame[:length] > @local_max_frame_size
346
345
 
347
- buf.read(9)
348
- payload = buf.read(frame[:length])
346
+ read_str(buf, 9)
347
+ payload = read_str(buf, frame[:length])
349
348
 
350
349
  # Implementations MUST discard frames
351
350
  # that have unknown or unsupported types.
@@ -357,7 +356,7 @@ module HTTP2
357
356
  if FRAME_TYPES_WITH_PADDING.include?(frame[:type])
358
357
  padded = frame[:flags].include?(:padded)
359
358
  if padded
360
- padlen = payload.read(1).unpack1(UINT8)
359
+ padlen = read_str(payload, 1).unpack1(UINT8)
361
360
  frame[:padding] = padlen + 1
362
361
  raise ProtocolError, "padding too long" if padlen > payload.bytesize
363
362
 
@@ -369,30 +368,30 @@ module HTTP2
369
368
 
370
369
  case frame[:type]
371
370
  when :data, :ping, :continuation
372
- frame[:payload] = payload.read(frame[:length])
371
+ frame[:payload] = read_str(payload, frame[:length])
373
372
  when :headers
374
373
  if frame[:flags].include? :priority
375
- e_sd = payload.read_uint32
374
+ e_sd = read_uint32(payload)
376
375
  frame[:dependency] = e_sd & RBIT
377
- frame[:exclusive] = (e_sd & EBIT) != 0
376
+ frame[:exclusive] = e_sd.anybits?(EBIT)
378
377
  weight = payload.byteslice(0, 1).ord + 1
379
378
  frame[:weight] = weight
380
379
  payload = payload.byteslice(1..-1)
381
380
  end
382
- frame[:payload] = payload.read(frame[:length])
381
+ frame[:payload] = read_str(payload, frame[:length])
383
382
  when :priority
384
383
  raise FrameSizeError, "Invalid length for PRIORITY_STREAM (#{frame[:length]} != 5)" if frame[:length] != 5
385
384
 
386
- e_sd = payload.read_uint32
385
+ e_sd = read_uint32(payload)
387
386
  frame[:dependency] = e_sd & RBIT
388
- frame[:exclusive] = (e_sd & EBIT) != 0
387
+ frame[:exclusive] = e_sd.anybits?(EBIT)
389
388
  weight = payload.byteslice(0, 1).ord + 1
390
389
  frame[:weight] = weight
391
390
  payload = payload.byteslice(1..-1)
392
391
  when :rst_stream
393
392
  raise FrameSizeError, "Invalid length for RST_STREAM (#{frame[:length]} != 4)" if frame[:length] != 4
394
393
 
395
- frame[:error] = unpack_error payload.read_uint32
394
+ frame[:error] = unpack_error read_uint32(payload)
396
395
 
397
396
  when :settings
398
397
  # NOTE: frame[:length] might not match the number of frame[:payload]
@@ -403,8 +402,8 @@ module HTTP2
403
402
  raise ProtocolError, "Invalid stream ID (#{frame[:stream]})" if (frame[:stream]).nonzero?
404
403
 
405
404
  (frame[:length] / 6).times do
406
- id = payload.read(2).unpack1(UINT16)
407
- val = payload.read_uint32
405
+ id = read_str(payload, 2).unpack1(UINT16)
406
+ val = read_uint32(payload)
408
407
 
409
408
  # Unsupported or unrecognized settings MUST be ignored.
410
409
  # Here we send it along.
@@ -412,39 +411,39 @@ module HTTP2
412
411
  frame[:payload] << [name, val] if name
413
412
  end
414
413
  when :push_promise
415
- frame[:promise_stream] = payload.read_uint32 & RBIT
416
- frame[:payload] = payload.read(frame[:length])
414
+ frame[:promise_stream] = read_uint32(payload) & RBIT
415
+ frame[:payload] = read_str(payload, frame[:length])
417
416
  when :goaway
418
- frame[:last_stream] = payload.read_uint32 & RBIT
419
- frame[:error] = unpack_error payload.read_uint32
417
+ frame[:last_stream] = read_uint32(payload) & RBIT
418
+ frame[:error] = unpack_error read_uint32(payload)
420
419
 
421
420
  size = frame[:length] - 8 # for last_stream and error
422
- frame[:payload] = payload.read(size) if size > 0
421
+ frame[:payload] = read_str(payload, size) if size > 0
423
422
  when :window_update
424
423
  if frame[:length] % 4 != 0
425
424
  raise FrameSizeError, "Invalid length for WINDOW_UPDATE (#{frame[:length]} not multiple of 4)"
426
425
  end
427
426
 
428
- frame[:increment] = payload.read_uint32 & RBIT
427
+ frame[:increment] = read_uint32(payload) & RBIT
429
428
  when :altsvc
430
- frame[:max_age], frame[:port] = payload.read(6).unpack(UINT32 + UINT16)
429
+ frame[:max_age], frame[:port] = read_str(payload, 6).unpack(UINT32 + UINT16)
431
430
 
432
431
  len = payload.byteslice(0, 1).ord
433
432
  payload = payload.byteslice(1..-1)
434
- frame[:proto] = payload.read(len) if len > 0
433
+ frame[:proto] = read_str(payload, len) if len > 0
435
434
 
436
435
  len = payload.byteslice(0, 1).ord
437
436
  payload = payload.byteslice(1..-1)
438
- frame[:host] = payload.read(len) if len > 0
437
+ frame[:host] = read_str(payload, len) if len > 0
439
438
 
440
- frame[:origin] = payload.read(payload.size) unless payload.empty?
439
+ frame[:origin] = read_str(payload, payload.size) unless payload.empty?
441
440
 
442
441
  when :origin
443
442
  origins = []
444
443
 
445
444
  until payload.empty?
446
- len = payload.read(2).unpack1(UINT16)
447
- origins << payload.read(len)
445
+ len = read_str(payload, 2).unpack1(UINT16)
446
+ origins << read_str(payload, len)
448
447
  end
449
448
 
450
449
  frame[:payload] = origins
@@ -2,7 +2,6 @@
2
2
 
3
3
  module HTTP2
4
4
  module Header
5
- using StringExtensions
6
5
  # Responsible for decoding received headers and maintaining compression
7
6
  # context of the opposing peer. Decompressor must be initialized with
8
7
  # appropriate starting context based on local role: client or server.
@@ -12,6 +11,7 @@ module HTTP2
12
11
  # client_role = Decompressor.new(:response)
13
12
  class Decompressor
14
13
  include Error
14
+ include BufferUtils
15
15
 
16
16
  # @param options [Hash] decoding options. Only :table_size is effective.
17
17
  def initialize(options = {})
@@ -31,15 +31,15 @@ module HTTP2
31
31
  # @return [Integer]
32
32
  def integer(buf, n)
33
33
  limit = (2**n) - 1
34
- i = n.zero? ? 0 : (buf.shift_byte & limit)
34
+ i = n.zero? ? 0 : (shift_byte(buf) & limit)
35
35
 
36
36
  m = 0
37
37
  if i == limit
38
- while (byte = buf.shift_byte)
38
+ while (byte = shift_byte(buf))
39
39
  i += ((byte & 127) << m)
40
40
  m += 7
41
41
 
42
- break if (byte & 128).zero?
42
+ break if byte.nobits?(128)
43
43
  end
44
44
  end
45
45
 
@@ -54,9 +54,9 @@ module HTTP2
54
54
  def string(buf)
55
55
  raise CompressionError, "invalid header block fragment" if buf.empty?
56
56
 
57
- huffman = (buf.getbyte(0) & 0x80) == 0x80
57
+ huffman = buf.getbyte(0).allbits?(0x80)
58
58
  len = integer(buf, 7)
59
- str = buf.read(len)
59
+ str = read_str(buf, len)
60
60
  raise CompressionError, "string too short" unless str.bytesize == len
61
61
 
62
62
  str = Huffman.new.decode(str) if huffman
@@ -75,12 +75,14 @@ module HTTP2
75
75
  ["vary", ""],
76
76
  ["via", ""],
77
77
  ["www-authenticate", ""]
78
- ].each { |pair| pair.each(&:freeze).freeze }.freeze
79
-
80
- STATIC_TABLE_BY_FIELD = STATIC_TABLE
81
- .each_with_object({})
82
- .with_index { |((field, value), hs), idx| (hs[field] ||= []) << [idx, value] }
83
- .each { |pair| pair.each(&:freeze).freeze }.freeze
78
+ ].each(&:freeze).freeze
79
+
80
+ STATIC_TABLE_BY_FIELD =
81
+ STATIC_TABLE
82
+ .each_with_object({})
83
+ .with_index { |((field, value), hs), idx| (hs[field] ||= []) << [idx, value].freeze }
84
+ .each_value(&:freeze)
85
+ .freeze
84
86
 
85
87
  STATIC_TABLE_SIZE = STATIC_TABLE.size
86
88
 
@@ -10,8 +10,6 @@ module HTTP2
10
10
  module Header
11
11
  # Huffman encoder/decoder
12
12
  class Huffman
13
- using StringExtensions
14
-
15
13
  include Error
16
14
  include PackingExtensions
17
15
 
@@ -268,7 +268,7 @@ module HTTP2
268
268
  [[28, 29], [28, 5], [29, 29], [29, 5], [30, 29], [30, 5], [31, 29], [31, 5], [127, 29], [127, 5], [220, 29], [220, 5], [249, 29], [249, 5], [nil, 254], [nil, 255]],
269
269
  [[10, 17], [10, 18], [10, 19], [10, 20], [10, 21], [10, 22], [10, 23], [10, 7], [13, 17], [13, 18], [13, 19], [13, 20], [13, 21], [13, 22], [13, 23], [13, 7]],
270
270
  [[22, 17], [22, 18], [22, 19], [22, 20], [22, 21], [22, 22], [22, 23], [22, 7], [256, 17], [256, 18], [256, 19], [256, 20], [256, 21], [256, 22], [256, 23], [256, 7]],
271
- ].each { |arr| arr.each { |subarr| subarr.each(&:freeze) }.freeze }.freeze
271
+ ].each { |arr| arr.each { |subarr| subarr.freeze }.freeze }.freeze
272
272
  end
273
273
  end
274
274
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTP2
4
- VERSION = "1.0.1"
4
+ VERSION = "1.0.2"
5
5
  end
data/sig/connection.rbs CHANGED
@@ -2,6 +2,7 @@ module HTTP2
2
2
  class Connection
3
3
  include FlowBuffer
4
4
  include Emitter
5
+ include BufferUtils
5
6
 
6
7
  REQUEST_MANDATORY_HEADERS: Array[String]
7
8
  RESPONSE_MANDATORY_HEADERS: Array[String]
data/sig/extensions.rbs CHANGED
@@ -1,4 +1,12 @@
1
1
  module HTTP2
2
+ module BufferUtils
3
+ def read_str: (String str, Integer n) -> String
4
+
5
+ def read_uint32: (String str) -> Integer
6
+
7
+ def shift_byte: (String str) -> Integer
8
+ end
9
+
2
10
  module PackingExtensions
3
11
  def pack: (Array[Integer] array_to_pack, String template, buffer: String, ?offset: Integer) -> String
4
12
  end
data/sig/framer.rbs CHANGED
@@ -1,6 +1,7 @@
1
1
  module HTTP2
2
2
  class Framer
3
3
  include PackingExtensions
4
+ include BufferUtils
4
5
 
5
6
  DEFAULT_MAX_FRAME_SIZE: Integer
6
7
 
@@ -1,6 +1,8 @@
1
1
  module HTTP2
2
2
  module Header
3
3
  class Decompressor
4
+ include BufferUtils
5
+
4
6
  @cc: EncodingContext
5
7
 
6
8
  def table_size=: (Integer) -> void
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http-2
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Cardoso
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2024-07-26 00:00:00.000000000 Z
13
+ date: 2024-11-05 00:00:00.000000000 Z
14
14
  dependencies: []
15
15
  description: Pure-ruby HTTP 2.0 protocol implementation
16
16
  email: