@@ -18,6 +18,7 @@ import (
18
18
"bufio"
19
19
"bytes"
20
20
"compress/gzip"
21
+ "errors"
21
22
"fmt"
22
23
"io"
23
24
"log"
@@ -26,6 +27,22 @@ import (
26
27
"golang.org/x/net/http2/hpack"
27
28
)
28
29
30
+ const frameHeaderLen = 9
31
+
32
+ // http2.FrameType
33
+ // const (
34
+ // FrameData FrameType = 0x0
35
+ // FrameHeaders FrameType = 0x1
36
+ // FramePriority FrameType = 0x2
37
+ // FrameRSTStream FrameType = 0x3
38
+ // FrameSettings FrameType = 0x4
39
+ // FramePushPromise FrameType = 0x5
40
+ // FramePing FrameType = 0x6
41
+ // FrameGoAway FrameType = 0x7
42
+ // FrameWindowUpdate FrameType = 0x8
43
+ // FrameContinuation FrameType = 0x9
44
+ // )
45
+
29
46
type HTTP2Response struct {
30
47
framer * http2.Framer
31
48
packerType PacketType
@@ -36,15 +53,37 @@ type HTTP2Response struct {
36
53
}
37
54
38
55
func (h2r * HTTP2Response ) detect (payload []byte ) error {
39
- rd := bytes .NewReader (payload )
40
- buf := bufio .NewReader (rd )
41
- framer := http2 .NewFramer (nil , buf )
42
- framer .ReadMetaHeaders = hpack .NewDecoder (0 , nil )
43
- _ , err := framer .ReadFrame ()
44
- if err != nil {
45
- return err
56
+ payloadLen := len (payload )
57
+ if payloadLen < frameHeaderLen {
58
+ return errors .New ("Payload less than http2 frame Header" )
59
+ }
60
+ // https://httpwg.org/specs/rfc7540.html#FrameHeader
61
+ // All frames begin with a fixed 9-octet header followed by a variable-length payload.
62
+ //
63
+ // +-----------------------------------------------+
64
+ // | Length (24) |
65
+ // +---------------+---------------+---------------+
66
+ // | Type (8) | Flags (8) |
67
+ // +-+-------------+---------------+-------------------------------+
68
+ // |R| Stream Identifier (31) |
69
+ // +=+=============================================================+
70
+ // | Frame Payload (0...) ...
71
+ // +---------------------------------------------------------------+
72
+ data := payload [0 :frameHeaderLen ]
73
+ // currentFrameLen := uint32(data[0])<<16 | uint32(data[1])<<8 | uint32(data[2])
74
+ currentFrameType := http2 .FrameType (data [3 ])
75
+ // Frame type in http2.FrameType
76
+ if currentFrameType > http2 .FrameContinuation {
77
+ return errors .New ("Invalid frame type" )
78
+ }
79
+ // R: A reserved 1-bit field.
80
+ // The semantics of this bit are undefined, and the bit MUST remain unset (0x0) when
81
+ // sending and MUST be ignored when receiving.
82
+ reservedBit := uint32 (data [5 ]) >> 7
83
+ if reservedBit == 0 {
84
+ return nil
46
85
}
47
- return nil
86
+ return errors . New ( "Invalid reserved bit in frame header" )
48
87
}
49
88
50
89
func (h2r * HTTP2Response ) Init () {
0 commit comments