crypto_stream.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package quic
  2. import (
  3. "fmt"
  4. "io"
  5. "github.com/Psiphon-Labs/quic-go/internal/protocol"
  6. "github.com/Psiphon-Labs/quic-go/internal/qerr"
  7. "github.com/Psiphon-Labs/quic-go/internal/utils"
  8. "github.com/Psiphon-Labs/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{queue: newFrameSorter()}
  30. }
  31. func (s *cryptoStreamImpl) HandleCryptoFrame(f *wire.CryptoFrame) error {
  32. highestOffset := f.Offset + protocol.ByteCount(len(f.Data))
  33. if maxOffset := highestOffset; maxOffset > protocol.MaxCryptoStreamOffset {
  34. return &qerr.TransportError{
  35. ErrorCode: qerr.CryptoBufferExceeded,
  36. ErrorMessage: fmt.Sprintf("received invalid offset %d on crypto stream, maximum allowed %d", maxOffset, protocol.MaxCryptoStreamOffset),
  37. }
  38. }
  39. if s.finished {
  40. if highestOffset > s.highestOffset {
  41. // reject crypto data received after this stream was already finished
  42. return &qerr.TransportError{
  43. ErrorCode: qerr.ProtocolViolation,
  44. ErrorMessage: "received crypto data after change of encryption level",
  45. }
  46. }
  47. // ignore data with a smaller offset than the highest received
  48. // could e.g. be a retransmission
  49. return nil
  50. }
  51. s.highestOffset = utils.MaxByteCount(s.highestOffset, highestOffset)
  52. if err := s.queue.Push(f.Data, f.Offset, nil); err != nil {
  53. return err
  54. }
  55. for {
  56. _, data, _ := s.queue.Pop()
  57. if data == nil {
  58. return nil
  59. }
  60. s.msgBuf = append(s.msgBuf, data...)
  61. }
  62. }
  63. // GetCryptoData retrieves data that was received in CRYPTO frames
  64. func (s *cryptoStreamImpl) GetCryptoData() []byte {
  65. if len(s.msgBuf) < 4 {
  66. return nil
  67. }
  68. msgLen := 4 + int(s.msgBuf[1])<<16 + int(s.msgBuf[2])<<8 + int(s.msgBuf[3])
  69. if len(s.msgBuf) < msgLen {
  70. return nil
  71. }
  72. msg := make([]byte, msgLen)
  73. copy(msg, s.msgBuf[:msgLen])
  74. s.msgBuf = s.msgBuf[msgLen:]
  75. return msg
  76. }
  77. func (s *cryptoStreamImpl) Finish() error {
  78. if s.queue.HasMoreData() {
  79. return &qerr.TransportError{
  80. ErrorCode: qerr.ProtocolViolation,
  81. ErrorMessage: "encryption level changed, but crypto stream has more data to read",
  82. }
  83. }
  84. s.finished = true
  85. return nil
  86. }
  87. // Writes writes data that should be sent out in CRYPTO frames
  88. func (s *cryptoStreamImpl) Write(p []byte) (int, error) {
  89. s.writeBuf = append(s.writeBuf, p...)
  90. return len(p), nil
  91. }
  92. func (s *cryptoStreamImpl) HasData() bool {
  93. return len(s.writeBuf) > 0
  94. }
  95. func (s *cryptoStreamImpl) PopCryptoFrame(maxLen protocol.ByteCount) *wire.CryptoFrame {
  96. f := &wire.CryptoFrame{Offset: s.writeOffset}
  97. n := utils.MinByteCount(f.MaxDataLen(maxLen), protocol.ByteCount(len(s.writeBuf)))
  98. f.Data = s.writeBuf[:n]
  99. s.writeBuf = s.writeBuf[n:]
  100. s.writeOffset += n
  101. return f
  102. }