blob: 5a2b1ada6513c84df5134b7e87fc4122695f775b [file] [log] [blame]
Carl Mastrangelo4aca7962015-10-05 16:17:47 -07001package http2interop
2
3import (
4 "encoding/binary"
5 "fmt"
6 "io"
7)
8
9const (
10 SETTINGS_ACK = 1
11)
12
13type SettingsFrame struct {
14 Header FrameHeader
15 Params []SettingsParameter
16}
17
18type SettingsIdentifier uint16
19
20const (
21 SettingsHeaderTableSize SettingsIdentifier = 1
22 SettingsEnablePush SettingsIdentifier = 2
23 SettingsMaxConcurrentStreams SettingsIdentifier = 3
24 SettingsInitialWindowSize SettingsIdentifier = 4
25 SettingsMaxFrameSize SettingsIdentifier = 5
26 SettingsMaxHeaderListSize SettingsIdentifier = 6
27)
28
29func (si SettingsIdentifier) String() string {
30 switch si {
31 case SettingsHeaderTableSize:
32 return "HEADER_TABLE_SIZE"
33 case SettingsEnablePush:
34 return "ENABLE_PUSH"
35 case SettingsMaxConcurrentStreams:
36 return "MAX_CONCURRENT_STREAMS"
37 case SettingsInitialWindowSize:
38 return "INITIAL_WINDOW_SIZE"
39 case SettingsMaxFrameSize:
40 return "MAX_FRAME_SIZE"
41 case SettingsMaxHeaderListSize:
42 return "MAX_HEADER_LIST_SIZE"
43 default:
44 return fmt.Sprintf("UNKNOWN(%d)", uint16(si))
45 }
46}
47
48type SettingsParameter struct {
49 Identifier SettingsIdentifier
50 Value uint32
51}
52
53func (f *SettingsFrame) GetHeader() *FrameHeader {
54 return &f.Header
55}
56
57func (f *SettingsFrame) ParsePayload(r io.Reader) error {
58 raw := make([]byte, f.Header.Length)
59 if _, err := io.ReadFull(r, raw); err != nil {
60 return err
61 }
62 return f.UnmarshalPayload(raw)
63}
64
65func (f *SettingsFrame) UnmarshalPayload(raw []byte) error {
66 if f.Header.Length != len(raw) {
67 return fmt.Errorf("Invalid Payload length %d != %d", f.Header.Length, len(raw))
68 }
69
70 if f.Header.Length%6 != 0 {
71 return fmt.Errorf("Invalid Payload length %d", f.Header.Length)
72 }
73
74 f.Params = make([]SettingsParameter, 0, f.Header.Length/6)
75 for i := 0; i < len(raw); i += 6 {
76 f.Params = append(f.Params, SettingsParameter{
77 Identifier: SettingsIdentifier(binary.BigEndian.Uint16(raw[i : i+2])),
78 Value: binary.BigEndian.Uint32(raw[i+2 : i+6]),
79 })
80 }
81 return nil
82}
83
84func (f *SettingsFrame) MarshalPayload() ([]byte, error) {
85 raw := make([]byte, 0, len(f.Params)*6)
86 for i, p := range f.Params {
87 binary.BigEndian.PutUint16(raw[i*6:i*6+2], uint16(p.Identifier))
88 binary.BigEndian.PutUint32(raw[i*6+2:i*6+6], p.Value)
89 }
90 return raw, nil
91}
92
93func (f *SettingsFrame) MarshalBinary() ([]byte, error) {
94 payload, err := f.MarshalPayload()
95 if err != nil {
96 return nil, err
97 }
98
99 f.Header.Length = len(payload)
100 f.Header.Type = SettingsFrameType
101 header, err := f.Header.MarshalBinary()
102 if err != nil {
103 return nil, err
104 }
105
106 header = append(header, payload...)
107
108 return header, nil
109}