crypto_stream.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package quic
  2. import (
  3. "errors"
  4. "fmt"
  5. "io"
  6. "github.com/lucas-clemente/quic-go/internal/protocol"
  7. "github.com/lucas-clemente/quic-go/internal/utils"
  8. "github.com/lucas-clemente/quic-go/internal/wire"
  9. )
  10. type cryptoStream interface {
  11. // for receiving data
  12. HandleCryptoFrame(*wire.CryptoFrame) error
  13. GetCryptoData() []byte
  14. Finish() error
  15. // for sending data
  16. io.Writer
  17. HasData() bool
  18. PopCryptoFrame(protocol.ByteCount) *wire.CryptoFrame
  19. }
  20. type cryptoStreamImpl struct {
  21. queue *frameSorter
  22. msgBuf []byte
  23. highestOffset protocol.ByteCount
  24. finished bool
  25. writeOffset protocol.ByteCount
  26. writeBuf []byte
  27. }
  28. func newCryptoStream() cryptoStream {
  29. return &cryptoStreamImpl{
  30. queue: newFrameSorter(),
  31. }
  32. }
  33. func (s *cryptoStreamImpl) HandleCryptoFrame(f *wire.CryptoFrame) error {
  34. highestOffset := f.Offset + protocol.ByteCount(len(f.Data))
  35. if maxOffset := highestOffset; maxOffset > protocol.MaxCryptoStreamOffset {
  36. return fmt.Errorf("received invalid offset %d on crypto stream, maximum allowed %d", maxOffset, protocol.MaxCryptoStreamOffset)
  37. }
  38. if s.finished {
  39. if highestOffset > s.highestOffset {
  40. // reject crypto data received after this stream was already finished
  41. return errors.New("received crypto data after change of encryption level")
  42. }
  43. // ignore data with a smaller offset than the highest received
  44. // could e.g. be a retransmission
  45. return nil
  46. }
  47. s.highestOffset = utils.MaxByteCount(s.highestOffset, highestOffset)
  48. if err := s.queue.Push(f.Data, f.Offset, false); err != nil {
  49. return err
  50. }
  51. for {
  52. data, _ := s.queue.Pop()
  53. if data == nil {
  54. return nil
  55. }
  56. s.msgBuf = append(s.msgBuf, data...)
  57. }
  58. }
  59. // GetCryptoData retrieves data that was received in CRYPTO frames
  60. func (s *cryptoStreamImpl) GetCryptoData() []byte {
  61. if len(s.msgBuf) < 4 {
  62. return nil
  63. }
  64. msgLen := 4 + int(s.msgBuf[1])<<16 + int(s.msgBuf[2])<<8 + int(s.msgBuf[3])
  65. if len(s.msgBuf) < msgLen {
  66. return nil
  67. }
  68. msg := make([]byte, msgLen)
  69. copy(msg, s.msgBuf[:msgLen])
  70. s.msgBuf = s.msgBuf[msgLen:]
  71. return msg
  72. }
  73. func (s *cryptoStreamImpl) Finish() error {
  74. if s.queue.HasMoreData() {
  75. return errors.New("encryption level changed, but crypto stream has more data to read")
  76. }
  77. s.finished = true
  78. return nil
  79. }
  80. // Writes writes data that should be sent out in CRYPTO frames
  81. func (s *cryptoStreamImpl) Write(p []byte) (int, error) {
  82. s.writeBuf = append(s.writeBuf, p...)
  83. return len(p), nil
  84. }
  85. func (s *cryptoStreamImpl) HasData() bool {
  86. return len(s.writeBuf) > 0
  87. }
  88. func (s *cryptoStreamImpl) PopCryptoFrame(maxLen protocol.ByteCount) *wire.CryptoFrame {
  89. f := &wire.CryptoFrame{Offset: s.writeOffset}
  90. n := utils.MinByteCount(f.MaxDataLen(maxLen), protocol.ByteCount(len(s.writeBuf)))
  91. f.Data = s.writeBuf[:n]
  92. s.writeBuf = s.writeBuf[n:]
  93. s.writeOffset += n
  94. return f
  95. }