frame.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. package http2
  2. import (
  3. "encoding/binary"
  4. "io"
  5. "io/ioutil"
  6. "log"
  7. "sync"
  8. )
  9. const frameHeaderLen = 8
  10. type FrameType uint8
  11. // Defined in http://http2.github.io/http2-spec/#rfc.section.11.2
  12. const (
  13. FrameData FrameType = 0x0
  14. FrameHeaders FrameType = 0x1
  15. FramePriority FrameType = 0x2
  16. FrameRSTStream FrameType = 0x3
  17. FrameSettings FrameType = 0x4
  18. FramePushPromise FrameType = 0x5
  19. FramePing FrameType = 0x6
  20. FrameGoAway FrameType = 0x7
  21. FrameWindowUpdate FrameType = 0x8
  22. FrameContinuation FrameType = 0x9
  23. FlagSettingsAck Flags = 0x1
  24. )
  25. type SettingID uint16
  26. const (
  27. SettingHeaderTableSize SettingID = 0x1
  28. SettingEnablePush SettingID = 0x2
  29. SettingMaxConcurrentStreams SettingID = 0x3
  30. SettingInitialWindowSize SettingID = 0x4
  31. )
  32. func knownSetting(id SettingID) bool {
  33. // TODO: permit registration of custom settings values?
  34. // Per server type?
  35. return id >= 1 && id <= 4
  36. }
  37. type frameParser func(FrameHeader, io.Reader) (Frame, error)
  38. var FrameParsers = map[FrameType]frameParser{
  39. FrameSettings: parseFrameSettings,
  40. }
  41. func typeFrameParser(t FrameType) frameParser {
  42. if f, ok := FrameParsers[t]; ok {
  43. return f
  44. }
  45. return parseUnknownFrame
  46. }
  47. type Flags uint8
  48. func (f Flags) Has(v Flags) bool {
  49. return (f & v) == v
  50. }
  51. // A FrameHeader is the 8 byte header of all HTTP/2 frames.
  52. //
  53. // See http://http2.github.io/http2-spec/#FrameHeader
  54. type FrameHeader struct {
  55. Type FrameType
  56. Flags Flags
  57. Length uint16
  58. StreamID uint32
  59. }
  60. func (h FrameHeader) Header() FrameHeader { return h }
  61. // frame header bytes
  62. var fhBytes = sync.Pool{
  63. New: func() interface{} {
  64. buf := make([]byte, frameHeaderLen)
  65. return &buf
  66. },
  67. }
  68. func ReadFrameHeader(r io.Reader) (FrameHeader, error) {
  69. bufp := fhBytes.Get().(*[]byte)
  70. defer fhBytes.Put(bufp)
  71. buf := *bufp
  72. _, err := io.ReadFull(r, buf)
  73. if err != nil {
  74. return FrameHeader{}, err
  75. }
  76. return FrameHeader{
  77. Length: (uint16(buf[0])<<8 + uint16(buf[1])) & (1<<14 - 1),
  78. Flags: Flags(buf[3]),
  79. Type: FrameType(buf[2]),
  80. StreamID: binary.BigEndian.Uint32(buf[4:]) & (1<<31 - 1),
  81. }, nil
  82. }
  83. type Frame interface {
  84. Header() FrameHeader
  85. }
  86. type SettingsFrame struct {
  87. FrameHeader
  88. Settings map[SettingID]uint32
  89. }
  90. func parseFrameSettings(fh FrameHeader, r io.Reader) (Frame, error) {
  91. if fh.Flags.Has(FlagSettingsAck) && fh.Length > 0 {
  92. // When this (ACK 0x1) bit is set, the payload of the
  93. // SETTINGS frame MUST be empty. Receipt of a
  94. // SETTINGS frame with the ACK flag set and a length
  95. // field value other than 0 MUST be treated as a
  96. // connection error (Section 5.4.1) of type
  97. // FRAME_SIZE_ERROR.
  98. return nil, ConnectionError(ErrCodeFrameSize)
  99. }
  100. if fh.StreamID != 0 {
  101. // SETTINGS frames always apply to a connection,
  102. // never a single stream. The stream identifier for a
  103. // SETTINGS frame MUST be zero (0x0). If an endpoint
  104. // receives a SETTINGS frame whose stream identifier
  105. // field is anything other than 0x0, the endpoint MUST
  106. // respond with a connection error (Section 5.4.1) of
  107. // type PROTOCOL_ERROR.
  108. log.Printf("Bogus StreamID in settings: %+v", fh)
  109. return nil, ConnectionError(ErrCodeProtocol)
  110. }
  111. if fh.Length%6 != 0 {
  112. // Expecting even number of 6 byte settings.
  113. return nil, ConnectionError(ErrCodeFrameSize)
  114. }
  115. s := make(map[SettingID]uint32)
  116. nSettings := int(fh.Length / 6)
  117. var buf [4]byte
  118. for i := 0; i < nSettings; i++ {
  119. if _, err := io.ReadFull(r, buf[:2]); err != nil {
  120. return nil, err
  121. }
  122. settingID := SettingID(binary.BigEndian.Uint16(buf[:2]))
  123. if _, err := io.ReadFull(r, buf[:4]); err != nil {
  124. return nil, err
  125. }
  126. value := binary.BigEndian.Uint32(buf[:4])
  127. if knownSetting(settingID) {
  128. s[settingID] = value
  129. }
  130. }
  131. return &SettingsFrame{
  132. FrameHeader: fh,
  133. Settings: s,
  134. }, nil
  135. }
  136. type UnknownFrame struct {
  137. FrameHeader
  138. }
  139. func parseUnknownFrame(fh FrameHeader, r io.Reader) (Frame, error) {
  140. _, err := io.CopyN(ioutil.Discard, r, int64(fh.Length))
  141. return UnknownFrame{fh}, err
  142. }