1package http2interop 2 3import ( 4 "encoding/binary" 5 "fmt" 6 "io" 7) 8 9type GoAwayFrame struct { 10 Header FrameHeader 11 Reserved 12 StreamID 13 // TODO(carl-mastrangelo): make an enum out of this. 14 Code uint32 15 Data []byte 16} 17 18func (f *GoAwayFrame) GetHeader() *FrameHeader { 19 return &f.Header 20} 21 22func (f *GoAwayFrame) ParsePayload(r io.Reader) error { 23 raw := make([]byte, f.Header.Length) 24 if _, err := io.ReadFull(r, raw); err != nil { 25 return err 26 } 27 return f.UnmarshalPayload(raw) 28} 29 30func (f *GoAwayFrame) UnmarshalPayload(raw []byte) error { 31 if f.Header.Length != len(raw) { 32 return fmt.Errorf("Invalid Payload length %d != %d", f.Header.Length, len(raw)) 33 } 34 if f.Header.Length < 8 { 35 return fmt.Errorf("Invalid Payload length %d", f.Header.Length) 36 } 37 *f = GoAwayFrame{ 38 Reserved: Reserved(raw[0]>>7 == 1), 39 StreamID: StreamID(binary.BigEndian.Uint32(raw[0:4]) & 0x7fffffff), 40 Code: binary.BigEndian.Uint32(raw[4:8]), 41 Data: []byte(string(raw[8:])), 42 } 43 44 return nil 45} 46 47func (f *GoAwayFrame) MarshalPayload() ([]byte, error) { 48 raw := make([]byte, 8, 8+len(f.Data)) 49 binary.BigEndian.PutUint32(raw[:4], uint32(f.StreamID)) 50 binary.BigEndian.PutUint32(raw[4:8], f.Code) 51 raw = append(raw, f.Data...) 52 53 return raw, nil 54} 55 56func (f *GoAwayFrame) MarshalBinary() ([]byte, error) { 57 payload, err := f.MarshalPayload() 58 if err != nil { 59 return nil, err 60 } 61 62 f.Header.Length = len(payload) 63 f.Header.Type = GoAwayFrameType 64 header, err := f.Header.MarshalBinary() 65 if err != nil { 66 return nil, err 67 } 68 69 header = append(header, payload...) 70 71 return header, nil 72} 73