frames.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. package http3
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "github.com/Psiphon-Labs/quic-go/internal/protocol"
  8. "github.com/Psiphon-Labs/quic-go/quicvarint"
  9. )
  10. // FrameType is the frame type of a HTTP/3 frame
  11. type FrameType uint64
  12. type unknownFrameHandlerFunc func(FrameType, error) (processed bool, err error)
  13. type frame interface{}
  14. var errHijacked = errors.New("hijacked")
  15. func parseNextFrame(r io.Reader, unknownFrameHandler unknownFrameHandlerFunc) (frame, error) {
  16. qr := quicvarint.NewReader(r)
  17. for {
  18. t, err := quicvarint.Read(qr)
  19. if err != nil {
  20. if unknownFrameHandler != nil {
  21. hijacked, err := unknownFrameHandler(0, err)
  22. if err != nil {
  23. return nil, err
  24. }
  25. if hijacked {
  26. return nil, errHijacked
  27. }
  28. }
  29. return nil, err
  30. }
  31. // Call the unknownFrameHandler for frames not defined in the HTTP/3 spec
  32. if t > 0xd && unknownFrameHandler != nil {
  33. hijacked, err := unknownFrameHandler(FrameType(t), nil)
  34. if err != nil {
  35. return nil, err
  36. }
  37. if hijacked {
  38. return nil, errHijacked
  39. }
  40. // If the unknownFrameHandler didn't process the frame, it is our responsibility to skip it.
  41. }
  42. l, err := quicvarint.Read(qr)
  43. if err != nil {
  44. return nil, err
  45. }
  46. switch t {
  47. case 0x0:
  48. return &dataFrame{Length: l}, nil
  49. case 0x1:
  50. return &headersFrame{Length: l}, nil
  51. case 0x4:
  52. return parseSettingsFrame(r, l)
  53. case 0x3: // CANCEL_PUSH
  54. case 0x5: // PUSH_PROMISE
  55. case 0x7: // GOAWAY
  56. case 0xd: // MAX_PUSH_ID
  57. }
  58. // skip over unknown frames
  59. if _, err := io.CopyN(io.Discard, qr, int64(l)); err != nil {
  60. return nil, err
  61. }
  62. }
  63. }
  64. type dataFrame struct {
  65. Length uint64
  66. }
  67. func (f *dataFrame) Append(b []byte) []byte {
  68. b = quicvarint.Append(b, 0x0)
  69. return quicvarint.Append(b, f.Length)
  70. }
  71. type headersFrame struct {
  72. Length uint64
  73. }
  74. func (f *headersFrame) Append(b []byte) []byte {
  75. b = quicvarint.Append(b, 0x1)
  76. return quicvarint.Append(b, f.Length)
  77. }
  78. const settingDatagram = 0x33
  79. type settingsFrame struct {
  80. Datagram bool
  81. Other map[uint64]uint64 // all settings that we don't explicitly recognize
  82. }
  83. func parseSettingsFrame(r io.Reader, l uint64) (*settingsFrame, error) {
  84. if l > 8*(1<<10) {
  85. return nil, fmt.Errorf("unexpected size for SETTINGS frame: %d", l)
  86. }
  87. buf := make([]byte, l)
  88. if _, err := io.ReadFull(r, buf); err != nil {
  89. if err == io.ErrUnexpectedEOF {
  90. return nil, io.EOF
  91. }
  92. return nil, err
  93. }
  94. frame := &settingsFrame{}
  95. b := bytes.NewReader(buf)
  96. var readDatagram bool
  97. for b.Len() > 0 {
  98. id, err := quicvarint.Read(b)
  99. if err != nil { // should not happen. We allocated the whole frame already.
  100. return nil, err
  101. }
  102. val, err := quicvarint.Read(b)
  103. if err != nil { // should not happen. We allocated the whole frame already.
  104. return nil, err
  105. }
  106. switch id {
  107. case settingDatagram:
  108. if readDatagram {
  109. return nil, fmt.Errorf("duplicate setting: %d", id)
  110. }
  111. readDatagram = true
  112. if val != 0 && val != 1 {
  113. return nil, fmt.Errorf("invalid value for H3_DATAGRAM: %d", val)
  114. }
  115. frame.Datagram = val == 1
  116. default:
  117. if _, ok := frame.Other[id]; ok {
  118. return nil, fmt.Errorf("duplicate setting: %d", id)
  119. }
  120. if frame.Other == nil {
  121. frame.Other = make(map[uint64]uint64)
  122. }
  123. frame.Other[id] = val
  124. }
  125. }
  126. return frame, nil
  127. }
  128. func (f *settingsFrame) Append(b []byte) []byte {
  129. b = quicvarint.Append(b, 0x4)
  130. var l protocol.ByteCount
  131. for id, val := range f.Other {
  132. l += quicvarint.Len(id) + quicvarint.Len(val)
  133. }
  134. if f.Datagram {
  135. l += quicvarint.Len(settingDatagram) + quicvarint.Len(1)
  136. }
  137. b = quicvarint.Append(b, uint64(l))
  138. if f.Datagram {
  139. b = quicvarint.Append(b, settingDatagram)
  140. b = quicvarint.Append(b, 1)
  141. }
  142. for id, val := range f.Other {
  143. b = quicvarint.Append(b, id)
  144. b = quicvarint.Append(b, val)
  145. }
  146. return b
  147. }