2018-11-20 17:51:25 -05:00
package quic
import (
"bytes"
"errors"
"fmt"
"net"
"time"
2019-01-17 09:33:18 -05:00
"v2ray.com/core/external/github.com/lucas-clemente/quic-go/internal/ackhandler"
"v2ray.com/core/external/github.com/lucas-clemente/quic-go/internal/handshake"
"v2ray.com/core/external/github.com/lucas-clemente/quic-go/internal/protocol"
"v2ray.com/core/external/github.com/lucas-clemente/quic-go/internal/utils"
"v2ray.com/core/external/github.com/lucas-clemente/quic-go/internal/wire"
2018-11-20 17:51:25 -05:00
)
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 {
2019-01-02 07:01:06 -05:00
header * wire . ExtendedHeader
raw [ ] byte
frames [ ] wire . Frame
buffer * packetBuffer
}
func ( p * packedPacket ) EncryptionLevel ( ) protocol . EncryptionLevel {
if ! p . header . IsLongHeader {
return protocol . Encryption1RTT
}
switch p . header . Type {
case protocol . PacketTypeInitial :
return protocol . EncryptionInitial
case protocol . PacketTypeHandshake :
return protocol . EncryptionHandshake
default :
return protocol . EncryptionUnspecified
}
2018-11-20 17:51:25 -05:00
}
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 ) ) ,
2019-01-02 07:01:06 -05:00
EncryptionLevel : p . EncryptionLevel ( ) ,
2018-11-20 17:51:25 -05:00
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 {
2019-01-16 05:48:15 -05:00
GetAckFrame ( protocol . EncryptionLevel ) * 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
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 )
2019-01-02 07:01:06 -05:00
return p . writeAndSealPacket ( header , frames , sealer )
2018-11-20 17:51:25 -05:00
}
2018-11-23 11:04:53 -05:00
func ( p * packetPacker ) MaybePackAckPacket ( ) ( * packedPacket , error ) {
2019-01-16 05:48:15 -05:00
ack := p . acks . GetAckFrame ( protocol . Encryption1RTT )
2018-11-23 11:04:53 -05:00
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 }
2019-01-02 07:01:06 -05:00
return p . writeAndSealPacket ( header , frames , sealer )
2018-11-20 17:51:25 -05:00
}
// 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 ) {
var controlFrames [ ] wire . Frame
var streamFrames [ ] * wire . StreamFrame
for _ , f := range packet . Frames {
2018-11-30 08:41:11 -05:00
// CRYPTO frames are treated as control frames here.
// Since we're making sure that the header can never be larger for a retransmission,
// we never have to split CRYPTO frames.
2018-11-20 17:51:25 -05:00
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
}
2019-01-02 07:01:06 -05:00
p , err := p . writeAndSealPacket ( header , frames , sealer )
2018-11-20 17:51:25 -05:00
if err != nil {
return nil , err
}
2019-01-02 07:01:06 -05:00
packets = append ( packets , p )
2018-11-20 17:51:25 -05:00
}
return packets , nil
}
// 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
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
2018-11-30 08:41:11 -05:00
frames , err := p . composeNextPacket ( maxSize )
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
}
2019-01-02 07:01:06 -05:00
return p . writeAndSealPacket ( header , frames , sealer )
2018-11-20 17:51:25 -05:00
}
2018-11-23 11:04:53 -05:00
func ( p * packetPacker ) maybePackCryptoPacket ( ) ( * packedPacket , error ) {
var s cryptoStream
var encLevel protocol . EncryptionLevel
2019-01-16 05:48:15 -05:00
hasData := p . initialStream . HasData ( )
ack := p . acks . GetAckFrame ( protocol . EncryptionInitial )
if hasData || ack != nil {
2018-11-23 11:04:53 -05:00
s = p . initialStream
encLevel = protocol . EncryptionInitial
2019-01-16 05:48:15 -05:00
} else {
hasData = p . handshakeStream . HasData ( )
ack = p . acks . GetAckFrame ( protocol . EncryptionHandshake )
if hasData || ack != nil {
s = p . handshakeStream
encLevel = protocol . EncryptionHandshake
}
2018-11-23 11:04:53 -05:00
}
if s == nil {
return nil , nil
}
sealer , err := p . cryptoSetup . GetSealerWithEncryptionLevel ( encLevel )
2018-11-20 17:51:25 -05:00
if err != nil {
2019-01-16 05:48:15 -05:00
// The sealer
2018-11-20 17:51:25 -05:00
return nil , err
}
2019-01-16 05:48:15 -05:00
hdr := p . getHeader ( encLevel )
hdrLen := hdr . GetLength ( p . version )
2018-11-23 11:04:53 -05:00
var length protocol . ByteCount
frames := make ( [ ] wire . Frame , 0 , 2 )
2019-01-16 05:48:15 -05:00
if ack != nil {
2018-11-23 11:04:53 -05:00
frames = append ( frames , ack )
length += ack . Length ( p . version )
}
2019-01-16 05:48:15 -05:00
if hasData {
cf := s . PopCryptoFrame ( p . maxPacketSize - hdrLen - protocol . ByteCount ( sealer . Overhead ( ) ) - length )
frames = append ( frames , cf )
}
2019-01-02 07:01:06 -05:00
return p . writeAndSealPacket ( hdr , frames , sealer )
2018-11-20 17:51:25 -05:00
}
2018-11-30 08:41:11 -05:00
func ( p * packetPacker ) composeNextPacket ( maxFrameSize protocol . ByteCount ) ( [ ] 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
2019-01-16 05:48:15 -05:00
if ack := p . acks . GetAckFrame ( protocol . Encryption1RTT ) ; ack != nil {
2018-11-23 11:04:53 -05:00
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
// 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
}
2018-11-27 09:29:03 -05:00
func ( p * packetPacker ) getHeader ( encLevel protocol . EncryptionLevel ) * wire . ExtendedHeader {
2018-11-23 11:04:53 -05:00
pn , pnLen := p . pnManager . PeekPacketNumber ( )
2018-11-27 09:29:03 -05:00
header := & wire . ExtendedHeader { }
header . PacketNumber = pn
header . PacketNumberLen = pnLen
header . Version = p . version
header . 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
2018-11-30 08:41:11 -05:00
// Always send Initial and Handshake packets with the maximum packet number length.
// This simplifies retransmissions: Since the header can't get any larger,
// we don't need to split CRYPTO frames.
header . PacketNumberLen = protocol . PacketNumberLen4
2018-11-20 17:51:25 -05:00
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 (
2018-11-30 08:41:11 -05:00
header * wire . ExtendedHeader ,
frames [ ] wire . Frame ,
2018-11-20 17:51:25 -05:00
sealer handshake . Sealer ,
2019-01-02 07:01:06 -05:00
) ( * packedPacket , error ) {
packetBuffer := getPacketBuffer ( )
buffer := bytes . NewBuffer ( packetBuffer . Slice [ : 0 ] )
2018-11-20 17:51:25 -05:00
2018-11-30 08:41:11 -05:00
addPaddingForInitial := p . perspective == protocol . PerspectiveClient && header . Type == protocol . PacketTypeInitial
2018-11-23 11:04:53 -05:00
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
}
2018-11-30 08:41:11 -05:00
if addPaddingForInitial {
2018-11-23 11:04:53 -05:00
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-30 08:41:11 -05:00
// long header packets always use 4 byte packet number, so we never need to pad short payloads
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
}
}
2018-11-27 09:29:03 -05:00
if err := header . Write ( buffer , p . version ) ; err != nil {
2018-11-20 17:51:25 -05:00
return nil , err
}
2019-01-02 07:01:06 -05:00
payloadOffset := buffer . Len ( )
2018-11-20 17:51:25 -05:00
2018-11-30 08:41:11 -05:00
// write all frames but the last one
for _ , frame := range frames [ : len ( frames ) - 1 ] {
if err := frame . Write ( buffer , p . version ) ; err != nil {
return nil , err
}
}
lastFrame := frames [ len ( frames ) - 1 ]
if addPaddingForInitial {
// when appending padding, we need to make sure that the last STREAM frames has the data length set
2018-11-20 17:51:25 -05:00
if sf , ok := lastFrame . ( * wire . StreamFrame ) ; ok {
sf . DataLenPresent = true
}
2018-11-30 08:41:11 -05:00
} else {
2019-01-02 07:01:06 -05:00
payloadLen := buffer . Len ( ) - payloadOffset + int ( lastFrame . Length ( p . version ) )
2018-11-30 08:41:11 -05:00
if paddingLen := 4 - int ( header . PacketNumberLen ) - payloadLen ; paddingLen > 0 {
// Pad the packet such that packet number length + payload length is 4 bytes.
// This is needed to enable the peer to get a 16 byte sample for header protection.
buffer . Write ( bytes . Repeat ( [ ] byte { 0 } , paddingLen ) )
2018-11-20 17:51:25 -05:00
}
}
2018-11-30 08:41:11 -05:00
if err := lastFrame . Write ( buffer , p . version ) ; err != nil {
return nil , err
}
if addPaddingForInitial {
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 )
}
2019-01-02 07:01:06 -05:00
raw := buffer . Bytes ( )
_ = sealer . Seal ( raw [ payloadOffset : payloadOffset ] , raw [ payloadOffset : ] , header . PacketNumber , raw [ : payloadOffset ] )
2018-11-20 17:51:25 -05:00
raw = raw [ 0 : buffer . Len ( ) + sealer . Overhead ( ) ]
2019-01-02 07:01:06 -05:00
pnOffset := payloadOffset - int ( header . PacketNumberLen )
sealer . EncryptHeader (
raw [ pnOffset + 4 : pnOffset + 4 + 16 ] ,
& raw [ 0 ] ,
raw [ pnOffset : payloadOffset ] ,
)
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" )
}
2019-01-02 07:01:06 -05:00
return & packedPacket {
header : header ,
raw : raw ,
frames : frames ,
buffer : packetBuffer ,
} , nil
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
}