1// Copyright 2019 The gRPC Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package http2interop 16 17import ( 18 "encoding/binary" 19 "fmt" 20 "io" 21) 22 23type GoAwayFrame struct { 24 Header FrameHeader 25 Reserved 26 StreamID 27 // TODO(carl-mastrangelo): make an enum out of this. 28 Code uint32 29 Data []byte 30} 31 32func (f *GoAwayFrame) GetHeader() *FrameHeader { 33 return &f.Header 34} 35 36func (f *GoAwayFrame) ParsePayload(r io.Reader) error { 37 raw := make([]byte, f.Header.Length) 38 if _, err := io.ReadFull(r, raw); err != nil { 39 return err 40 } 41 return f.UnmarshalPayload(raw) 42} 43 44func (f *GoAwayFrame) UnmarshalPayload(raw []byte) error { 45 if f.Header.Length != len(raw) { 46 return fmt.Errorf("Invalid Payload length %d != %d", f.Header.Length, len(raw)) 47 } 48 if f.Header.Length < 8 { 49 return fmt.Errorf("Invalid Payload length %d", f.Header.Length) 50 } 51 *f = GoAwayFrame{ 52 Reserved: Reserved(raw[0]>>7 == 1), 53 StreamID: StreamID(binary.BigEndian.Uint32(raw[0:4]) & 0x7fffffff), 54 Code: binary.BigEndian.Uint32(raw[4:8]), 55 Data: []byte(string(raw[8:])), 56 } 57 58 return nil 59} 60 61func (f *GoAwayFrame) MarshalPayload() ([]byte, error) { 62 raw := make([]byte, 8, 8+len(f.Data)) 63 binary.BigEndian.PutUint32(raw[:4], uint32(f.StreamID)) 64 binary.BigEndian.PutUint32(raw[4:8], f.Code) 65 raw = append(raw, f.Data...) 66 67 return raw, nil 68} 69 70func (f *GoAwayFrame) MarshalBinary() ([]byte, error) { 71 payload, err := f.MarshalPayload() 72 if err != nil { 73 return nil, err 74 } 75 76 f.Header.Length = len(payload) 77 f.Header.Type = GoAwayFrameType 78 header, err := f.Header.MarshalBinary() 79 if err != nil { 80 return nil, err 81 } 82 83 header = append(header, payload...) 84 85 return header, nil 86} 87