The Perl Toolchain Summit 2025 Needs You: You can help 🙏 Learn more

use strict;
use constant {
# Header Compression
MAX_INT_SIZE => 4,
MAX_PAYLOAD_SIZE => ( 1 << 24 ) - 1,
# Frame
FRAME_HEADER_SIZE => 9,
# Flow control
MAX_FCW_SIZE => ( 1 << 31 ) - 1,
# Ping payload
PING_PAYLOAD_SIZE => 8,
# Settings defaults
DEFAULT_HEADER_TABLE_SIZE => 4_096,
DEFAULT_ENABLE_PUSH => 1,
DEFAULT_MAX_CONCURRENT_STREAMS => 100,
DEFAULT_INITIAL_WINDOW_SIZE => 65_535,
DEFAULT_MAX_FRAME_SIZE => 16_384,
DEFAULT_MAX_HEADER_LIST_SIZE => 65_536,
# Priority
DEFAULT_WEIGHT => 16,
# Stream states
IDLE => 1,
RESERVED => 2,
OPEN => 3,
HALF_CLOSED => 4,
CLOSED => 5,
# Endpoint types
CLIENT => 1,
SERVER => 2,
# Preface string
PREFACE => "PRI * HTTP/2.0\x0d\x0a\x0d\x0aSM\x0d\x0a\x0d\x0a",
# Frame types
DATA => 0,
HEADERS => 1,
PRIORITY => 2,
RST_STREAM => 3,
SETTINGS => 4,
PUSH_PROMISE => 5,
PING => 6,
GOAWAY => 7,
WINDOW_UPDATE => 8,
CONTINUATION => 9,
# Flags
ACK => 0x1,
END_STREAM => 0x1,
END_HEADERS => 0x4,
PADDED => 0x8,
PRIORITY_FLAG => 0x20,
# Errors
NO_ERROR => 0,
PROTOCOL_ERROR => 1,
INTERNAL_ERROR => 2,
FLOW_CONTROL_ERROR => 3,
SETTINGS_TIMEOUT => 4,
STREAM_CLOSED => 5,
FRAME_SIZE_ERROR => 6,
REFUSED_STREAM => 7,
CANCEL => 8,
COMPRESSION_ERROR => 9,
CONNECT_ERROR => 10,
ENHANCE_YOUR_CALM => 11,
INADEQUATE_SECURITY => 12,
HTTP_1_1_REQUIRED => 13,
# SETTINGS
SETTINGS_HEADER_TABLE_SIZE => 1,
SETTINGS_ENABLE_PUSH => 2,
SETTINGS_MAX_CONCURRENT_STREAMS => 3,
SETTINGS_INITIAL_WINDOW_SIZE => 4,
SETTINGS_MAX_FRAME_SIZE => 5,
SETTINGS_MAX_HEADER_LIST_SIZE => 6,
};
require Exporter;
our @ISA = qw(Exporter);
our %EXPORT_TAGS = (
frame_types => [
qw(DATA HEADERS PRIORITY RST_STREAM SETTINGS PUSH_PROMISE PING GOAWAY
WINDOW_UPDATE CONTINUATION)
],
errors => [
qw(NO_ERROR PROTOCOL_ERROR INTERNAL_ERROR FLOW_CONTROL_ERROR
SETTINGS_TIMEOUT STREAM_CLOSED FRAME_SIZE_ERROR REFUSED_STREAM CANCEL
COMPRESSION_ERROR CONNECT_ERROR ENHANCE_YOUR_CALM INADEQUATE_SECURITY
HTTP_1_1_REQUIRED)
],
preface => [qw(PREFACE)],
flags => [qw(ACK END_STREAM END_HEADERS PADDED PRIORITY_FLAG)],
settings => [
qw(SETTINGS_HEADER_TABLE_SIZE SETTINGS_ENABLE_PUSH
SETTINGS_MAX_CONCURRENT_STREAMS SETTINGS_INITIAL_WINDOW_SIZE
SETTINGS_MAX_FRAME_SIZE SETTINGS_MAX_HEADER_LIST_SIZE)
],
limits => [
qw(MAX_INT_SIZE MAX_PAYLOAD_SIZE PING_PAYLOAD_SIZE MAX_FCW_SIZE
DEFAULT_WEIGHT DEFAULT_HEADER_TABLE_SIZE DEFAULT_MAX_CONCURRENT_STREAMS
DEFAULT_ENABLE_PUSH DEFAULT_INITIAL_WINDOW_SIZE DEFAULT_MAX_FRAME_SIZE
DEFAULT_MAX_HEADER_LIST_SIZE FRAME_HEADER_SIZE)
],
states => [qw(IDLE RESERVED OPEN HALF_CLOSED CLOSED)],
endpoints => [qw(CLIENT SERVER)],
);
my %reverse;
{
no strict 'refs';
for my $k ( keys %EXPORT_TAGS ) {
for my $v ( @{ $EXPORT_TAGS{$k} } ) {
$reverse{$k}{ &{$v} } = $v;
}
}
}
sub const_name {
my ( $tag, $value ) = @_;
exists $reverse{$tag} ? ( $reverse{$tag}{$value} || '' ) : '';
}
our @EXPORT_OK = ( qw(const_name), map { @$_ } values %EXPORT_TAGS );
1;