File Coverage

blib/lib/Protocol/HTTP2/Frame/Headers.pm
Criterion Covered Total %
statement 41 52 78.8
branch 11 18 61.1
condition 5 9 55.5
subroutine 6 6 100.0
pod 0 2 0.0
total 63 87 72.4


line stmt bran cond sub pod time code
1             package Protocol::HTTP2::Frame::Headers;
2 12     12   40 use strict;
  12         12  
  12         264  
3 12     12   37 use warnings;
  12         11  
  12         248  
4 12     12   37 use Protocol::HTTP2::Constants qw(:flags :errors :states :limits);
  12         12  
  12         2492  
5 12     12   51 use Protocol::HTTP2::Trace qw(tracer);
  12         12  
  12         4263  
6              
7             # 6.2 HEADERS
8             sub decode {
9 72     72 0 3261 my ( $con, $buf_ref, $buf_offset, $length ) = @_;
10 72         3235 my ( $pad, $offset, $weight, $exclusive, $stream_dep ) = ( 0, 0 );
11 72         3328 my $frame_ref = $con->decode_context->{frame};
12              
13             # Protocol errors
14 72 50       3326 if (
15             # HEADERS frames MUST be associated with a stream
16             $frame_ref->{stream} == 0
17             )
18             {
19 0         0 $con->error(PROTOCOL_ERROR);
20 0         0 return undef;
21             }
22              
23 72 50       3285 if ( $frame_ref->{flags} & PADDED ) {
24 0         0 $pad = unpack( 'C', substr( $$buf_ref, $buf_offset, 1 ) );
25 0         0 $offset += 1;
26             }
27              
28 72 100       3281 if ( $frame_ref->{flags} & PRIORITY_FLAG ) {
29 1         4 ( $stream_dep, $weight ) =
30             unpack( 'NC', substr( $$buf_ref, $buf_offset + $offset, 5 ) );
31 1         1 $exclusive = $stream_dep >> 31;
32 1         1 $stream_dep &= 0x7FFF_FFFF;
33 1         1 $weight++;
34              
35 1         3 $con->stream_weight( $frame_ref->{stream}, $weight );
36 1 50       3 unless (
37             $con->stream_reprio(
38             $frame_ref->{stream}, $exclusive, $stream_dep
39             )
40             )
41             {
42 0         0 tracer->error("Malformed HEADERS frame priority");
43 0         0 $con->error(PROTOCOL_ERROR);
44 0         0 return undef;
45             }
46              
47 1         3 $offset += 5;
48             }
49              
50             # Not enough space for header block
51 72         3215 my $hblock_size = $length - $offset - $pad;
52 72 50       3257 if ( $hblock_size < 0 ) {
53 0         0 $con->error(PROTOCOL_ERROR);
54 0         0 return undef;
55             }
56              
57             $con->stream_header_block( $frame_ref->{stream},
58 72         3473 substr( $$buf_ref, $buf_offset + $offset, $hblock_size ) );
59              
60             # Stream header block complete
61             $con->stream_headers_done( $frame_ref->{stream} )
62             or return undef
63 72 50 50     3428 if $frame_ref->{flags} & END_HEADERS;
64              
65 72         6531 return $length;
66             }
67              
68             sub encode {
69 75     75 0 3229 my ( $con, $flags_ref, $stream, $data_ref ) = @_;
70 75         3245 my $res = '';
71              
72 75 50       3287 if ( exists $data_ref->{padding} ) {
73 0         0 $$flags_ref |= PADDED;
74 0         0 $res .= pack 'C', $data_ref->{padding};
75             }
76              
77 75 100 66     3416 if ( exists $data_ref->{stream_dep} || exists $data_ref->{weight} ) {
78 1         2 $$flags_ref |= PRIORITY_FLAG;
79 1   50     6 my $weight = ( $data_ref->{weight} || DEFAULT_WEIGHT ) - 1;
80 1   50     6 my $stream_dep = $data_ref->{stream_dep} || 0;
81 1 50       3 $stream_dep |= ( 1 << 31 ) if $data_ref->{exclusive};
82 1         4 $res .= pack 'NC', $stream_dep, $weight;
83             }
84              
85 75         3204 return $res . ${ $data_ref->{hblock} };
  75         9699  
86             }
87              
88             1;