• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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