1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
|
# frozen_string_literal: true
# Released under the MIT License.
# Copyright, 2019-2025, by Samuel Williams.
require_relative "frame"
module Protocol
module HTTP2
# Certain frames can have padding:
# https://http2.github.io/http2-spec/#padding
#
# +---------------+
# |Pad Length? (8)|
# +---------------+-----------------------------------------------+
# | Data (*) ...
# +---------------------------------------------------------------+
# | Padding (*) ...
# +---------------------------------------------------------------+
#
# Provides padding functionality for HTTP/2 frames.
# Padding can be used to obscure the actual size of frame payloads.
module Padded
# Check if the frame has padding enabled.
# @returns [Boolean] True if the PADDED flag is set.
def padded?
flag_set?(PADDED)
end
# Pack data with optional padding into the frame.
# @parameter data [String] The data to pack.
# @parameter padding_size [Integer | Nil] Number of padding bytes to add.
# @parameter maximum_size [Integer | Nil] Maximum frame size limit.
def pack(data, padding_size: nil, maximum_size: nil)
if padding_size
set_flags(PADDED)
buffer = String.new.b
buffer << padding_size
buffer << data
if padding_size
buffer << ("\0" * padding_size)
end
super buffer
else
clear_flags(PADDED)
super data
end
end
# Unpack frame data, removing padding if present.
# @returns [String] The unpacked data without padding.
# @raises [ProtocolError] If padding length is invalid.
def unpack
if padded?
padding_size = @payload[0].ord
# 1 byte for the padding octet, and padding_size bytes for the padding itself:
data_size = @payload.bytesize - (1 + padding_size)
if data_size < 0
raise ProtocolError, "Invalid padding length: #{padding_size}"
end
return @payload.byteslice(1, data_size)
else
return @payload
end
end
end
end
end
|