| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- package quic
- import (
- "errors"
- "fmt"
- "io"
- "github.com/lucas-clemente/quic-go/internal/protocol"
- "github.com/lucas-clemente/quic-go/internal/utils"
- "github.com/lucas-clemente/quic-go/internal/wire"
- )
- type cryptoStream interface {
- // for receiving data
- HandleCryptoFrame(*wire.CryptoFrame) error
- GetCryptoData() []byte
- Finish() error
- // for sending data
- io.Writer
- HasData() bool
- PopCryptoFrame(protocol.ByteCount) *wire.CryptoFrame
- }
- type cryptoStreamImpl struct {
- queue *frameSorter
- msgBuf []byte
- highestOffset protocol.ByteCount
- finished bool
- writeOffset protocol.ByteCount
- writeBuf []byte
- }
- func newCryptoStream() cryptoStream {
- return &cryptoStreamImpl{
- queue: newFrameSorter(),
- }
- }
- func (s *cryptoStreamImpl) HandleCryptoFrame(f *wire.CryptoFrame) error {
- highestOffset := f.Offset + protocol.ByteCount(len(f.Data))
- if maxOffset := highestOffset; maxOffset > protocol.MaxCryptoStreamOffset {
- return fmt.Errorf("received invalid offset %d on crypto stream, maximum allowed %d", maxOffset, protocol.MaxCryptoStreamOffset)
- }
- if s.finished {
- if highestOffset > s.highestOffset {
- // reject crypto data received after this stream was already finished
- return errors.New("received crypto data after change of encryption level")
- }
- // ignore data with a smaller offset than the highest received
- // could e.g. be a retransmission
- return nil
- }
- s.highestOffset = utils.MaxByteCount(s.highestOffset, highestOffset)
- if err := s.queue.Push(f.Data, f.Offset, false); err != nil {
- return err
- }
- for {
- data, _ := s.queue.Pop()
- if data == nil {
- return nil
- }
- s.msgBuf = append(s.msgBuf, data...)
- }
- }
- // GetCryptoData retrieves data that was received in CRYPTO frames
- func (s *cryptoStreamImpl) GetCryptoData() []byte {
- if len(s.msgBuf) < 4 {
- return nil
- }
- msgLen := 4 + int(s.msgBuf[1])<<16 + int(s.msgBuf[2])<<8 + int(s.msgBuf[3])
- if len(s.msgBuf) < msgLen {
- return nil
- }
- msg := make([]byte, msgLen)
- copy(msg, s.msgBuf[:msgLen])
- s.msgBuf = s.msgBuf[msgLen:]
- return msg
- }
- func (s *cryptoStreamImpl) Finish() error {
- if s.queue.HasMoreData() {
- return errors.New("encryption level changed, but crypto stream has more data to read")
- }
- s.finished = true
- return nil
- }
- // Writes writes data that should be sent out in CRYPTO frames
- func (s *cryptoStreamImpl) Write(p []byte) (int, error) {
- s.writeBuf = append(s.writeBuf, p...)
- return len(p), nil
- }
- func (s *cryptoStreamImpl) HasData() bool {
- return len(s.writeBuf) > 0
- }
- func (s *cryptoStreamImpl) PopCryptoFrame(maxLen protocol.ByteCount) *wire.CryptoFrame {
- f := &wire.CryptoFrame{Offset: s.writeOffset}
- n := utils.MinByteCount(f.MaxDataLen(maxLen), protocol.ByteCount(len(s.writeBuf)))
- f.Data = s.writeBuf[:n]
- s.writeBuf = s.writeBuf[n:]
- s.writeOffset += n
- return f
- }
|