1*cc02d7e2SAndroid Build Coastguard Worker// Copyright 2019 The gRPC Authors 2*cc02d7e2SAndroid Build Coastguard Worker// 3*cc02d7e2SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*cc02d7e2SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*cc02d7e2SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*cc02d7e2SAndroid Build Coastguard Worker// 7*cc02d7e2SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*cc02d7e2SAndroid Build Coastguard Worker// 9*cc02d7e2SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*cc02d7e2SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*cc02d7e2SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*cc02d7e2SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*cc02d7e2SAndroid Build Coastguard Worker// limitations under the License. 14*cc02d7e2SAndroid Build Coastguard Worker 15*cc02d7e2SAndroid Build Coastguard Workerpackage http2interop 16*cc02d7e2SAndroid Build Coastguard Worker 17*cc02d7e2SAndroid Build Coastguard Workerimport ( 18*cc02d7e2SAndroid Build Coastguard Worker "encoding/binary" 19*cc02d7e2SAndroid Build Coastguard Worker "fmt" 20*cc02d7e2SAndroid Build Coastguard Worker "io" 21*cc02d7e2SAndroid Build Coastguard Worker) 22*cc02d7e2SAndroid Build Coastguard Worker 23*cc02d7e2SAndroid Build Coastguard Workerconst ( 24*cc02d7e2SAndroid Build Coastguard Worker SETTINGS_ACK = 1 25*cc02d7e2SAndroid Build Coastguard Worker) 26*cc02d7e2SAndroid Build Coastguard Worker 27*cc02d7e2SAndroid Build Coastguard Workertype SettingsFrame struct { 28*cc02d7e2SAndroid Build Coastguard Worker Header FrameHeader 29*cc02d7e2SAndroid Build Coastguard Worker Params []SettingsParameter 30*cc02d7e2SAndroid Build Coastguard Worker} 31*cc02d7e2SAndroid Build Coastguard Worker 32*cc02d7e2SAndroid Build Coastguard Workertype SettingsIdentifier uint16 33*cc02d7e2SAndroid Build Coastguard Worker 34*cc02d7e2SAndroid Build Coastguard Workerconst ( 35*cc02d7e2SAndroid Build Coastguard Worker SettingsHeaderTableSize SettingsIdentifier = 1 36*cc02d7e2SAndroid Build Coastguard Worker SettingsEnablePush SettingsIdentifier = 2 37*cc02d7e2SAndroid Build Coastguard Worker SettingsMaxConcurrentStreams SettingsIdentifier = 3 38*cc02d7e2SAndroid Build Coastguard Worker SettingsInitialWindowSize SettingsIdentifier = 4 39*cc02d7e2SAndroid Build Coastguard Worker SettingsMaxFrameSize SettingsIdentifier = 5 40*cc02d7e2SAndroid Build Coastguard Worker SettingsMaxHeaderListSize SettingsIdentifier = 6 41*cc02d7e2SAndroid Build Coastguard Worker) 42*cc02d7e2SAndroid Build Coastguard Worker 43*cc02d7e2SAndroid Build Coastguard Workerconst ( 44*cc02d7e2SAndroid Build Coastguard Worker SETTINGS_FLAG_ACK byte = 0x01 45*cc02d7e2SAndroid Build Coastguard Worker) 46*cc02d7e2SAndroid Build Coastguard Worker 47*cc02d7e2SAndroid Build Coastguard Workerfunc (si SettingsIdentifier) String() string { 48*cc02d7e2SAndroid Build Coastguard Worker switch si { 49*cc02d7e2SAndroid Build Coastguard Worker case SettingsHeaderTableSize: 50*cc02d7e2SAndroid Build Coastguard Worker return "SETTINGS_HEADER_TABLE_SIZE" 51*cc02d7e2SAndroid Build Coastguard Worker case SettingsEnablePush: 52*cc02d7e2SAndroid Build Coastguard Worker return "SETTINGS_ENABLE_PUSH" 53*cc02d7e2SAndroid Build Coastguard Worker case SettingsMaxConcurrentStreams: 54*cc02d7e2SAndroid Build Coastguard Worker return "SETTINGS_MAX_CONCURRENT_STREAMS" 55*cc02d7e2SAndroid Build Coastguard Worker case SettingsInitialWindowSize: 56*cc02d7e2SAndroid Build Coastguard Worker return "SETTINGS_INITIAL_WINDOW_SIZE" 57*cc02d7e2SAndroid Build Coastguard Worker case SettingsMaxFrameSize: 58*cc02d7e2SAndroid Build Coastguard Worker return "SETTINGS_MAX_FRAME_SIZE" 59*cc02d7e2SAndroid Build Coastguard Worker case SettingsMaxHeaderListSize: 60*cc02d7e2SAndroid Build Coastguard Worker return "SETTINGS_MAX_HEADER_LIST_SIZE" 61*cc02d7e2SAndroid Build Coastguard Worker default: 62*cc02d7e2SAndroid Build Coastguard Worker return fmt.Sprintf("SETTINGS_UNKNOWN(%d)", uint16(si)) 63*cc02d7e2SAndroid Build Coastguard Worker } 64*cc02d7e2SAndroid Build Coastguard Worker} 65*cc02d7e2SAndroid Build Coastguard Worker 66*cc02d7e2SAndroid Build Coastguard Workertype SettingsParameter struct { 67*cc02d7e2SAndroid Build Coastguard Worker Identifier SettingsIdentifier 68*cc02d7e2SAndroid Build Coastguard Worker Value uint32 69*cc02d7e2SAndroid Build Coastguard Worker} 70*cc02d7e2SAndroid Build Coastguard Worker 71*cc02d7e2SAndroid Build Coastguard Workerfunc (f *SettingsFrame) GetHeader() *FrameHeader { 72*cc02d7e2SAndroid Build Coastguard Worker return &f.Header 73*cc02d7e2SAndroid Build Coastguard Worker} 74*cc02d7e2SAndroid Build Coastguard Worker 75*cc02d7e2SAndroid Build Coastguard Workerfunc (f *SettingsFrame) ParsePayload(r io.Reader) error { 76*cc02d7e2SAndroid Build Coastguard Worker raw := make([]byte, f.Header.Length) 77*cc02d7e2SAndroid Build Coastguard Worker if _, err := io.ReadFull(r, raw); err != nil { 78*cc02d7e2SAndroid Build Coastguard Worker return err 79*cc02d7e2SAndroid Build Coastguard Worker } 80*cc02d7e2SAndroid Build Coastguard Worker return f.UnmarshalPayload(raw) 81*cc02d7e2SAndroid Build Coastguard Worker} 82*cc02d7e2SAndroid Build Coastguard Worker 83*cc02d7e2SAndroid Build Coastguard Workerfunc (f *SettingsFrame) UnmarshalPayload(raw []byte) error { 84*cc02d7e2SAndroid Build Coastguard Worker if f.Header.Length != len(raw) { 85*cc02d7e2SAndroid Build Coastguard Worker return fmt.Errorf("Invalid Payload length %d != %d", f.Header.Length, len(raw)) 86*cc02d7e2SAndroid Build Coastguard Worker } 87*cc02d7e2SAndroid Build Coastguard Worker 88*cc02d7e2SAndroid Build Coastguard Worker if f.Header.Length%6 != 0 { 89*cc02d7e2SAndroid Build Coastguard Worker return fmt.Errorf("Invalid Payload length %d", f.Header.Length) 90*cc02d7e2SAndroid Build Coastguard Worker } 91*cc02d7e2SAndroid Build Coastguard Worker 92*cc02d7e2SAndroid Build Coastguard Worker f.Params = make([]SettingsParameter, 0, f.Header.Length/6) 93*cc02d7e2SAndroid Build Coastguard Worker for i := 0; i < len(raw); i += 6 { 94*cc02d7e2SAndroid Build Coastguard Worker f.Params = append(f.Params, SettingsParameter{ 95*cc02d7e2SAndroid Build Coastguard Worker Identifier: SettingsIdentifier(binary.BigEndian.Uint16(raw[i : i+2])), 96*cc02d7e2SAndroid Build Coastguard Worker Value: binary.BigEndian.Uint32(raw[i+2 : i+6]), 97*cc02d7e2SAndroid Build Coastguard Worker }) 98*cc02d7e2SAndroid Build Coastguard Worker } 99*cc02d7e2SAndroid Build Coastguard Worker return nil 100*cc02d7e2SAndroid Build Coastguard Worker} 101*cc02d7e2SAndroid Build Coastguard Worker 102*cc02d7e2SAndroid Build Coastguard Workerfunc (f *SettingsFrame) MarshalPayload() ([]byte, error) { 103*cc02d7e2SAndroid Build Coastguard Worker raw := make([]byte, len(f.Params)*6) 104*cc02d7e2SAndroid Build Coastguard Worker for i, p := range f.Params { 105*cc02d7e2SAndroid Build Coastguard Worker binary.BigEndian.PutUint16(raw[i*6:i*6+2], uint16(p.Identifier)) 106*cc02d7e2SAndroid Build Coastguard Worker binary.BigEndian.PutUint32(raw[i*6+2:i*6+6], p.Value) 107*cc02d7e2SAndroid Build Coastguard Worker } 108*cc02d7e2SAndroid Build Coastguard Worker return raw, nil 109*cc02d7e2SAndroid Build Coastguard Worker} 110*cc02d7e2SAndroid Build Coastguard Worker 111*cc02d7e2SAndroid Build Coastguard Workerfunc (f *SettingsFrame) MarshalBinary() ([]byte, error) { 112*cc02d7e2SAndroid Build Coastguard Worker payload, err := f.MarshalPayload() 113*cc02d7e2SAndroid Build Coastguard Worker if err != nil { 114*cc02d7e2SAndroid Build Coastguard Worker return nil, err 115*cc02d7e2SAndroid Build Coastguard Worker } 116*cc02d7e2SAndroid Build Coastguard Worker 117*cc02d7e2SAndroid Build Coastguard Worker f.Header.Length = len(payload) 118*cc02d7e2SAndroid Build Coastguard Worker f.Header.Type = SettingsFrameType 119*cc02d7e2SAndroid Build Coastguard Worker header, err := f.Header.MarshalBinary() 120*cc02d7e2SAndroid Build Coastguard Worker if err != nil { 121*cc02d7e2SAndroid Build Coastguard Worker return nil, err 122*cc02d7e2SAndroid Build Coastguard Worker } 123*cc02d7e2SAndroid Build Coastguard Worker header = append(header, payload...) 124*cc02d7e2SAndroid Build Coastguard Worker 125*cc02d7e2SAndroid Build Coastguard Worker return header, nil 126*cc02d7e2SAndroid Build Coastguard Worker} 127