github.com/ooni/psiphon/tunnel-core@v0.0.0-20230105123940-fe12a24c96ee/oovendor/quic-go/internal/wire/crypto_frame.go (about) 1 package wire 2 3 import ( 4 "bytes" 5 "io" 6 7 "github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/protocol" 8 "github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/quicvarint" 9 ) 10 11 // A CryptoFrame is a CRYPTO frame 12 type CryptoFrame struct { 13 Offset protocol.ByteCount 14 Data []byte 15 } 16 17 func parseCryptoFrame(r *bytes.Reader, _ protocol.VersionNumber) (*CryptoFrame, error) { 18 if _, err := r.ReadByte(); err != nil { 19 return nil, err 20 } 21 22 frame := &CryptoFrame{} 23 offset, err := quicvarint.Read(r) 24 if err != nil { 25 return nil, err 26 } 27 frame.Offset = protocol.ByteCount(offset) 28 dataLen, err := quicvarint.Read(r) 29 if err != nil { 30 return nil, err 31 } 32 if dataLen > uint64(r.Len()) { 33 return nil, io.EOF 34 } 35 if dataLen != 0 { 36 frame.Data = make([]byte, dataLen) 37 if _, err := io.ReadFull(r, frame.Data); err != nil { 38 // this should never happen, since we already checked the dataLen earlier 39 return nil, err 40 } 41 } 42 return frame, nil 43 } 44 45 func (f *CryptoFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error { 46 b.WriteByte(0x6) 47 quicvarint.Write(b, uint64(f.Offset)) 48 quicvarint.Write(b, uint64(len(f.Data))) 49 b.Write(f.Data) 50 return nil 51 } 52 53 // Length of a written frame 54 func (f *CryptoFrame) Length(_ protocol.VersionNumber) protocol.ByteCount { 55 return 1 + quicvarint.Len(uint64(f.Offset)) + quicvarint.Len(uint64(len(f.Data))) + protocol.ByteCount(len(f.Data)) 56 } 57 58 // MaxDataLen returns the maximum data length 59 func (f *CryptoFrame) MaxDataLen(maxSize protocol.ByteCount) protocol.ByteCount { 60 // pretend that the data size will be 1 bytes 61 // if it turns out that varint encoding the length will consume 2 bytes, we need to adjust the data length afterwards 62 headerLen := 1 + quicvarint.Len(uint64(f.Offset)) + 1 63 if headerLen > maxSize { 64 return 0 65 } 66 maxDataLen := maxSize - headerLen 67 if quicvarint.Len(uint64(maxDataLen)) != 1 { 68 maxDataLen-- 69 } 70 return maxDataLen 71 } 72 73 // MaybeSplitOffFrame splits a frame such that it is not bigger than n bytes. 74 // It returns if the frame was actually split. 75 // The frame might not be split if: 76 // * the size is large enough to fit the whole frame 77 // * the size is too small to fit even a 1-byte frame. In that case, the frame returned is nil. 78 func (f *CryptoFrame) MaybeSplitOffFrame(maxSize protocol.ByteCount, version protocol.VersionNumber) (*CryptoFrame, bool /* was splitting required */) { 79 if f.Length(version) <= maxSize { 80 return nil, false 81 } 82 83 n := f.MaxDataLen(maxSize) 84 if n == 0 { 85 return nil, true 86 } 87 88 newLen := protocol.ByteCount(len(f.Data)) - n 89 90 new := &CryptoFrame{} 91 new.Offset = f.Offset 92 new.Data = make([]byte, newLen) 93 94 // swap the data slices 95 new.Data, f.Data = f.Data, new.Data 96 97 copy(f.Data, new.Data[n:]) 98 new.Data = new.Data[:n] 99 f.Offset += n 100 101 return new, true 102 }