File: Headers.pm

package info (click to toggle)
libprotocol-http2-perl 1.11-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 448 kB
  • sloc: perl: 3,370; makefile: 7
file content (88 lines) | stat: -rw-r--r-- 2,453 bytes parent folder | download | duplicates (4)
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
77
78
79
80
81
82
83
84
85
86
87
88
package Protocol::HTTP2::Frame::Headers;
use strict;
use warnings;
use Protocol::HTTP2::Constants qw(:flags :errors :states :limits);
use Protocol::HTTP2::Trace qw(tracer);

# 6.2 HEADERS
sub decode {
    my ( $con, $buf_ref, $buf_offset, $length ) = @_;
    my ( $pad, $offset, $weight, $exclusive, $stream_dep ) = ( 0, 0 );
    my $frame_ref = $con->decode_context->{frame};

    # Protocol errors
    if (
        # HEADERS frames MUST be associated with a stream
        $frame_ref->{stream} == 0
      )
    {
        $con->error(PROTOCOL_ERROR);
        return undef;
    }

    if ( $frame_ref->{flags} & PADDED ) {
        $pad = unpack( 'C', substr( $$buf_ref, $buf_offset, 1 ) );
        $offset += 1;
    }

    if ( $frame_ref->{flags} & PRIORITY_FLAG ) {
        ( $stream_dep, $weight ) =
          unpack( 'NC', substr( $$buf_ref, $buf_offset + $offset, 5 ) );
        $exclusive = $stream_dep >> 31;
        $stream_dep &= 0x7FFF_FFFF;
        $weight++;

        $con->stream_weight( $frame_ref->{stream}, $weight );
        unless (
            $con->stream_reprio(
                $frame_ref->{stream}, $exclusive, $stream_dep
            )
          )
        {
            tracer->error("Malformed HEADERS frame priority");
            $con->error(PROTOCOL_ERROR);
            return undef;
        }

        $offset += 5;
    }

    # Not enough space for header block
    my $hblock_size = $length - $offset - $pad;
    if ( $hblock_size < 0 ) {
        $con->error(PROTOCOL_ERROR);
        return undef;
    }

    $con->stream_header_block( $frame_ref->{stream},
        substr( $$buf_ref, $buf_offset + $offset, $hblock_size ) );

    # Stream header block complete
    $con->stream_headers_done( $frame_ref->{stream} )
      or return undef
      if $frame_ref->{flags} & END_HEADERS;

    return $length;
}

sub encode {
    my ( $con, $flags_ref, $stream, $data_ref ) = @_;
    my $res = '';

    if ( exists $data_ref->{padding} ) {
        $$flags_ref |= PADDED;
        $res .= pack 'C', $data_ref->{padding};
    }

    if ( exists $data_ref->{stream_dep} || exists $data_ref->{weight} ) {
        $$flags_ref |= PRIORITY_FLAG;
        my $weight = ( $data_ref->{weight} || DEFAULT_WEIGHT ) - 1;
        my $stream_dep = $data_ref->{stream_dep} || 0;
        $stream_dep |= ( 1 << 31 ) if $data_ref->{exclusive};
        $res .= pack 'NC', $stream_dep, $weight;
    }

    return $res . ${ $data_ref->{hblock} };
}

1;