File Coverage

blib/lib/Protocol/HTTP2/Frame/Settings.pm
Criterion Covered Total %
statement 35 48 72.9
branch 10 16 62.5
condition 1 3 33.3
subroutine 6 6 100.0
pod 0 2 0.0
total 52 75 69.3


line stmt bran cond sub pod time code
1             package Protocol::HTTP2::Frame::Settings;
2 12     12   41 use strict;
  12         14  
  12         297  
3 12     12   34 use warnings;
  12         116  
  12         308  
4 12     12   42 use Protocol::HTTP2::Constants qw(const_name :flags :errors :limits :settings);
  12         11  
  12         2723  
5 12     12   52 use Protocol::HTTP2::Trace qw(tracer);
  12         12  
  12         6080  
6              
7             my %s_check = (
8             &SETTINGS_MAX_FRAME_SIZE => {
9             validator => sub {
10             $_[0] <= MAX_PAYLOAD_SIZE && $_[0] >= DEFAULT_MAX_FRAME_SIZE;
11             },
12             error => PROTOCOL_ERROR
13             },
14             &SETTINGS_ENABLE_PUSH => {
15             validator => sub {
16             $_[0] == 0 || $_[0] == 1;
17             },
18             error => PROTOCOL_ERROR
19             },
20             &SETTINGS_INITIAL_WINDOW_SIZE => {
21             validator => sub {
22             $_[0] <= MAX_FCW_SIZE;
23             },
24             error => FLOW_CONTROL_ERROR
25             },
26             );
27              
28             my %s_action = (
29             &SETTINGS_INITIAL_WINDOW_SIZE => sub {
30             my ( $con, $size ) = @_;
31             $con->fcw_initial_change($size);
32             }
33             );
34              
35             sub decode {
36 65     65 0 6395 my ( $con, $buf_ref, $buf_offset, $length ) = @_;
37 65         6416 my $frame_ref = $con->decode_context->{frame};
38              
39 65 50       6761 if ( $frame_ref->{stream} != 0 ) {
40 0         0 $con->error(PROTOCOL_ERROR);
41 0         0 return undef;
42             }
43              
44             # just ack for our previous settings
45 65 100       6482 if ( $frame_ref->{flags} & ACK ) {
    100          
46 32 50       3228 if ( $length != 0 ) {
47 0         0 tracer->error(
48             "ACK settings frame have non-zero ($length) payload\n");
49 0         0 $con->error(FRAME_SIZE_ERROR);
50 0         0 return undef;
51             }
52 32         6423 return 0
53              
54             # received empty settings (default), accept it
55             }
56             elsif ( $length == 0 ) {
57 16         1599 $con->accept_settings();
58 16         3170 return 0;
59             }
60              
61 17 50       1604 if ( $length % 6 != 0 ) {
62 0         0 tracer->error("Settings frame payload is broken (lenght $length)\n");
63 0         0 $con->error(FRAME_SIZE_ERROR);
64 0         0 return undef;
65             }
66              
67 17         1664 my @settings = unpack( '(nN)*', substr( $$buf_ref, $buf_offset, $length ) );
68 17         1621 while ( my ( $key, $value ) = splice @settings, 0, 2 ) {
69 17 50 33     1622 if ( !defined $con->enc_setting($key) ) {
    50          
70 0         0 tracer->debug("\tUnknown setting $key\n");
71              
72             # ignore unknown setting
73 0         0 next;
74             }
75             elsif ( exists $s_check{$key}
76             && !$s_check{$key}{validator}->($value) )
77             {
78 0         0 tracer->debug( "\tInvalid value of setting "
79             . const_name( "settings", $key ) . ": "
80             . $value );
81 0         0 $con->error( $s_check{$key}{error} );
82 0         0 return undef;
83             }
84              
85             # Settings change may run some action
86 17 50       1621 $s_action{$key}->( $con, $value ) if exists $s_action{$key};
87              
88 17         1610 tracer->debug(
89             "\tSettings " . const_name( "settings", $key ) . " = $value\n" );
90 17         1608 $con->enc_setting( $key, $value );
91             }
92              
93 17         1619 $con->accept_settings();
94 17         3194 return $length;
95             }
96              
97             sub encode {
98 70     70 0 6318 my ( $con, $flags_ref, $stream, $data ) = @_;
99 70         6315 my $payload = '';
100 70         6504 for my $key ( sort keys %$data ) {
101 19         1626 tracer->debug( "\tSettings "
102             . const_name( "settings", $key )
103             . " = $data->{$key}\n" );
104 19         3226 $payload .= pack( 'nN', $key, $data->{$key} );
105             }
106 70         12748 return $payload;
107             }
108              
109             1;