crypto_stream.go 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package quic
  2. import (
  3. "fmt"
  4. "github.com/Psiphon-Labs/quic-go/internal/protocol"
  5. "github.com/Psiphon-Labs/quic-go/internal/qerr"
  6. "github.com/Psiphon-Labs/quic-go/internal/wire"
  7. )
  8. type cryptoStream struct {
  9. queue frameSorter
  10. highestOffset protocol.ByteCount
  11. finished bool
  12. writeOffset protocol.ByteCount
  13. writeBuf []byte
  14. }
  15. func newCryptoStream() *cryptoStream {
  16. return &cryptoStream{queue: *newFrameSorter()}
  17. }
  18. func (s *cryptoStream) HandleCryptoFrame(f *wire.CryptoFrame) error {
  19. highestOffset := f.Offset + protocol.ByteCount(len(f.Data))
  20. if maxOffset := highestOffset; maxOffset > protocol.MaxCryptoStreamOffset {
  21. return &qerr.TransportError{
  22. ErrorCode: qerr.CryptoBufferExceeded,
  23. ErrorMessage: fmt.Sprintf("received invalid offset %d on crypto stream, maximum allowed %d", maxOffset, protocol.MaxCryptoStreamOffset),
  24. }
  25. }
  26. if s.finished {
  27. if highestOffset > s.highestOffset {
  28. // reject crypto data received after this stream was already finished
  29. return &qerr.TransportError{
  30. ErrorCode: qerr.ProtocolViolation,
  31. ErrorMessage: "received crypto data after change of encryption level",
  32. }
  33. }
  34. // ignore data with a smaller offset than the highest received
  35. // could e.g. be a retransmission
  36. return nil
  37. }
  38. s.highestOffset = max(s.highestOffset, highestOffset)
  39. return s.queue.Push(f.Data, f.Offset, nil)
  40. }
  41. // GetCryptoData retrieves data that was received in CRYPTO frames
  42. func (s *cryptoStream) GetCryptoData() []byte {
  43. _, data, _ := s.queue.Pop()
  44. return data
  45. }
  46. func (s *cryptoStream) Finish() error {
  47. if s.queue.HasMoreData() {
  48. return &qerr.TransportError{
  49. ErrorCode: qerr.ProtocolViolation,
  50. ErrorMessage: "encryption level changed, but crypto stream has more data to read",
  51. }
  52. }
  53. s.finished = true
  54. return nil
  55. }
  56. // Writes writes data that should be sent out in CRYPTO frames
  57. func (s *cryptoStream) Write(p []byte) (int, error) {
  58. s.writeBuf = append(s.writeBuf, p...)
  59. return len(p), nil
  60. }
  61. func (s *cryptoStream) HasData() bool {
  62. return len(s.writeBuf) > 0
  63. }
  64. func (s *cryptoStream) PopCryptoFrame(maxLen protocol.ByteCount) *wire.CryptoFrame {
  65. f := &wire.CryptoFrame{Offset: s.writeOffset}
  66. n := min(f.MaxDataLen(maxLen), protocol.ByteCount(len(s.writeBuf)))
  67. f.Data = s.writeBuf[:n]
  68. s.writeBuf = s.writeBuf[n:]
  69. s.writeOffset += n
  70. return f
  71. }