crypto_stream.go 2.7 KB

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