1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-09-14 07:58:16 -04:00
v2fly/vendor/github.com/lucas-clemente/quic-go/packet_packer.go

506 lines
15 KiB
Go
Raw Normal View History

2018-11-20 17:51:25 -05:00
package quic
import (
"bytes"
"errors"
"fmt"
"net"
"time"
"github.com/lucas-clemente/quic-go/internal/ackhandler"
"github.com/lucas-clemente/quic-go/internal/handshake"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/internal/wire"
)
2018-11-23 11:04:53 -05:00
type packer interface {
PackPacket() (*packedPacket, error)
MaybePackAckPacket() (*packedPacket, error)
PackRetransmission(packet *ackhandler.Packet) ([]*packedPacket, error)
PackConnectionClose(*wire.ConnectionCloseFrame) (*packedPacket, error)
HandleTransportParameters(*handshake.TransportParameters)
ChangeDestConnectionID(protocol.ConnectionID)
}
2018-11-20 17:51:25 -05:00
type packedPacket struct {
header *wire.Header
raw []byte
frames []wire.Frame
encryptionLevel protocol.EncryptionLevel
}
func (p *packedPacket) ToAckHandlerPacket() *ackhandler.Packet {
return &ackhandler.Packet{
PacketNumber: p.header.PacketNumber,
PacketType: p.header.Type,
Frames: p.frames,
Length: protocol.ByteCount(len(p.raw)),
EncryptionLevel: p.encryptionLevel,
SendTime: time.Now(),
}
}
2018-11-23 11:04:53 -05:00
func getMaxPacketSize(addr net.Addr) protocol.ByteCount {
maxSize := protocol.ByteCount(protocol.MinInitialPacketSize)
// If this is not a UDP address, we don't know anything about the MTU.
// Use the minimum size of an Initial packet as the max packet size.
if udpAddr, ok := addr.(*net.UDPAddr); ok {
// If ip is not an IPv4 address, To4 returns nil.
// Note that there might be some corner cases, where this is not correct.
// See https://stackoverflow.com/questions/22751035/golang-distinguish-ipv4-ipv6.
if udpAddr.IP.To4() == nil {
maxSize = protocol.MaxPacketSizeIPv6
} else {
maxSize = protocol.MaxPacketSizeIPv4
}
}
return maxSize
}
type packetNumberManager interface {
PeekPacketNumber() (protocol.PacketNumber, protocol.PacketNumberLen)
PopPacketNumber() protocol.PacketNumber
}
2018-11-20 17:51:25 -05:00
type sealingManager interface {
GetSealer() (protocol.EncryptionLevel, handshake.Sealer)
GetSealerWithEncryptionLevel(protocol.EncryptionLevel) (handshake.Sealer, error)
}
2018-11-23 11:04:53 -05:00
type frameSource interface {
AppendStreamFrames([]wire.Frame, protocol.ByteCount) []wire.Frame
AppendControlFrames([]wire.Frame, protocol.ByteCount) ([]wire.Frame, protocol.ByteCount)
}
type ackFrameSource interface {
GetAckFrame() *wire.AckFrame
2018-11-20 17:51:25 -05:00
}
type packetPacker struct {
destConnID protocol.ConnectionID
srcConnID protocol.ConnectionID
perspective protocol.Perspective
version protocol.VersionNumber
cryptoSetup sealingManager
2018-11-23 11:04:53 -05:00
initialStream cryptoStream
handshakeStream cryptoStream
2018-11-20 17:51:25 -05:00
2018-11-23 11:04:53 -05:00
token []byte
2018-11-20 17:51:25 -05:00
2018-11-23 11:04:53 -05:00
pnManager packetNumberManager
framer frameSource
acks ackFrameSource
2018-11-20 17:51:25 -05:00
maxPacketSize protocol.ByteCount
hasSentPacket bool // has the packetPacker already sent a packet
numNonRetransmittableAcks int
}
2018-11-23 11:04:53 -05:00
var _ packer = &packetPacker{}
2018-11-20 17:51:25 -05:00
func newPacketPacker(
destConnID protocol.ConnectionID,
srcConnID protocol.ConnectionID,
2018-11-23 11:04:53 -05:00
initialStream cryptoStream,
handshakeStream cryptoStream,
packetNumberManager packetNumberManager,
2018-11-20 17:51:25 -05:00
remoteAddr net.Addr, // only used for determining the max packet size
token []byte,
cryptoSetup sealingManager,
2018-11-23 11:04:53 -05:00
framer frameSource,
acks ackFrameSource,
2018-11-20 17:51:25 -05:00
perspective protocol.Perspective,
version protocol.VersionNumber,
) *packetPacker {
return &packetPacker{
2018-11-23 11:04:53 -05:00
cryptoSetup: cryptoSetup,
token: token,
destConnID: destConnID,
srcConnID: srcConnID,
initialStream: initialStream,
handshakeStream: handshakeStream,
perspective: perspective,
version: version,
framer: framer,
acks: acks,
pnManager: packetNumberManager,
maxPacketSize: getMaxPacketSize(remoteAddr),
2018-11-20 17:51:25 -05:00
}
}
// PackConnectionClose packs a packet that ONLY contains a ConnectionCloseFrame
func (p *packetPacker) PackConnectionClose(ccf *wire.ConnectionCloseFrame) (*packedPacket, error) {
frames := []wire.Frame{ccf}
encLevel, sealer := p.cryptoSetup.GetSealer()
header := p.getHeader(encLevel)
raw, err := p.writeAndSealPacket(header, frames, sealer)
return &packedPacket{
header: header,
raw: raw,
frames: frames,
encryptionLevel: encLevel,
}, err
}
2018-11-23 11:04:53 -05:00
func (p *packetPacker) MaybePackAckPacket() (*packedPacket, error) {
ack := p.acks.GetAckFrame()
if ack == nil {
return nil, nil
2018-11-20 17:51:25 -05:00
}
2018-11-23 11:04:53 -05:00
// TODO(#1534): only pack ACKs with the right encryption level
2018-11-20 17:51:25 -05:00
encLevel, sealer := p.cryptoSetup.GetSealer()
header := p.getHeader(encLevel)
2018-11-23 11:04:53 -05:00
frames := []wire.Frame{ack}
2018-11-20 17:51:25 -05:00
raw, err := p.writeAndSealPacket(header, frames, sealer)
return &packedPacket{
header: header,
raw: raw,
frames: frames,
encryptionLevel: encLevel,
}, err
}
// PackRetransmission packs a retransmission
// For packets sent after completion of the handshake, it might happen that 2 packets have to be sent.
// This can happen e.g. when a longer packet number is used in the header.
func (p *packetPacker) PackRetransmission(packet *ackhandler.Packet) ([]*packedPacket, error) {
2018-11-23 11:04:53 -05:00
if packet.EncryptionLevel != protocol.Encryption1RTT {
2018-11-20 17:51:25 -05:00
p, err := p.packHandshakeRetransmission(packet)
return []*packedPacket{p}, err
}
var controlFrames []wire.Frame
var streamFrames []*wire.StreamFrame
for _, f := range packet.Frames {
if sf, ok := f.(*wire.StreamFrame); ok {
sf.DataLenPresent = true
streamFrames = append(streamFrames, sf)
} else {
controlFrames = append(controlFrames, f)
}
}
var packets []*packedPacket
2018-11-23 11:04:53 -05:00
encLevel := packet.EncryptionLevel
sealer, err := p.cryptoSetup.GetSealerWithEncryptionLevel(encLevel)
if err != nil {
return nil, err
}
2018-11-20 17:51:25 -05:00
for len(controlFrames) > 0 || len(streamFrames) > 0 {
var frames []wire.Frame
2018-11-23 11:04:53 -05:00
var length protocol.ByteCount
2018-11-20 17:51:25 -05:00
header := p.getHeader(encLevel)
2018-11-23 11:04:53 -05:00
headerLen := header.GetLength(p.version)
maxSize := p.maxPacketSize - protocol.ByteCount(sealer.Overhead()) - headerLen
2018-11-20 17:51:25 -05:00
for len(controlFrames) > 0 {
frame := controlFrames[0]
2018-11-23 11:04:53 -05:00
frameLen := frame.Length(p.version)
if length+frameLen > maxSize {
2018-11-20 17:51:25 -05:00
break
}
2018-11-23 11:04:53 -05:00
length += frameLen
2018-11-20 17:51:25 -05:00
frames = append(frames, frame)
controlFrames = controlFrames[1:]
}
2018-11-23 11:04:53 -05:00
for len(streamFrames) > 0 && length+protocol.MinStreamFrameSize < maxSize {
2018-11-20 17:51:25 -05:00
frame := streamFrames[0]
2018-11-23 11:04:53 -05:00
frame.DataLenPresent = false
2018-11-20 17:51:25 -05:00
frameToAdd := frame
2018-11-23 11:04:53 -05:00
sf, err := frame.MaybeSplitOffFrame(maxSize-length, p.version)
2018-11-20 17:51:25 -05:00
if err != nil {
return nil, err
}
if sf != nil {
frameToAdd = sf
} else {
streamFrames = streamFrames[1:]
}
2018-11-23 11:04:53 -05:00
frame.DataLenPresent = true
length += frameToAdd.Length(p.version)
2018-11-20 17:51:25 -05:00
frames = append(frames, frameToAdd)
}
if sf, ok := frames[len(frames)-1].(*wire.StreamFrame); ok {
sf.DataLenPresent = false
}
raw, err := p.writeAndSealPacket(header, frames, sealer)
if err != nil {
return nil, err
}
packets = append(packets, &packedPacket{
header: header,
raw: raw,
frames: frames,
encryptionLevel: encLevel,
})
}
return packets, nil
}
2018-11-23 11:04:53 -05:00
// packHandshakeRetransmission retransmits a handshake packet
2018-11-20 17:51:25 -05:00
func (p *packetPacker) packHandshakeRetransmission(packet *ackhandler.Packet) (*packedPacket, error) {
sealer, err := p.cryptoSetup.GetSealerWithEncryptionLevel(packet.EncryptionLevel)
if err != nil {
return nil, err
}
// make sure that the retransmission for an Initial packet is sent as an Initial packet
if packet.PacketType == protocol.PacketTypeInitial {
p.hasSentPacket = false
}
header := p.getHeader(packet.EncryptionLevel)
header.Type = packet.PacketType
2018-11-23 11:04:53 -05:00
raw, err := p.writeAndSealPacket(header, packet.Frames, sealer)
2018-11-20 17:51:25 -05:00
return &packedPacket{
header: header,
raw: raw,
2018-11-23 11:04:53 -05:00
frames: packet.Frames,
2018-11-20 17:51:25 -05:00
encryptionLevel: packet.EncryptionLevel,
}, err
}
// PackPacket packs a new packet
// the other controlFrames are sent in the next packet, but might be queued and sent in the next packet if the packet would overflow MaxPacketSize otherwise
func (p *packetPacker) PackPacket() (*packedPacket, error) {
2018-11-23 11:04:53 -05:00
packet, err := p.maybePackCryptoPacket()
if err != nil {
return nil, err
}
if packet != nil {
return packet, nil
}
2018-11-20 17:51:25 -05:00
// if this is the first packet to be send, make sure it contains stream data
2018-11-23 11:04:53 -05:00
if !p.hasSentPacket && packet == nil {
2018-11-20 17:51:25 -05:00
return nil, nil
}
encLevel, sealer := p.cryptoSetup.GetSealer()
header := p.getHeader(encLevel)
2018-11-23 11:04:53 -05:00
headerLen := header.GetLength(p.version)
2018-11-20 17:51:25 -05:00
if err != nil {
return nil, err
}
2018-11-23 11:04:53 -05:00
maxSize := p.maxPacketSize - protocol.ByteCount(sealer.Overhead()) - headerLen
frames, err := p.composeNextPacket(maxSize, p.canSendData(encLevel))
2018-11-20 17:51:25 -05:00
if err != nil {
return nil, err
}
// Check if we have enough frames to send
2018-11-23 11:04:53 -05:00
if len(frames) == 0 {
2018-11-20 17:51:25 -05:00
return nil, nil
}
2018-11-23 11:04:53 -05:00
// check if this packet only contains an ACK
if !ackhandler.HasRetransmittableFrames(frames) {
if p.numNonRetransmittableAcks >= protocol.MaxNonRetransmittableAcks {
frames = append(frames, &wire.PingFrame{})
2018-11-20 17:51:25 -05:00
p.numNonRetransmittableAcks = 0
2018-11-23 11:04:53 -05:00
} else {
p.numNonRetransmittableAcks++
2018-11-20 17:51:25 -05:00
}
2018-11-23 11:04:53 -05:00
} else {
p.numNonRetransmittableAcks = 0
2018-11-20 17:51:25 -05:00
}
2018-11-23 11:04:53 -05:00
raw, err := p.writeAndSealPacket(header, frames, sealer)
2018-11-20 17:51:25 -05:00
if err != nil {
return nil, err
}
return &packedPacket{
header: header,
raw: raw,
2018-11-23 11:04:53 -05:00
frames: frames,
2018-11-20 17:51:25 -05:00
encryptionLevel: encLevel,
}, nil
}
2018-11-23 11:04:53 -05:00
func (p *packetPacker) maybePackCryptoPacket() (*packedPacket, error) {
var s cryptoStream
var encLevel protocol.EncryptionLevel
if p.initialStream.HasData() {
s = p.initialStream
encLevel = protocol.EncryptionInitial
} else if p.handshakeStream.HasData() {
s = p.handshakeStream
encLevel = protocol.EncryptionHandshake
}
if s == nil {
return nil, nil
}
hdr := p.getHeader(encLevel)
hdrLen := hdr.GetLength(p.version)
sealer, err := p.cryptoSetup.GetSealerWithEncryptionLevel(encLevel)
2018-11-20 17:51:25 -05:00
if err != nil {
return nil, err
}
2018-11-23 11:04:53 -05:00
var length protocol.ByteCount
frames := make([]wire.Frame, 0, 2)
if ack := p.acks.GetAckFrame(); ack != nil {
frames = append(frames, ack)
length += ack.Length(p.version)
}
cf := s.PopCryptoFrame(p.maxPacketSize - hdrLen - protocol.ByteCount(sealer.Overhead()) - length)
frames = append(frames, cf)
raw, err := p.writeAndSealPacket(hdr, frames, sealer)
2018-11-20 17:51:25 -05:00
if err != nil {
return nil, err
}
return &packedPacket{
2018-11-23 11:04:53 -05:00
header: hdr,
2018-11-20 17:51:25 -05:00
raw: raw,
frames: frames,
encryptionLevel: encLevel,
}, nil
}
func (p *packetPacker) composeNextPacket(
maxFrameSize protocol.ByteCount,
canSendStreamFrames bool,
) ([]wire.Frame, error) {
2018-11-23 11:04:53 -05:00
var length protocol.ByteCount
var frames []wire.Frame
2018-11-20 17:51:25 -05:00
2018-11-23 11:04:53 -05:00
// ACKs need to go first, so that the sentPacketHandler will recognize them
if ack := p.acks.GetAckFrame(); ack != nil {
frames = append(frames, ack)
length += ack.Length(p.version)
2018-11-20 17:51:25 -05:00
}
2018-11-23 11:04:53 -05:00
var lengthAdded protocol.ByteCount
frames, lengthAdded = p.framer.AppendControlFrames(frames, maxFrameSize-length)
length += lengthAdded
2018-11-20 17:51:25 -05:00
if !canSendStreamFrames {
2018-11-23 11:04:53 -05:00
return frames, nil
2018-11-20 17:51:25 -05:00
}
// temporarily increase the maxFrameSize by the (minimum) length of the DataLen field
2018-11-23 11:04:53 -05:00
// this leads to a properly sized packet in all cases, since we do all the packet length calculations with STREAM frames that have the DataLen set
2018-11-20 17:51:25 -05:00
// however, for the last STREAM frame in the packet, we can omit the DataLen, thus yielding a packet of exactly the correct size
2018-11-23 11:04:53 -05:00
// the length is encoded to either 1 or 2 bytes
maxFrameSize++
2018-11-20 17:51:25 -05:00
2018-11-23 11:04:53 -05:00
frames = p.framer.AppendStreamFrames(frames, maxFrameSize-length)
if len(frames) > 0 {
lastFrame := frames[len(frames)-1]
if sf, ok := lastFrame.(*wire.StreamFrame); ok {
sf.DataLenPresent = false
}
2018-11-20 17:51:25 -05:00
}
2018-11-23 11:04:53 -05:00
return frames, nil
2018-11-20 17:51:25 -05:00
}
func (p *packetPacker) getHeader(encLevel protocol.EncryptionLevel) *wire.Header {
2018-11-23 11:04:53 -05:00
pn, pnLen := p.pnManager.PeekPacketNumber()
2018-11-20 17:51:25 -05:00
header := &wire.Header{
2018-11-23 11:04:53 -05:00
PacketNumber: pn,
PacketNumberLen: pnLen,
Version: p.version,
DestConnectionID: p.destConnID,
2018-11-20 17:51:25 -05:00
}
2018-11-23 11:04:53 -05:00
if encLevel != protocol.Encryption1RTT {
2018-11-20 17:51:25 -05:00
header.IsLongHeader = true
header.SrcConnectionID = p.srcConnID
2018-11-25 15:55:45 -05:00
// Set the length to the maximum packet size.
2018-11-20 17:51:25 -05:00
// Since it is encoded as a varint, this guarantees us that the header will end up at most as big as GetLength() returns.
2018-11-25 15:55:45 -05:00
header.Length = p.maxPacketSize
2018-11-23 11:04:53 -05:00
switch encLevel {
case protocol.EncryptionInitial:
2018-11-20 17:51:25 -05:00
header.Type = protocol.PacketTypeInitial
2018-11-23 11:04:53 -05:00
case protocol.EncryptionHandshake:
2018-11-20 17:51:25 -05:00
header.Type = protocol.PacketTypeHandshake
}
}
return header
}
func (p *packetPacker) writeAndSealPacket(
header *wire.Header,
2018-11-23 11:04:53 -05:00
frames []wire.Frame,
2018-11-20 17:51:25 -05:00
sealer handshake.Sealer,
) ([]byte, error) {
raw := *getPacketBuffer()
buffer := bytes.NewBuffer(raw[:0])
2018-11-23 11:04:53 -05:00
addPadding := p.perspective == protocol.PerspectiveClient && header.Type == protocol.PacketTypeInitial && !p.hasSentPacket
2018-11-25 15:55:45 -05:00
// the length is only needed for Long Headers
2018-11-20 17:51:25 -05:00
if header.IsLongHeader {
2018-11-23 11:04:53 -05:00
if p.perspective == protocol.PerspectiveClient && header.Type == protocol.PacketTypeInitial {
header.Token = p.token
}
if addPadding {
headerLen := header.GetLength(p.version)
2018-11-25 15:55:45 -05:00
header.Length = protocol.ByteCount(header.PacketNumberLen) + protocol.MinInitialPacketSize - headerLen
2018-11-20 17:51:25 -05:00
} else {
2018-11-25 15:55:45 -05:00
length := protocol.ByteCount(sealer.Overhead()) + protocol.ByteCount(header.PacketNumberLen)
2018-11-23 11:04:53 -05:00
for _, frame := range frames {
2018-11-25 15:55:45 -05:00
length += frame.Length(p.version)
2018-11-20 17:51:25 -05:00
}
2018-11-25 15:55:45 -05:00
header.Length = length
2018-11-20 17:51:25 -05:00
}
}
if err := header.Write(buffer, p.perspective, p.version); err != nil {
return nil, err
}
payloadStartIndex := buffer.Len()
// the Initial packet needs to be padded, so the last STREAM frame must have the data length present
2018-11-23 11:04:53 -05:00
if p.perspective == protocol.PerspectiveClient && header.Type == protocol.PacketTypeInitial {
lastFrame := frames[len(frames)-1]
2018-11-20 17:51:25 -05:00
if sf, ok := lastFrame.(*wire.StreamFrame); ok {
sf.DataLenPresent = true
}
}
2018-11-23 11:04:53 -05:00
for _, frame := range frames {
2018-11-20 17:51:25 -05:00
if err := frame.Write(buffer, p.version); err != nil {
return nil, err
}
}
2018-11-23 11:04:53 -05:00
if addPadding {
2018-11-20 17:51:25 -05:00
paddingLen := protocol.MinInitialPacketSize - sealer.Overhead() - buffer.Len()
if paddingLen > 0 {
buffer.Write(bytes.Repeat([]byte{0}, paddingLen))
}
}
if size := protocol.ByteCount(buffer.Len() + sealer.Overhead()); size > p.maxPacketSize {
return nil, fmt.Errorf("PacketPacker BUG: packet too large (%d bytes, allowed %d bytes)", size, p.maxPacketSize)
}
raw = raw[0:buffer.Len()]
_ = sealer.Seal(raw[payloadStartIndex:payloadStartIndex], raw[payloadStartIndex:], header.PacketNumber, raw[:payloadStartIndex])
raw = raw[0 : buffer.Len()+sealer.Overhead()]
2018-11-23 11:04:53 -05:00
num := p.pnManager.PopPacketNumber()
2018-11-20 17:51:25 -05:00
if num != header.PacketNumber {
return nil, errors.New("packetPacker BUG: Peeked and Popped packet numbers do not match")
}
p.hasSentPacket = true
return raw, nil
}
func (p *packetPacker) canSendData(encLevel protocol.EncryptionLevel) bool {
2018-11-23 11:04:53 -05:00
return encLevel == protocol.Encryption1RTT
2018-11-20 17:51:25 -05:00
}
func (p *packetPacker) ChangeDestConnectionID(connID protocol.ConnectionID) {
p.destConnID = connID
}
2018-11-23 11:04:53 -05:00
func (p *packetPacker) HandleTransportParameters(params *handshake.TransportParameters) {
if params.MaxPacketSize != 0 {
p.maxPacketSize = utils.MinByteCount(p.maxPacketSize, params.MaxPacketSize)
}
2018-11-20 17:51:25 -05:00
}