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