2017-05-27 22:30:11 +03:00
package quic
import (
"bytes"
"errors"
"fmt"
2018-03-26 07:37:41 +03:00
"net"
2018-02-17 08:29:53 +03:00
"sync"
2018-04-19 00:48:08 +03:00
"time"
2017-05-27 22:30:11 +03:00
2018-02-17 08:29:53 +03:00
"github.com/lucas-clemente/quic-go/internal/ackhandler"
"github.com/lucas-clemente/quic-go/internal/handshake"
"github.com/lucas-clemente/quic-go/internal/protocol"
2018-03-26 07:37:41 +03:00
"github.com/lucas-clemente/quic-go/internal/utils"
2018-02-17 08:29:53 +03:00
"github.com/lucas-clemente/quic-go/internal/wire"
2017-05-27 22:30:11 +03:00
)
type packedPacket struct {
2018-02-17 08:29:53 +03:00
header * wire . Header
2017-05-27 22:30:11 +03:00
raw [ ] byte
2018-02-17 08:29:53 +03:00
frames [ ] wire . Frame
2017-05-27 22:30:11 +03:00
encryptionLevel protocol . EncryptionLevel
}
2018-03-26 07:37:41 +03: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 ) ) ,
EncryptionLevel : p . encryptionLevel ,
2018-04-19 00:48:08 +03:00
SendTime : time . Now ( ) ,
2018-03-26 07:37:41 +03:00
}
}
2018-04-19 00:48:08 +03:00
type sealingManager interface {
GetSealer ( ) ( protocol . EncryptionLevel , handshake . Sealer )
GetSealerForCryptoStream ( ) ( protocol . EncryptionLevel , handshake . Sealer )
GetSealerWithEncryptionLevel ( protocol . EncryptionLevel ) ( handshake . Sealer , error )
}
2018-02-17 08:29:53 +03:00
type streamFrameSource interface {
HasCryptoStreamData ( ) bool
PopCryptoStreamFrame ( protocol . ByteCount ) * wire . StreamFrame
PopStreamFrames ( protocol . ByteCount ) [ ] * wire . StreamFrame
}
2017-05-27 22:30:11 +03:00
type packetPacker struct {
2018-09-03 00:18:54 +03:00
destConnID protocol . ConnectionID
srcConnID protocol . ConnectionID
perspective protocol . Perspective
version protocol . VersionNumber
cryptoSetup sealingManager
token [ ] byte
divNonce [ ] byte
2017-05-27 22:30:11 +03:00
packetNumberGenerator * packetNumberGenerator
2018-03-26 07:37:41 +03:00
getPacketNumberLen func ( protocol . PacketNumber ) protocol . PacketNumberLen
2018-02-17 08:29:53 +03:00
streams streamFrameSource
controlFrameMutex sync . Mutex
controlFrames [ ] wire . Frame
2017-05-27 22:30:11 +03:00
2018-02-17 08:29:53 +03:00
stopWaiting * wire . StopWaitingFrame
ackFrame * wire . AckFrame
omitConnectionID bool
2018-03-26 07:37:41 +03:00
maxPacketSize protocol . ByteCount
2018-02-17 08:29:53 +03:00
hasSentPacket bool // has the packetPacker already sent a packet
numNonRetransmittableAcks int
2017-05-27 22:30:11 +03:00
}
2018-09-03 00:18:54 +03:00
func newPacketPacker (
destConnID protocol . ConnectionID ,
srcConnID protocol . ConnectionID ,
2018-02-17 08:29:53 +03:00
initialPacketNumber protocol . PacketNumber ,
2018-03-26 07:37:41 +03:00
getPacketNumberLen func ( protocol . PacketNumber ) protocol . PacketNumberLen ,
remoteAddr net . Addr , // only used for determining the max packet size
2018-09-03 00:18:54 +03:00
token [ ] byte ,
2018-04-19 00:48:08 +03:00
divNonce [ ] byte ,
cryptoSetup sealingManager ,
2018-02-17 08:29:53 +03:00
streamFramer streamFrameSource ,
2017-07-28 01:11:56 +03:00
perspective protocol . Perspective ,
version protocol . VersionNumber ,
) * packetPacker {
2018-03-26 07:37:41 +03:00
maxPacketSize := 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 := remoteAddr . ( * 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 {
maxPacketSize = protocol . MaxPacketSizeIPv6
} else {
maxPacketSize = protocol . MaxPacketSizeIPv4
}
}
2017-05-27 22:30:11 +03:00
return & packetPacker {
cryptoSetup : cryptoSetup ,
2018-04-19 00:48:08 +03:00
divNonce : divNonce ,
2018-09-03 00:18:54 +03:00
token : token ,
destConnID : destConnID ,
srcConnID : srcConnID ,
2017-05-27 22:30:11 +03:00
perspective : perspective ,
version : version ,
2018-02-17 08:29:53 +03:00
streams : streamFramer ,
2018-03-26 07:37:41 +03:00
getPacketNumberLen : getPacketNumberLen ,
2018-02-17 08:29:53 +03:00
packetNumberGenerator : newPacketNumberGenerator ( initialPacketNumber , protocol . SkipPacketAveragePeriodLength ) ,
2018-03-26 07:37:41 +03:00
maxPacketSize : maxPacketSize ,
2017-05-27 22:30:11 +03:00
}
}
// PackConnectionClose packs a packet that ONLY contains a ConnectionCloseFrame
2018-02-17 08:29:53 +03:00
func ( p * packetPacker ) PackConnectionClose ( ccf * wire . ConnectionCloseFrame ) ( * packedPacket , error ) {
frames := [ ] wire . Frame { ccf }
2017-07-28 01:11:56 +03:00
encLevel , sealer := p . cryptoSetup . GetSealer ( )
2018-02-17 08:29:53 +03:00
header := p . getHeader ( encLevel )
raw , err := p . writeAndSealPacket ( header , frames , sealer )
2017-07-28 01:11:56 +03:00
return & packedPacket {
2018-02-17 08:29:53 +03:00
header : header ,
2017-07-28 01:11:56 +03:00
raw : raw ,
frames : frames ,
encryptionLevel : encLevel ,
} , err
}
func ( p * packetPacker ) PackAckPacket ( ) ( * packedPacket , error ) {
if p . ackFrame == nil {
return nil , errors . New ( "packet packer BUG: no ack frame queued" )
}
encLevel , sealer := p . cryptoSetup . GetSealer ( )
2018-02-17 08:29:53 +03:00
header := p . getHeader ( encLevel )
frames := [ ] wire . Frame { p . ackFrame }
if p . stopWaiting != nil { // a STOP_WAITING will only be queued when using gQUIC
p . stopWaiting . PacketNumber = header . PacketNumber
p . stopWaiting . PacketNumberLen = header . PacketNumberLen
2017-07-28 01:11:56 +03:00
frames = append ( frames , p . stopWaiting )
p . stopWaiting = nil
}
p . ackFrame = nil
2018-02-17 08:29:53 +03:00
raw , err := p . writeAndSealPacket ( header , frames , sealer )
2017-07-28 01:11:56 +03:00
return & packedPacket {
2018-02-17 08:29:53 +03:00
header : header ,
2017-07-28 01:11:56 +03:00
raw : raw ,
frames : frames ,
encryptionLevel : encLevel ,
} , err
2017-05-27 22:30:11 +03:00
}
2018-03-26 07:37:41 +03: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 ) {
if packet . EncryptionLevel != protocol . EncryptionForwardSecure {
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
encLevel , sealer := p . cryptoSetup . GetSealer ( )
for len ( controlFrames ) > 0 || len ( streamFrames ) > 0 {
var frames [ ] wire . Frame
var payloadLength protocol . ByteCount
header := p . getHeader ( encLevel )
2018-09-03 00:18:54 +03:00
headerLength , err := header . GetLength ( p . version )
2018-03-26 07:37:41 +03:00
if err != nil {
return nil , err
}
maxSize := p . maxPacketSize - protocol . ByteCount ( sealer . Overhead ( ) ) - headerLength
// for gQUIC: add a STOP_WAITING for *every* retransmission
if p . version . UsesStopWaitingFrames ( ) {
if p . stopWaiting == nil {
return nil , errors . New ( "PacketPacker BUG: Handshake retransmissions must contain a STOP_WAITING frame" )
}
// create a new StopWaitingFrame, since we might need to send more than one packet as a retransmission
swf := & wire . StopWaitingFrame {
LeastUnacked : p . stopWaiting . LeastUnacked ,
PacketNumber : header . PacketNumber ,
PacketNumberLen : header . PacketNumberLen ,
}
payloadLength += swf . Length ( p . version )
frames = append ( frames , swf )
}
for len ( controlFrames ) > 0 {
frame := controlFrames [ 0 ]
length := frame . Length ( p . version )
if payloadLength + length > maxSize {
break
}
payloadLength += length
frames = append ( frames , frame )
controlFrames = controlFrames [ 1 : ]
}
// temporarily increase the maxFrameSize by the (minimum) length of the DataLen field
// this leads to a properly sized packet in all cases, since we do all the packet length calculations with StreamFrames that have the DataLen set
// however, for the last STREAM frame in the packet, we can omit the DataLen, thus yielding a packet of exactly the correct size
// for gQUIC STREAM frames, DataLen is always 2 bytes
// for IETF draft style STREAM frames, the length is encoded to either 1 or 2 bytes
if p . version . UsesIETFFrameFormat ( ) {
maxSize ++
} else {
maxSize += 2
}
for len ( streamFrames ) > 0 && payloadLength + protocol . MinStreamFrameSize < maxSize {
// TODO: optimize by setting DataLenPresent = false on all but the last STREAM frame
frame := streamFrames [ 0 ]
frameToAdd := frame
sf , err := frame . MaybeSplitOffFrame ( maxSize - payloadLength , p . version )
if err != nil {
return nil , err
}
if sf != nil {
frameToAdd = sf
} else {
streamFrames = streamFrames [ 1 : ]
}
payloadLength += frameToAdd . Length ( p . version )
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 ,
} )
2017-05-27 22:30:11 +03:00
}
2018-03-26 07:37:41 +03:00
p . stopWaiting = nil
return packets , nil
}
// packHandshakeRetransmission retransmits a handshake packet, that was sent with less than forward-secure encryption
func ( p * packetPacker ) packHandshakeRetransmission ( packet * ackhandler . Packet ) ( * packedPacket , error ) {
2017-07-28 01:11:56 +03:00
sealer , err := p . cryptoSetup . GetSealerWithEncryptionLevel ( packet . EncryptionLevel )
if err != nil {
return nil , err
}
2018-03-26 07:37:41 +03:00
// make sure that the retransmission for an Initial packet is sent as an Initial packet
if packet . PacketType == protocol . PacketTypeInitial {
p . hasSentPacket = false
}
2018-02-17 08:29:53 +03:00
header := p . getHeader ( packet . EncryptionLevel )
2018-03-26 07:37:41 +03:00
header . Type = packet . PacketType
2018-02-17 08:29:53 +03:00
var frames [ ] wire . Frame
2018-03-26 07:37:41 +03:00
if p . version . UsesStopWaitingFrames ( ) { // for gQUIC: pack a STOP_WAITING first
2018-02-17 08:29:53 +03:00
if p . stopWaiting == nil {
return nil , errors . New ( "PacketPacker BUG: Handshake retransmissions must contain a STOP_WAITING frame" )
}
swf := p . stopWaiting
swf . PacketNumber = header . PacketNumber
swf . PacketNumberLen = header . PacketNumberLen
p . stopWaiting = nil
frames = append ( [ ] wire . Frame { swf } , packet . Frames ... )
} else {
frames = packet . Frames
2017-05-27 22:30:11 +03:00
}
2018-02-17 08:29:53 +03:00
raw , err := p . writeAndSealPacket ( header , frames , sealer )
2017-07-28 01:11:56 +03:00
return & packedPacket {
2018-02-17 08:29:53 +03:00
header : header ,
2017-07-28 01:11:56 +03:00
raw : raw ,
frames : frames ,
encryptionLevel : packet . EncryptionLevel ,
} , err
2017-05-27 22:30:11 +03:00
}
// 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
2017-07-28 01:11:56 +03:00
func ( p * packetPacker ) PackPacket ( ) ( * packedPacket , error ) {
2018-02-17 08:29:53 +03:00
hasCryptoStreamFrame := p . streams . HasCryptoStreamData ( )
// if this is the first packet to be send, make sure it contains stream data
if ! p . hasSentPacket && ! hasCryptoStreamFrame {
return nil , nil
}
if hasCryptoStreamFrame {
2017-07-28 01:11:56 +03:00
return p . packCryptoPacket ( )
2017-05-27 22:30:11 +03:00
}
2017-07-28 01:11:56 +03:00
encLevel , sealer := p . cryptoSetup . GetSealer ( )
2017-05-27 22:30:11 +03:00
2018-02-17 08:29:53 +03:00
header := p . getHeader ( encLevel )
2018-09-03 00:18:54 +03:00
headerLength , err := header . GetLength ( p . version )
2017-05-27 22:30:11 +03:00
if err != nil {
return nil , err
}
2017-07-28 01:11:56 +03:00
if p . stopWaiting != nil {
2018-02-17 08:29:53 +03:00
p . stopWaiting . PacketNumber = header . PacketNumber
p . stopWaiting . PacketNumberLen = header . PacketNumberLen
2017-05-27 22:30:11 +03:00
}
2018-03-26 07:37:41 +03:00
maxSize := p . maxPacketSize - protocol . ByteCount ( sealer . Overhead ( ) ) - headerLength
2017-07-28 01:11:56 +03:00
payloadFrames , err := p . composeNextPacket ( maxSize , p . canSendData ( encLevel ) )
if err != nil {
return nil , err
2017-05-27 22:30:11 +03:00
}
// Check if we have enough frames to send
if len ( payloadFrames ) == 0 {
return nil , nil
}
// Don't send out packets that only contain a StopWaitingFrame
2017-07-28 01:11:56 +03:00
if len ( payloadFrames ) == 1 && p . stopWaiting != nil {
2017-05-27 22:30:11 +03:00
return nil , nil
}
2018-02-17 08:29:53 +03:00
if p . ackFrame != nil {
// check if this packet only contains an ACK (and maybe a STOP_WAITING)
if len ( payloadFrames ) == 1 || ( p . stopWaiting != nil && len ( payloadFrames ) == 2 ) {
if p . numNonRetransmittableAcks >= protocol . MaxNonRetransmittableAcks {
payloadFrames = append ( payloadFrames , & wire . PingFrame { } )
p . numNonRetransmittableAcks = 0
} else {
p . numNonRetransmittableAcks ++
}
} else {
p . numNonRetransmittableAcks = 0
}
}
2017-07-28 01:11:56 +03:00
p . stopWaiting = nil
p . ackFrame = nil
2017-05-27 22:30:11 +03:00
2018-02-17 08:29:53 +03:00
raw , err := p . writeAndSealPacket ( header , payloadFrames , sealer )
2017-07-28 01:11:56 +03:00
if err != nil {
2017-05-27 22:30:11 +03:00
return nil , err
}
2017-07-28 01:11:56 +03:00
return & packedPacket {
2018-02-17 08:29:53 +03:00
header : header ,
2017-07-28 01:11:56 +03:00
raw : raw ,
frames : payloadFrames ,
encryptionLevel : encLevel ,
} , nil
}
2017-05-27 22:30:11 +03:00
2017-07-28 01:11:56 +03:00
func ( p * packetPacker ) packCryptoPacket ( ) ( * packedPacket , error ) {
encLevel , sealer := p . cryptoSetup . GetSealerForCryptoStream ( )
2018-02-17 08:29:53 +03:00
header := p . getHeader ( encLevel )
2018-09-03 00:18:54 +03:00
headerLength , err := header . GetLength ( p . version )
2017-07-28 01:11:56 +03:00
if err != nil {
return nil , err
2017-05-27 22:30:11 +03:00
}
2018-03-26 07:37:41 +03:00
maxLen := p . maxPacketSize - protocol . ByteCount ( sealer . Overhead ( ) ) - protocol . NonForwardSecurePacketSizeReduction - headerLength
2018-02-17 08:29:53 +03:00
sf := p . streams . PopCryptoStreamFrame ( maxLen )
sf . DataLenPresent = false
frames := [ ] wire . Frame { sf }
raw , err := p . writeAndSealPacket ( header , frames , sealer )
2017-07-28 01:11:56 +03:00
if err != nil {
return nil , err
2017-05-27 22:30:11 +03:00
}
return & packedPacket {
2018-02-17 08:29:53 +03:00
header : header ,
2017-05-27 22:30:11 +03:00
raw : raw ,
2017-07-28 01:11:56 +03:00
frames : frames ,
2017-05-27 22:30:11 +03:00
encryptionLevel : encLevel ,
} , nil
}
2017-07-28 01:11:56 +03:00
func ( p * packetPacker ) composeNextPacket (
maxFrameSize protocol . ByteCount ,
canSendStreamFrames bool ,
2018-02-17 08:29:53 +03:00
) ( [ ] wire . Frame , error ) {
2017-05-27 22:30:11 +03:00
var payloadLength protocol . ByteCount
2018-02-17 08:29:53 +03:00
var payloadFrames [ ] wire . Frame
2017-05-27 22:30:11 +03:00
2017-07-28 01:11:56 +03:00
// STOP_WAITING and ACK will always fit
2018-02-17 08:29:53 +03:00
if p . ackFrame != nil { // ACKs need to go first, so that the sentPacketHandler will recognize them
2017-07-28 01:11:56 +03:00
payloadFrames = append ( payloadFrames , p . ackFrame )
2018-02-17 08:29:53 +03:00
l := p . ackFrame . Length ( p . version )
2017-07-28 01:11:56 +03:00
payloadLength += l
2017-05-27 22:30:11 +03:00
}
2018-02-17 08:29:53 +03:00
if p . stopWaiting != nil { // a STOP_WAITING will only be queued when using gQUIC
payloadFrames = append ( payloadFrames , p . stopWaiting )
payloadLength += p . stopWaiting . Length ( p . version )
}
2017-05-27 22:30:11 +03:00
2018-02-17 08:29:53 +03:00
p . controlFrameMutex . Lock ( )
2017-05-27 22:30:11 +03:00
for len ( p . controlFrames ) > 0 {
frame := p . controlFrames [ len ( p . controlFrames ) - 1 ]
2018-02-17 08:29:53 +03:00
length := frame . Length ( p . version )
if payloadLength + length > maxFrameSize {
2017-05-27 22:30:11 +03:00
break
}
payloadFrames = append ( payloadFrames , frame )
2018-02-17 08:29:53 +03:00
payloadLength += length
2017-05-27 22:30:11 +03:00
p . controlFrames = p . controlFrames [ : len ( p . controlFrames ) - 1 ]
}
2018-02-17 08:29:53 +03:00
p . controlFrameMutex . Unlock ( )
2017-05-27 22:30:11 +03:00
if payloadLength > maxFrameSize {
return nil , fmt . Errorf ( "Packet Packer BUG: packet payload (%d) too large (%d)" , payloadLength , maxFrameSize )
}
2017-07-28 01:11:56 +03:00
if ! canSendStreamFrames {
return payloadFrames , nil
}
2018-02-17 08:29:53 +03:00
// temporarily increase the maxFrameSize by the (minimum) length of the DataLen field
2017-05-27 22:30:11 +03:00
// this leads to a properly sized packet in all cases, since we do all the packet length calculations with StreamFrames that have the DataLen set
2018-03-26 07:37:41 +03: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-02-17 08:29:53 +03:00
// for gQUIC STREAM frames, DataLen is always 2 bytes
// for IETF draft style STREAM frames, the length is encoded to either 1 or 2 bytes
if p . version . UsesIETFFrameFormat ( ) {
maxFrameSize ++
} else {
maxFrameSize += 2
}
2017-05-27 22:30:11 +03:00
2018-02-17 08:29:53 +03:00
fs := p . streams . PopStreamFrames ( maxFrameSize - payloadLength )
2017-05-27 22:30:11 +03:00
if len ( fs ) != 0 {
fs [ len ( fs ) - 1 ] . DataLenPresent = false
}
for _ , f := range fs {
payloadFrames = append ( payloadFrames , f )
}
return payloadFrames , nil
}
2018-02-17 08:29:53 +03:00
func ( p * packetPacker ) QueueControlFrame ( frame wire . Frame ) {
2017-07-28 01:11:56 +03:00
switch f := frame . ( type ) {
2018-02-17 08:29:53 +03:00
case * wire . StopWaitingFrame :
2017-07-28 01:11:56 +03:00
p . stopWaiting = f
2018-02-17 08:29:53 +03:00
case * wire . AckFrame :
2017-07-28 01:11:56 +03:00
p . ackFrame = f
default :
2018-02-17 08:29:53 +03:00
p . controlFrameMutex . Lock ( )
2017-07-28 01:11:56 +03:00
p . controlFrames = append ( p . controlFrames , f )
2018-02-17 08:29:53 +03:00
p . controlFrameMutex . Unlock ( )
2017-07-28 01:11:56 +03:00
}
}
2018-02-17 08:29:53 +03:00
func ( p * packetPacker ) getHeader ( encLevel protocol . EncryptionLevel ) * wire . Header {
2017-07-28 01:11:56 +03:00
pnum := p . packetNumberGenerator . Peek ( )
2018-03-26 07:37:41 +03:00
packetNumberLen := p . getPacketNumberLen ( pnum )
2017-07-28 01:11:56 +03:00
2018-02-17 08:29:53 +03:00
header := & wire . Header {
PacketNumber : pnum ,
PacketNumberLen : packetNumberLen ,
2018-09-03 00:18:54 +03:00
Version : p . version ,
2017-07-28 01:11:56 +03:00
}
2018-02-17 08:29:53 +03:00
2018-09-03 00:18:54 +03:00
if p . version . UsesIETFHeaderFormat ( ) && encLevel != protocol . EncryptionForwardSecure {
2018-02-17 08:29:53 +03:00
header . IsLongHeader = true
2018-09-03 00:18:54 +03:00
header . SrcConnectionID = p . srcConnID
if ! p . version . UsesVarintPacketNumbers ( ) {
header . PacketNumberLen = protocol . PacketNumberLen4
}
// Set the payload len to maximum size.
// Since it is encoded as a varint, this guarantees us that the header will end up at most as big as GetLength() returns.
header . PayloadLen = p . maxPacketSize
2018-02-17 08:29:53 +03:00
if ! p . hasSentPacket && p . perspective == protocol . PerspectiveClient {
header . Type = protocol . PacketTypeInitial
2018-09-03 00:18:54 +03:00
header . Token = p . token
2018-02-17 08:29:53 +03:00
} else {
header . Type = protocol . PacketTypeHandshake
}
2017-07-28 01:11:56 +03:00
}
2018-09-03 00:18:54 +03:00
if ! p . omitConnectionID || encLevel != protocol . EncryptionForwardSecure {
header . DestConnectionID = p . destConnID
2018-02-17 08:29:53 +03:00
}
if ! p . version . UsesTLS ( ) {
if p . perspective == protocol . PerspectiveServer && encLevel == protocol . EncryptionSecure {
2018-09-03 00:18:54 +03:00
header . Type = protocol . PacketType0RTT
2018-04-19 00:48:08 +03:00
header . DiversificationNonce = p . divNonce
2018-02-17 08:29:53 +03:00
}
if p . perspective == protocol . PerspectiveClient && encLevel != protocol . EncryptionForwardSecure {
header . VersionFlag = true
}
}
return header
2017-07-28 01:11:56 +03:00
}
func ( p * packetPacker ) writeAndSealPacket (
2018-02-17 08:29:53 +03:00
header * wire . Header ,
payloadFrames [ ] wire . Frame ,
2017-07-28 01:11:56 +03:00
sealer handshake . Sealer ,
) ( [ ] byte , error ) {
2018-03-26 07:37:41 +03:00
raw := * getPacketBuffer ( )
buffer := bytes . NewBuffer ( raw [ : 0 ] )
2017-07-28 01:11:56 +03:00
2018-09-03 00:18:54 +03:00
// the payload length is only needed for Long Headers
if header . IsLongHeader {
if header . Type == protocol . PacketTypeInitial {
headerLen , _ := header . GetLength ( p . version )
header . PayloadLen = protocol . ByteCount ( protocol . MinInitialPacketSize ) - headerLen
} else {
payloadLen := protocol . ByteCount ( sealer . Overhead ( ) )
for _ , frame := range payloadFrames {
payloadLen += frame . Length ( p . version )
}
header . PayloadLen = payloadLen
}
}
2018-02-17 08:29:53 +03:00
if err := header . Write ( buffer , p . perspective , p . version ) ; err != nil {
2017-07-28 01:11:56 +03:00
return nil , err
}
payloadStartIndex := buffer . Len ( )
2018-02-17 08:29:53 +03:00
// the Initial packet needs to be padded, so the last STREAM frame must have the data length present
if header . Type == protocol . PacketTypeInitial {
lastFrame := payloadFrames [ len ( payloadFrames ) - 1 ]
if sf , ok := lastFrame . ( * wire . StreamFrame ) ; ok {
sf . DataLenPresent = true
}
}
2017-07-28 01:11:56 +03:00
for _ , frame := range payloadFrames {
2018-02-17 08:29:53 +03:00
if err := frame . Write ( buffer , p . version ) ; err != nil {
2017-07-28 01:11:56 +03:00
return nil , err
}
}
2018-02-17 08:29:53 +03:00
// if this is an IETF QUIC Initial packet, we need to pad it to fulfill the minimum size requirement
// in gQUIC, padding is handled in the CHLO
if header . Type == protocol . PacketTypeInitial {
paddingLen := protocol . MinInitialPacketSize - sealer . Overhead ( ) - buffer . Len ( )
if paddingLen > 0 {
buffer . Write ( bytes . Repeat ( [ ] byte { 0 } , paddingLen ) )
}
}
2018-03-26 07:37:41 +03:00
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 )
2017-07-28 01:11:56 +03:00
}
raw = raw [ 0 : buffer . Len ( ) ]
2018-02-17 08:29:53 +03:00
_ = sealer . Seal ( raw [ payloadStartIndex : payloadStartIndex ] , raw [ payloadStartIndex : ] , header . PacketNumber , raw [ : payloadStartIndex ] )
raw = raw [ 0 : buffer . Len ( ) + sealer . Overhead ( ) ]
2017-07-28 01:11:56 +03:00
num := p . packetNumberGenerator . Pop ( )
2018-02-17 08:29:53 +03:00
if num != header . PacketNumber {
2017-07-28 01:11:56 +03:00
return nil , errors . New ( "packetPacker BUG: Peeked and Popped packet numbers do not match" )
}
2018-02-17 08:29:53 +03:00
p . hasSentPacket = true
2017-07-28 01:11:56 +03:00
return raw , nil
}
func ( p * packetPacker ) canSendData ( encLevel protocol . EncryptionLevel ) bool {
if p . perspective == protocol . PerspectiveClient {
return encLevel >= protocol . EncryptionSecure
}
return encLevel == protocol . EncryptionForwardSecure
2017-05-27 22:30:11 +03:00
}
2018-02-17 08:29:53 +03:00
func ( p * packetPacker ) SetOmitConnectionID ( ) {
p . omitConnectionID = true
}
2018-03-26 07:37:41 +03:00
2018-09-03 00:18:54 +03:00
func ( p * packetPacker ) ChangeDestConnectionID ( connID protocol . ConnectionID ) {
p . destConnID = connID
}
2018-03-26 07:37:41 +03:00
func ( p * packetPacker ) SetMaxPacketSize ( size protocol . ByteCount ) {
p . maxPacketSize = utils . MinByteCount ( p . maxPacketSize , size )
}