mirror of
https://github.com/caddyserver/caddy.git
synced 2025-01-16 07:46:28 +03:00
vendor: update quic-go to v0.10.1 (#2431)
This commit is contained in:
parent
8ab447e615
commit
917534e35e
33 changed files with 957 additions and 485 deletions
38
vendor/github.com/lucas-clemente/quic-go/client.go
generated
vendored
38
vendor/github.com/lucas-clemente/quic-go/client.go
generated
vendored
|
@ -25,12 +25,9 @@ type client struct {
|
|||
// If it is started with Dial, we take a packet conn as a parameter.
|
||||
createdPacketConn bool
|
||||
|
||||
hostname string
|
||||
|
||||
packetHandlers packetHandlerManager
|
||||
|
||||
token []byte
|
||||
numRetries int
|
||||
token []byte
|
||||
|
||||
versionNegotiated bool // has the server accepted our version
|
||||
receivedVersionNegotiationPacket bool
|
||||
|
@ -159,13 +156,12 @@ func newClient(
|
|||
closeCallback func(protocol.ConnectionID),
|
||||
createdPacketConn bool,
|
||||
) (*client, error) {
|
||||
var hostname string
|
||||
if tlsConf != nil {
|
||||
hostname = tlsConf.ServerName
|
||||
if tlsConf == nil {
|
||||
tlsConf = &tls.Config{}
|
||||
}
|
||||
if hostname == "" {
|
||||
if tlsConf.ServerName == "" {
|
||||
var err error
|
||||
hostname, _, err = net.SplitHostPort(host)
|
||||
tlsConf.ServerName, _, err = net.SplitHostPort(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -186,7 +182,6 @@ func newClient(
|
|||
c := &client{
|
||||
conn: &conn{pconn: pconn, currentAddr: remoteAddr},
|
||||
createdPacketConn: createdPacketConn,
|
||||
hostname: hostname,
|
||||
tlsConf: tlsConf,
|
||||
config: config,
|
||||
version: config.Versions[0],
|
||||
|
@ -286,7 +281,7 @@ func (c *client) generateConnectionIDs() error {
|
|||
}
|
||||
|
||||
func (c *client) dial(ctx context.Context) error {
|
||||
c.logger.Infof("Starting new connection to %s (%s -> %s), source connection ID %s, destination connection ID %s, version %s", c.hostname, c.conn.LocalAddr(), c.conn.RemoteAddr(), c.srcConnID, c.destConnID, c.version)
|
||||
c.logger.Infof("Starting new connection to %s (%s -> %s), source connection ID %s, destination connection ID %s, version %s", c.tlsConf.ServerName, c.conn.LocalAddr(), c.conn.RemoteAddr(), c.srcConnID, c.destConnID, c.version)
|
||||
|
||||
var err error
|
||||
if c.version.UsesTLS() {
|
||||
|
@ -324,7 +319,6 @@ func (c *client) dialTLS(ctx context.Context) error {
|
|||
return err
|
||||
}
|
||||
mintConf.ExtensionHandler = extHandler
|
||||
mintConf.ServerName = c.hostname
|
||||
c.mintConf = mintConf
|
||||
|
||||
if err := c.createNewTLSSession(extHandler.GetPeerParams(), c.version); err != nil {
|
||||
|
@ -483,19 +477,18 @@ func (c *client) handleVersionNegotiationPacket(hdr *wire.Header) error {
|
|||
func (c *client) handleRetryPacket(hdr *wire.Header) {
|
||||
c.logger.Debugf("<- Received Retry")
|
||||
hdr.Log(c.logger)
|
||||
// A server that performs multiple retries must use a source connection ID of at least 8 bytes.
|
||||
// Only a server that won't send additional Retries can use shorter connection IDs.
|
||||
if hdr.OrigDestConnectionID.Len() < protocol.MinConnectionIDLenInitial {
|
||||
c.logger.Debugf("Received a Retry with a too short Original Destination Connection ID: %d bytes, must have at least %d bytes.", hdr.OrigDestConnectionID.Len(), protocol.MinConnectionIDLenInitial)
|
||||
return
|
||||
}
|
||||
if !hdr.OrigDestConnectionID.Equal(c.destConnID) {
|
||||
c.logger.Debugf("Received spoofed Retry. Original Destination Connection ID: %s, expected: %s", hdr.OrigDestConnectionID, c.destConnID)
|
||||
c.logger.Debugf("Ignoring spoofed Retry. Original Destination Connection ID: %s, expected: %s", hdr.OrigDestConnectionID, c.destConnID)
|
||||
return
|
||||
}
|
||||
c.numRetries++
|
||||
if c.numRetries > protocol.MaxRetries {
|
||||
c.session.destroy(qerr.CryptoTooManyRejects)
|
||||
if hdr.SrcConnectionID.Equal(c.destConnID) {
|
||||
c.logger.Debugf("Ignoring Retry, since the server didn't change the Source Connection ID.")
|
||||
return
|
||||
}
|
||||
// If a token is already set, this means that we already received a Retry from the server.
|
||||
// Ignore this Retry packet.
|
||||
if len(c.token) > 0 {
|
||||
c.logger.Debugf("Ignoring Retry, since a Retry was already received.")
|
||||
return
|
||||
}
|
||||
c.destConnID = hdr.SrcConnectionID
|
||||
|
@ -513,7 +506,6 @@ func (c *client) createNewGQUICSession() error {
|
|||
sess, err := newClientSession(
|
||||
c.conn,
|
||||
runner,
|
||||
c.hostname,
|
||||
c.version,
|
||||
c.destConnID,
|
||||
c.srcConnID,
|
||||
|
|
1
vendor/github.com/lucas-clemente/quic-go/crypto_stream.go
generated
vendored
1
vendor/github.com/lucas-clemente/quic-go/crypto_stream.go
generated
vendored
|
@ -13,6 +13,7 @@ type cryptoStream interface {
|
|||
io.Reader
|
||||
io.Writer
|
||||
handleStreamFrame(*wire.StreamFrame) error
|
||||
hasData() bool
|
||||
popStreamFrame(protocol.ByteCount) (*wire.StreamFrame, bool)
|
||||
closeForShutdown(error)
|
||||
setReadOffset(protocol.ByteCount)
|
||||
|
|
9
vendor/github.com/lucas-clemente/quic-go/example/client/main.go
generated
vendored
9
vendor/github.com/lucas-clemente/quic-go/example/client/main.go
generated
vendored
|
@ -16,6 +16,7 @@ import (
|
|||
func main() {
|
||||
verbose := flag.Bool("v", false, "verbose")
|
||||
tls := flag.Bool("tls", false, "activate support for IETF QUIC (work in progress)")
|
||||
quiet := flag.Bool("q", false, "don't print the data")
|
||||
flag.Parse()
|
||||
urls := flag.Args()
|
||||
|
||||
|
@ -57,8 +58,12 @@ func main() {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
logger.Infof("Request Body:")
|
||||
logger.Infof("%s", body.Bytes())
|
||||
if *quiet {
|
||||
logger.Infof("Request Body: %d bytes", body.Len())
|
||||
} else {
|
||||
logger.Infof("Request Body:")
|
||||
logger.Infof("%s", body.Bytes())
|
||||
}
|
||||
wg.Done()
|
||||
}(addr)
|
||||
}
|
||||
|
|
|
@ -7,23 +7,25 @@ import (
|
|||
"github.com/lucas-clemente/quic-go/internal/wire"
|
||||
)
|
||||
|
||||
type streamFramer struct {
|
||||
type framer struct {
|
||||
streamGetter streamGetter
|
||||
cryptoStream cryptoStream
|
||||
version protocol.VersionNumber
|
||||
|
||||
streamQueueMutex sync.Mutex
|
||||
activeStreams map[protocol.StreamID]struct{}
|
||||
streamQueue []protocol.StreamID
|
||||
hasCryptoStreamData bool
|
||||
streamQueueMutex sync.Mutex
|
||||
activeStreams map[protocol.StreamID]struct{}
|
||||
streamQueue []protocol.StreamID
|
||||
|
||||
controlFrameMutex sync.Mutex
|
||||
controlFrames []wire.Frame
|
||||
}
|
||||
|
||||
func newStreamFramer(
|
||||
func newFramer(
|
||||
cryptoStream cryptoStream,
|
||||
streamGetter streamGetter,
|
||||
v protocol.VersionNumber,
|
||||
) *streamFramer {
|
||||
return &streamFramer{
|
||||
) *framer {
|
||||
return &framer{
|
||||
streamGetter: streamGetter,
|
||||
cryptoStream: cryptoStream,
|
||||
activeStreams: make(map[protocol.StreamID]struct{}),
|
||||
|
@ -31,13 +33,32 @@ func newStreamFramer(
|
|||
}
|
||||
}
|
||||
|
||||
func (f *streamFramer) AddActiveStream(id protocol.StreamID) {
|
||||
if id == f.version.CryptoStreamID() { // the crypto stream is handled separately
|
||||
f.streamQueueMutex.Lock()
|
||||
f.hasCryptoStreamData = true
|
||||
f.streamQueueMutex.Unlock()
|
||||
return
|
||||
func (f *framer) QueueControlFrame(frame wire.Frame) {
|
||||
f.controlFrameMutex.Lock()
|
||||
f.controlFrames = append(f.controlFrames, frame)
|
||||
f.controlFrameMutex.Unlock()
|
||||
}
|
||||
|
||||
func (f *framer) AppendControlFrames(frames []wire.Frame, maxLen protocol.ByteCount) ([]wire.Frame, protocol.ByteCount) {
|
||||
var length protocol.ByteCount
|
||||
f.controlFrameMutex.Lock()
|
||||
for len(f.controlFrames) > 0 {
|
||||
frame := f.controlFrames[len(f.controlFrames)-1]
|
||||
frameLen := frame.Length(f.version)
|
||||
if length+frameLen > maxLen {
|
||||
break
|
||||
}
|
||||
frames = append(frames, frame)
|
||||
length += frameLen
|
||||
f.controlFrames = f.controlFrames[:len(f.controlFrames)-1]
|
||||
}
|
||||
f.controlFrameMutex.Unlock()
|
||||
return frames, length
|
||||
}
|
||||
|
||||
// AddActiveStream adds a stream that has data to write.
|
||||
// It should not be used for the crypto stream.
|
||||
func (f *framer) AddActiveStream(id protocol.StreamID) {
|
||||
f.streamQueueMutex.Lock()
|
||||
if _, ok := f.activeStreams[id]; !ok {
|
||||
f.streamQueue = append(f.streamQueue, id)
|
||||
|
@ -46,29 +67,13 @@ func (f *streamFramer) AddActiveStream(id protocol.StreamID) {
|
|||
f.streamQueueMutex.Unlock()
|
||||
}
|
||||
|
||||
func (f *streamFramer) HasCryptoStreamData() bool {
|
||||
f.streamQueueMutex.Lock()
|
||||
hasCryptoStreamData := f.hasCryptoStreamData
|
||||
f.streamQueueMutex.Unlock()
|
||||
return hasCryptoStreamData
|
||||
}
|
||||
|
||||
func (f *streamFramer) PopCryptoStreamFrame(maxLen protocol.ByteCount) *wire.StreamFrame {
|
||||
f.streamQueueMutex.Lock()
|
||||
frame, hasMoreData := f.cryptoStream.popStreamFrame(maxLen)
|
||||
f.hasCryptoStreamData = hasMoreData
|
||||
f.streamQueueMutex.Unlock()
|
||||
return frame
|
||||
}
|
||||
|
||||
func (f *streamFramer) PopStreamFrames(maxTotalLen protocol.ByteCount) []*wire.StreamFrame {
|
||||
var currentLen protocol.ByteCount
|
||||
var frames []*wire.StreamFrame
|
||||
func (f *framer) AppendStreamFrames(frames []wire.Frame, maxLen protocol.ByteCount) []wire.Frame {
|
||||
var length protocol.ByteCount
|
||||
f.streamQueueMutex.Lock()
|
||||
// pop STREAM frames, until less than MinStreamFrameSize bytes are left in the packet
|
||||
numActiveStreams := len(f.streamQueue)
|
||||
for i := 0; i < numActiveStreams; i++ {
|
||||
if maxTotalLen-currentLen < protocol.MinStreamFrameSize {
|
||||
if maxLen-length < protocol.MinStreamFrameSize {
|
||||
break
|
||||
}
|
||||
id := f.streamQueue[0]
|
||||
|
@ -81,7 +86,7 @@ func (f *streamFramer) PopStreamFrames(maxTotalLen protocol.ByteCount) []*wire.S
|
|||
delete(f.activeStreams, id)
|
||||
continue
|
||||
}
|
||||
frame, hasMoreData := str.popStreamFrame(maxTotalLen - currentLen)
|
||||
frame, hasMoreData := str.popStreamFrame(maxLen - length)
|
||||
if hasMoreData { // put the stream back in the queue (at the end)
|
||||
f.streamQueue = append(f.streamQueue, id)
|
||||
} else { // no more data to send. Stream is not active any more
|
||||
|
@ -91,7 +96,7 @@ func (f *streamFramer) PopStreamFrames(maxTotalLen protocol.ByteCount) []*wire.S
|
|||
continue
|
||||
}
|
||||
frames = append(frames, frame)
|
||||
currentLen += frame.Length(f.version)
|
||||
length += frame.Length(f.version)
|
||||
}
|
||||
f.streamQueueMutex.Unlock()
|
||||
return frames
|
2
vendor/github.com/lucas-clemente/quic-go/h2quic/server.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/h2quic/server.go
generated
vendored
|
@ -141,7 +141,7 @@ func (s *Server) handleHeaderStream(session streamCreator) {
|
|||
// In this case, the session has already logged the error, so we don't
|
||||
// need to log it again.
|
||||
errorCode := qerr.InternalError
|
||||
if qerr, ok := err.(*qerr.QuicError); !ok {
|
||||
if qerr, ok := err.(*qerr.QuicError); ok {
|
||||
errorCode = qerr.ErrorCode
|
||||
s.logger.Errorf("error handling h2 request: %s", err.Error())
|
||||
}
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/interface.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/interface.go
generated
vendored
|
@ -23,8 +23,6 @@ const (
|
|||
VersionGQUIC43 = protocol.Version43
|
||||
// VersionGQUIC44 is gQUIC version 44.
|
||||
VersionGQUIC44 = protocol.Version44
|
||||
// VersionMilestone0_10_0 uses TLS
|
||||
VersionMilestone0_10_0 = protocol.VersionMilestone0_10_0
|
||||
)
|
||||
|
||||
// A Cookie can be used to verify the ownership of the client address.
|
||||
|
|
3
vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_handler.go
generated
vendored
3
vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_handler.go
generated
vendored
|
@ -148,6 +148,7 @@ func (h *sentPacketHandler) SentPacketsAsRetransmission(packets []*Packet, retra
|
|||
|
||||
func (h *sentPacketHandler) sentPacketImpl(packet *Packet) bool /* isRetransmittable */ {
|
||||
for p := h.lastSentPacketNumber + 1; p < packet.PacketNumber; p++ {
|
||||
h.logger.Debugf("Skipping packet number %#x", p)
|
||||
h.skippedPackets = append(h.skippedPackets, p)
|
||||
if len(h.skippedPackets) > protocol.MaxTrackedSkippedPackets {
|
||||
h.skippedPackets = h.skippedPackets[1:]
|
||||
|
@ -633,7 +634,7 @@ func (h *sentPacketHandler) computeRTOTimeout() time.Duration {
|
|||
}
|
||||
rto = utils.MaxDuration(rto, minRTOTimeout)
|
||||
// Exponential backoff
|
||||
rto = rto << h.rtoCount
|
||||
rto <<= h.rtoCount
|
||||
return utils.MinDuration(rto, maxRTOTimeout)
|
||||
}
|
||||
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/internal/congestion/cubic_sender.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/internal/congestion/cubic_sender.go
generated
vendored
|
@ -193,7 +193,7 @@ func (c *cubicSender) OnPacketLost(
|
|||
if c.congestionWindow >= 2*c.initialCongestionWindow {
|
||||
c.minSlowStartExitWindow = c.congestionWindow / 2
|
||||
}
|
||||
c.congestionWindow = c.congestionWindow - protocol.DefaultTCPMSS
|
||||
c.congestionWindow -= protocol.DefaultTCPMSS
|
||||
} else if c.reno {
|
||||
c.congestionWindow = protocol.ByteCount(float32(c.congestionWindow) * c.RenoBeta())
|
||||
} else {
|
||||
|
|
15
vendor/github.com/lucas-clemente/quic-go/internal/crypto/cert_chain.go
generated
vendored
15
vendor/github.com/lucas-clemente/quic-go/internal/crypto/cert_chain.go
generated
vendored
|
@ -56,8 +56,7 @@ func (c *certChain) GetLeafCert(sni string) ([]byte, error) {
|
|||
}
|
||||
|
||||
func (c *certChain) getCertForSNI(sni string) (*tls.Certificate, error) {
|
||||
conf := c.config
|
||||
conf, err := maybeGetConfigForClient(conf, sni)
|
||||
conf, err := maybeGetConfigForClient(c.config, sni)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -107,7 +106,13 @@ func maybeGetConfigForClient(c *tls.Config, sni string) (*tls.Config, error) {
|
|||
if c.GetConfigForClient == nil {
|
||||
return c, nil
|
||||
}
|
||||
return c.GetConfigForClient(&tls.ClientHelloInfo{
|
||||
ServerName: sni,
|
||||
})
|
||||
confForClient, err := c.GetConfigForClient(&tls.ClientHelloInfo{ServerName: sni})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// if GetConfigForClient returns nil, use the original config
|
||||
if confForClient == nil {
|
||||
return c, nil
|
||||
}
|
||||
return confForClient, nil
|
||||
}
|
||||
|
|
56
vendor/github.com/lucas-clemente/quic-go/internal/crypto/hkdf.go
generated
vendored
Normal file
56
vendor/github.com/lucas-clemente/quic-go/internal/crypto/hkdf.go
generated
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/hmac"
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
// copied from https://github.com/cloudflare/tls-tris/blob/master/hkdf.go
|
||||
func hkdfExtract(hash crypto.Hash, secret, salt []byte) []byte {
|
||||
if salt == nil {
|
||||
salt = make([]byte, hash.Size())
|
||||
}
|
||||
if secret == nil {
|
||||
secret = make([]byte, hash.Size())
|
||||
}
|
||||
extractor := hmac.New(hash.New, salt)
|
||||
extractor.Write(secret)
|
||||
return extractor.Sum(nil)
|
||||
}
|
||||
|
||||
// copied from https://github.com/cloudflare/tls-tris/blob/master/hkdf.go
|
||||
func hkdfExpand(hash crypto.Hash, prk, info []byte, l int) []byte {
|
||||
var (
|
||||
expander = hmac.New(hash.New, prk)
|
||||
res = make([]byte, l)
|
||||
counter = byte(1)
|
||||
prev []byte
|
||||
)
|
||||
|
||||
if l > 255*expander.Size() {
|
||||
panic("hkdf: requested too much output")
|
||||
}
|
||||
|
||||
p := res
|
||||
for len(p) > 0 {
|
||||
expander.Reset()
|
||||
expander.Write(prev)
|
||||
expander.Write(info)
|
||||
expander.Write([]byte{counter})
|
||||
prev = expander.Sum(prev[:0])
|
||||
counter++
|
||||
n := copy(p, prev)
|
||||
p = p[n:]
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func qhkdfExpand(secret []byte, label string, length int) []byte {
|
||||
qlabel := make([]byte, 2+1+5+len(label))
|
||||
binary.BigEndian.PutUint16(qlabel[0:2], uint16(length))
|
||||
qlabel[2] = uint8(5 + len(label))
|
||||
copy(qlabel[3:], []byte("QUIC "+label))
|
||||
return hkdfExpand(crypto.SHA256, secret, qlabel, length)
|
||||
}
|
11
vendor/github.com/lucas-clemente/quic-go/internal/crypto/key_derivation.go
generated
vendored
11
vendor/github.com/lucas-clemente/quic-go/internal/crypto/key_derivation.go
generated
vendored
|
@ -1,9 +1,6 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/bifurcation/mint"
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
)
|
||||
|
@ -19,14 +16,6 @@ type TLSExporter interface {
|
|||
ComputeExporter(label string, context []byte, keyLength int) ([]byte, error)
|
||||
}
|
||||
|
||||
func qhkdfExpand(secret []byte, label string, length int) []byte {
|
||||
qlabel := make([]byte, 2+1+5+len(label))
|
||||
binary.BigEndian.PutUint16(qlabel[0:2], uint16(length))
|
||||
qlabel[2] = uint8(5 + len(label))
|
||||
copy(qlabel[3:], []byte("QUIC "+label))
|
||||
return mint.HkdfExpand(crypto.SHA256, secret, qlabel, length)
|
||||
}
|
||||
|
||||
// DeriveAESKeys derives the AES keys and creates a matching AES-GCM AEAD instance
|
||||
func DeriveAESKeys(tls TLSExporter, pers protocol.Perspective) (AEAD, error) {
|
||||
var myLabel, otherLabel string
|
||||
|
|
3
vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_aesgcm.go
generated
vendored
3
vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_aesgcm.go
generated
vendored
|
@ -3,7 +3,6 @@ package crypto
|
|||
import (
|
||||
"crypto"
|
||||
|
||||
"github.com/bifurcation/mint"
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
)
|
||||
|
||||
|
@ -28,7 +27,7 @@ func newNullAEADAESGCM(connectionID protocol.ConnectionID, pers protocol.Perspec
|
|||
}
|
||||
|
||||
func computeSecrets(connID protocol.ConnectionID) (clientSecret, serverSecret []byte) {
|
||||
handshakeSecret := mint.HkdfExtract(crypto.SHA256, quicVersion1Salt, connID)
|
||||
handshakeSecret := hkdfExtract(crypto.SHA256, connID, quicVersion1Salt)
|
||||
clientSecret = qhkdfExpand(handshakeSecret, "client hs", crypto.SHA256.Size())
|
||||
serverSecret = qhkdfExpand(handshakeSecret, "server hs", crypto.SHA256.Size())
|
||||
return
|
||||
|
|
7
vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_client.go
generated
vendored
7
vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_client.go
generated
vendored
|
@ -69,10 +69,9 @@ var (
|
|||
// NewCryptoSetupClient creates a new CryptoSetup instance for a client
|
||||
func NewCryptoSetupClient(
|
||||
cryptoStream io.ReadWriter,
|
||||
hostname string,
|
||||
connID protocol.ConnectionID,
|
||||
version protocol.VersionNumber,
|
||||
tlsConfig *tls.Config,
|
||||
tlsConf *tls.Config,
|
||||
params *TransportParameters,
|
||||
paramsChan chan<- TransportParameters,
|
||||
handshakeEvent chan<- struct{},
|
||||
|
@ -87,10 +86,10 @@ func NewCryptoSetupClient(
|
|||
divNonceChan := make(chan struct{})
|
||||
cs := &cryptoSetupClient{
|
||||
cryptoStream: cryptoStream,
|
||||
hostname: hostname,
|
||||
hostname: tlsConf.ServerName,
|
||||
connID: connID,
|
||||
version: version,
|
||||
certManager: crypto.NewCertManager(tlsConfig),
|
||||
certManager: crypto.NewCertManager(tlsConf),
|
||||
params: params,
|
||||
keyDerivation: crypto.DeriveQuicCryptoAESKeys,
|
||||
nullAEAD: nullAEAD,
|
||||
|
|
22
vendor/github.com/lucas-clemente/quic-go/internal/handshake/transport_parameters.go
generated
vendored
22
vendor/github.com/lucas-clemente/quic-go/internal/handshake/transport_parameters.go
generated
vendored
|
@ -3,8 +3,8 @@ package handshake
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
|
@ -97,16 +97,18 @@ func (p *TransportParameters) getHelloMap() map[Tag][]byte {
|
|||
}
|
||||
|
||||
func (p *TransportParameters) unmarshal(data []byte) error {
|
||||
var foundIdleTimeout bool
|
||||
// needed to check that every parameter is only sent at most once
|
||||
var parameterIDs []transportParameterID
|
||||
|
||||
for len(data) >= 4 {
|
||||
paramID := binary.BigEndian.Uint16(data[:2])
|
||||
paramID := transportParameterID(binary.BigEndian.Uint16(data[:2]))
|
||||
paramLen := int(binary.BigEndian.Uint16(data[2:4]))
|
||||
data = data[4:]
|
||||
if len(data) < paramLen {
|
||||
return fmt.Errorf("remaining length (%d) smaller than parameter length (%d)", len(data), paramLen)
|
||||
}
|
||||
switch transportParameterID(paramID) {
|
||||
parameterIDs = append(parameterIDs, paramID)
|
||||
switch paramID {
|
||||
case initialMaxStreamDataParameterID:
|
||||
if paramLen != 4 {
|
||||
return fmt.Errorf("wrong length for initial_max_stream_data: %d (expected 4)", paramLen)
|
||||
|
@ -128,7 +130,6 @@ func (p *TransportParameters) unmarshal(data []byte) error {
|
|||
}
|
||||
p.MaxUniStreams = binary.BigEndian.Uint16(data[:2])
|
||||
case idleTimeoutParameterID:
|
||||
foundIdleTimeout = true
|
||||
if paramLen != 2 {
|
||||
return fmt.Errorf("wrong length for idle_timeout: %d (expected 2)", paramLen)
|
||||
}
|
||||
|
@ -156,12 +157,17 @@ func (p *TransportParameters) unmarshal(data []byte) error {
|
|||
data = data[paramLen:]
|
||||
}
|
||||
|
||||
// check that every transport parameter was sent at most once
|
||||
sort.Slice(parameterIDs, func(i, j int) bool { return parameterIDs[i] < parameterIDs[j] })
|
||||
for i := 0; i < len(parameterIDs)-1; i++ {
|
||||
if parameterIDs[i] == parameterIDs[i+1] {
|
||||
return fmt.Errorf("received duplicate transport parameter %#x", parameterIDs[i])
|
||||
}
|
||||
}
|
||||
|
||||
if len(data) != 0 {
|
||||
return fmt.Errorf("should have read all data. Still have %d bytes", len(data))
|
||||
}
|
||||
if !foundIdleTimeout {
|
||||
return errors.New("missing parameter")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
1
vendor/github.com/lucas-clemente/quic-go/internal/mocks/mockgen.go
generated
vendored
1
vendor/github.com/lucas-clemente/quic-go/internal/mocks/mockgen.go
generated
vendored
|
@ -1,6 +1,7 @@
|
|||
package mocks
|
||||
|
||||
//go:generate sh -c "../mockgen_internal.sh mocks tls_extension_handler.go github.com/lucas-clemente/quic-go/internal/handshake TLSExtensionHandler"
|
||||
//go:generate sh -c "../mockgen_internal.sh mocks sealer.go github.com/lucas-clemente/quic-go/internal/handshake Sealer"
|
||||
//go:generate sh -c "../mockgen_internal.sh mocks stream_flow_controller.go github.com/lucas-clemente/quic-go/internal/flowcontrol StreamFlowController"
|
||||
//go:generate sh -c "../mockgen_internal.sh mockackhandler ackhandler/sent_packet_handler.go github.com/lucas-clemente/quic-go/internal/ackhandler SentPacketHandler"
|
||||
//go:generate sh -c "../mockgen_internal.sh mockackhandler ackhandler/received_packet_handler.go github.com/lucas-clemente/quic-go/internal/ackhandler ReceivedPacketHandler"
|
||||
|
|
59
vendor/github.com/lucas-clemente/quic-go/internal/mocks/sealer.go
generated
vendored
Normal file
59
vendor/github.com/lucas-clemente/quic-go/internal/mocks/sealer.go
generated
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/lucas-clemente/quic-go/internal/handshake (interfaces: Sealer)
|
||||
|
||||
// Package mocks is a generated GoMock package.
|
||||
package mocks
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
protocol "github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
)
|
||||
|
||||
// MockSealer is a mock of Sealer interface
|
||||
type MockSealer struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockSealerMockRecorder
|
||||
}
|
||||
|
||||
// MockSealerMockRecorder is the mock recorder for MockSealer
|
||||
type MockSealerMockRecorder struct {
|
||||
mock *MockSealer
|
||||
}
|
||||
|
||||
// NewMockSealer creates a new mock instance
|
||||
func NewMockSealer(ctrl *gomock.Controller) *MockSealer {
|
||||
mock := &MockSealer{ctrl: ctrl}
|
||||
mock.recorder = &MockSealerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
func (m *MockSealer) EXPECT() *MockSealerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Overhead mocks base method
|
||||
func (m *MockSealer) Overhead() int {
|
||||
ret := m.ctrl.Call(m, "Overhead")
|
||||
ret0, _ := ret[0].(int)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Overhead indicates an expected call of Overhead
|
||||
func (mr *MockSealerMockRecorder) Overhead() *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Overhead", reflect.TypeOf((*MockSealer)(nil).Overhead))
|
||||
}
|
||||
|
||||
// Seal mocks base method
|
||||
func (m *MockSealer) Seal(arg0, arg1 []byte, arg2 protocol.PacketNumber, arg3 []byte) []byte {
|
||||
ret := m.ctrl.Call(m, "Seal", arg0, arg1, arg2, arg3)
|
||||
ret0, _ := ret[0].([]byte)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Seal indicates an expected call of Seal
|
||||
func (mr *MockSealerMockRecorder) Seal(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Seal", reflect.TypeOf((*MockSealer)(nil).Seal), arg0, arg1, arg2, arg3)
|
||||
}
|
3
vendor/github.com/lucas-clemente/quic-go/internal/protocol/server_parameters.go
generated
vendored
3
vendor/github.com/lucas-clemente/quic-go/internal/protocol/server_parameters.go
generated
vendored
|
@ -149,6 +149,3 @@ const MinPacingDelay time.Duration = 100 * time.Microsecond
|
|||
// DefaultConnectionIDLength is the connection ID length that is used for multiplexed connections
|
||||
// if no other value is configured.
|
||||
const DefaultConnectionIDLength = 4
|
||||
|
||||
// MaxRetries is the maximum number of Retries a client will do before failing the connection.
|
||||
const MaxRetries = 3
|
||||
|
|
6
vendor/github.com/lucas-clemente/quic-go/internal/protocol/version.go
generated
vendored
6
vendor/github.com/lucas-clemente/quic-go/internal/protocol/version.go
generated
vendored
|
@ -24,8 +24,6 @@ const (
|
|||
VersionTLS VersionNumber = 101
|
||||
VersionWhatever VersionNumber = 0 // for when the version doesn't matter
|
||||
VersionUnknown VersionNumber = math.MaxUint32
|
||||
|
||||
VersionMilestone0_10_0 VersionNumber = 0x51474f02
|
||||
)
|
||||
|
||||
// SupportedVersions lists the versions that the server supports
|
||||
|
@ -38,7 +36,7 @@ var SupportedVersions = []VersionNumber{
|
|||
|
||||
// IsValidVersion says if the version is known to quic-go
|
||||
func IsValidVersion(v VersionNumber) bool {
|
||||
return v == VersionTLS || v == VersionMilestone0_10_0 || IsSupportedVersion(SupportedVersions, v)
|
||||
return v == VersionTLS || IsSupportedVersion(SupportedVersions, v)
|
||||
}
|
||||
|
||||
// UsesTLS says if this QUIC version uses TLS 1.3 for the handshake
|
||||
|
@ -52,8 +50,6 @@ func (vn VersionNumber) String() string {
|
|||
return "whatever"
|
||||
case VersionUnknown:
|
||||
return "unknown"
|
||||
case VersionMilestone0_10_0:
|
||||
return "quic-go Milestone 0.10.0"
|
||||
case VersionTLS:
|
||||
return "TLS dev version (WIP)"
|
||||
default:
|
||||
|
|
11
vendor/github.com/lucas-clemente/quic-go/internal/utils/timer.go
generated
vendored
11
vendor/github.com/lucas-clemente/quic-go/internal/utils/timer.go
generated
vendored
|
@ -1,6 +1,9 @@
|
|||
package utils
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
// A Timer wrapper that behaves correctly when resetting
|
||||
type Timer struct {
|
||||
|
@ -11,7 +14,7 @@ type Timer struct {
|
|||
|
||||
// NewTimer creates a new timer that is not set
|
||||
func NewTimer() *Timer {
|
||||
return &Timer{t: time.NewTimer(0)}
|
||||
return &Timer{t: time.NewTimer(time.Duration(math.MaxInt64))}
|
||||
}
|
||||
|
||||
// Chan returns the channel of the wrapped timer
|
||||
|
@ -31,7 +34,9 @@ func (t *Timer) Reset(deadline time.Time) {
|
|||
if !t.t.Stop() && !t.read {
|
||||
<-t.t.C
|
||||
}
|
||||
t.t.Reset(time.Until(deadline))
|
||||
if !deadline.IsZero() {
|
||||
t.t.Reset(time.Until(deadline))
|
||||
}
|
||||
|
||||
t.read = false
|
||||
t.deadline = deadline
|
||||
|
|
34
vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_frame.go
generated
vendored
34
vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_frame.go
generated
vendored
|
@ -19,23 +19,17 @@ type AckFrame struct {
|
|||
DelayTime time.Duration
|
||||
}
|
||||
|
||||
func parseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, error) {
|
||||
return parseAckOrAckEcnFrame(r, false, version)
|
||||
}
|
||||
|
||||
func parseAckEcnFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, error) {
|
||||
return parseAckOrAckEcnFrame(r, true, version)
|
||||
}
|
||||
|
||||
// parseAckFrame reads an ACK frame
|
||||
func parseAckOrAckEcnFrame(r *bytes.Reader, ecn bool, version protocol.VersionNumber) (*AckFrame, error) {
|
||||
func parseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, error) {
|
||||
if !version.UsesIETFFrameFormat() {
|
||||
return parseAckFrameLegacy(r, version)
|
||||
}
|
||||
|
||||
if _, err := r.ReadByte(); err != nil {
|
||||
typeByte, err := r.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ecn := typeByte&0x1 > 0
|
||||
|
||||
frame := &AckFrame{}
|
||||
|
||||
|
@ -50,14 +44,6 @@ func parseAckOrAckEcnFrame(r *bytes.Reader, ecn bool, version protocol.VersionNu
|
|||
}
|
||||
frame.DelayTime = time.Duration(delay*1<<ackDelayExponent) * time.Microsecond
|
||||
|
||||
if ecn {
|
||||
for i := 0; i < 3; i++ {
|
||||
if _, err := utils.ReadVarInt(r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
numBlocks, err := utils.ReadVarInt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -103,6 +89,16 @@ func parseAckOrAckEcnFrame(r *bytes.Reader, ecn bool, version protocol.VersionNu
|
|||
if !frame.validateAckRanges() {
|
||||
return nil, errInvalidAckRanges
|
||||
}
|
||||
|
||||
// parse (and skip) the ECN section
|
||||
if ecn {
|
||||
for i := 0; i < 3; i++ {
|
||||
if _, err := utils.ReadVarInt(r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
|
@ -112,7 +108,7 @@ func (f *AckFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error
|
|||
return f.writeLegacy(b, version)
|
||||
}
|
||||
|
||||
b.WriteByte(0x0d)
|
||||
b.WriteByte(0x1a)
|
||||
utils.WriteVarInt(b, uint64(f.LargestAcked()))
|
||||
utils.WriteVarInt(b, encodeAckDelay(f.DelayTime))
|
||||
|
||||
|
|
9
vendor/github.com/lucas-clemente/quic-go/internal/wire/frame_parser.go
generated
vendored
9
vendor/github.com/lucas-clemente/quic-go/internal/wire/frame_parser.go
generated
vendored
|
@ -86,11 +86,6 @@ func parseIETFFrame(r *bytes.Reader, typeByte byte, v protocol.VersionNumber) (F
|
|||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidFrameData, err.Error())
|
||||
}
|
||||
case 0xd:
|
||||
frame, err = parseAckFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidAckData, err.Error())
|
||||
}
|
||||
case 0xe:
|
||||
frame, err = parsePathChallengeFrame(r, v)
|
||||
if err != nil {
|
||||
|
@ -101,8 +96,8 @@ func parseIETFFrame(r *bytes.Reader, typeByte byte, v protocol.VersionNumber) (F
|
|||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidFrameData, err.Error())
|
||||
}
|
||||
case 0x1a:
|
||||
frame, err = parseAckEcnFrame(r, v)
|
||||
case 0x1a, 0x1b:
|
||||
frame, err = parseAckFrame(r, v)
|
||||
if err != nil {
|
||||
err = qerr.Error(qerr.InvalidAckData, err.Error())
|
||||
}
|
||||
|
|
5
vendor/github.com/lucas-clemente/quic-go/mockgen.go
generated
vendored
5
vendor/github.com/lucas-clemente/quic-go/mockgen.go
generated
vendored
|
@ -5,10 +5,13 @@ package quic
|
|||
//go:generate sh -c "./mockgen_private.sh quic mock_send_stream_internal_test.go github.com/lucas-clemente/quic-go sendStreamI"
|
||||
//go:generate sh -c "./mockgen_private.sh quic mock_stream_sender_test.go github.com/lucas-clemente/quic-go streamSender"
|
||||
//go:generate sh -c "./mockgen_private.sh quic mock_stream_getter_test.go github.com/lucas-clemente/quic-go streamGetter"
|
||||
//go:generate sh -c "./mockgen_private.sh quic mock_stream_frame_source_test.go github.com/lucas-clemente/quic-go streamFrameSource"
|
||||
//go:generate sh -c "./mockgen_private.sh quic mock_frame_source_test.go github.com/lucas-clemente/quic-go frameSource"
|
||||
//go:generate sh -c "./mockgen_private.sh quic mock_ack_frame_source_test.go github.com/lucas-clemente/quic-go ackFrameSource"
|
||||
//go:generate sh -c "./mockgen_private.sh quic mock_crypto_stream_test.go github.com/lucas-clemente/quic-go cryptoStream"
|
||||
//go:generate sh -c "./mockgen_private.sh quic mock_stream_manager_test.go github.com/lucas-clemente/quic-go streamManager"
|
||||
//go:generate sh -c "./mockgen_private.sh quic mock_sealing_manager_test.go github.com/lucas-clemente/quic-go sealingManager"
|
||||
//go:generate sh -c "./mockgen_private.sh quic mock_unpacker_test.go github.com/lucas-clemente/quic-go unpacker"
|
||||
//go:generate sh -c "./mockgen_private.sh quic mock_packer_test.go github.com/lucas-clemente/quic-go packer"
|
||||
//go:generate sh -c "./mockgen_private.sh quic mock_quic_aead_test.go github.com/lucas-clemente/quic-go quicAEAD"
|
||||
//go:generate sh -c "./mockgen_private.sh quic mock_gquic_aead_test.go github.com/lucas-clemente/quic-go gQUICAEAD"
|
||||
//go:generate sh -c "./mockgen_private.sh quic mock_session_runner_test.go github.com/lucas-clemente/quic-go sessionRunner"
|
||||
|
|
23
vendor/github.com/lucas-clemente/quic-go/packet_number_generator.go
generated
vendored
23
vendor/github.com/lucas-clemente/quic-go/packet_number_generator.go
generated
vendored
|
@ -18,10 +18,12 @@ type packetNumberGenerator struct {
|
|||
}
|
||||
|
||||
func newPacketNumberGenerator(initial, averagePeriod protocol.PacketNumber) *packetNumberGenerator {
|
||||
return &packetNumberGenerator{
|
||||
g := &packetNumberGenerator{
|
||||
next: initial,
|
||||
averagePeriod: averagePeriod,
|
||||
}
|
||||
g.generateNewSkip()
|
||||
return g
|
||||
}
|
||||
|
||||
func (p *packetNumberGenerator) Peek() protocol.PacketNumber {
|
||||
|
@ -42,28 +44,19 @@ func (p *packetNumberGenerator) Pop() protocol.PacketNumber {
|
|||
return next
|
||||
}
|
||||
|
||||
func (p *packetNumberGenerator) generateNewSkip() error {
|
||||
num, err := p.getRandomNumber()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *packetNumberGenerator) generateNewSkip() {
|
||||
num := p.getRandomNumber()
|
||||
skip := protocol.PacketNumber(num) * (p.averagePeriod - 1) / (math.MaxUint16 / 2)
|
||||
// make sure that there are never two consecutive packet numbers that are skipped
|
||||
p.nextToSkip = p.next + 2 + skip
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getRandomNumber() generates a cryptographically secure random number between 0 and MaxUint16 (= 65535)
|
||||
// The expectation value is 65535/2
|
||||
func (p *packetNumberGenerator) getRandomNumber() (uint16, error) {
|
||||
func (p *packetNumberGenerator) getRandomNumber() uint16 {
|
||||
b := make([]byte, 2)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rand.Read(b) // ignore the error here
|
||||
|
||||
num := uint16(b[0])<<8 + uint16(b[1])
|
||||
return num, nil
|
||||
return num
|
||||
}
|
||||
|
|
336
vendor/github.com/lucas-clemente/quic-go/packet_packer.go
generated
vendored
336
vendor/github.com/lucas-clemente/quic-go/packet_packer.go
generated
vendored
|
@ -5,7 +5,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/ackhandler"
|
||||
|
@ -15,6 +14,16 @@ import (
|
|||
"github.com/lucas-clemente/quic-go/internal/wire"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
type packedPacket struct {
|
||||
header *wire.Header
|
||||
raw []byte
|
||||
|
@ -33,16 +42,37 @@ func (p *packedPacket) ToAckHandlerPacket() *ackhandler.Packet {
|
|||
}
|
||||
}
|
||||
|
||||
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 sealingManager interface {
|
||||
GetSealer() (protocol.EncryptionLevel, handshake.Sealer)
|
||||
GetSealerForCryptoStream() (protocol.EncryptionLevel, handshake.Sealer)
|
||||
GetSealerWithEncryptionLevel(protocol.EncryptionLevel) (handshake.Sealer, error)
|
||||
}
|
||||
|
||||
type streamFrameSource interface {
|
||||
HasCryptoStreamData() bool
|
||||
PopCryptoStreamFrame(protocol.ByteCount) *wire.StreamFrame
|
||||
PopStreamFrames(protocol.ByteCount) []*wire.StreamFrame
|
||||
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
|
||||
GetStopWaitingFrame(bool) *wire.StopWaitingFrame
|
||||
}
|
||||
|
||||
type packetPacker struct {
|
||||
|
@ -53,24 +83,21 @@ type packetPacker struct {
|
|||
version protocol.VersionNumber
|
||||
cryptoSetup sealingManager
|
||||
|
||||
token []byte
|
||||
divNonce []byte
|
||||
token []byte
|
||||
|
||||
packetNumberGenerator *packetNumberGenerator
|
||||
getPacketNumberLen func(protocol.PacketNumber) protocol.PacketNumberLen
|
||||
streams streamFrameSource
|
||||
cryptoStream cryptoStream
|
||||
framer frameSource
|
||||
acks ackFrameSource
|
||||
|
||||
controlFrameMutex sync.Mutex
|
||||
controlFrames []wire.Frame
|
||||
|
||||
stopWaiting *wire.StopWaitingFrame
|
||||
ackFrame *wire.AckFrame
|
||||
omitConnectionID bool
|
||||
maxPacketSize protocol.ByteCount
|
||||
hasSentPacket bool // has the packetPacker already sent a packet
|
||||
numNonRetransmittableAcks int
|
||||
}
|
||||
|
||||
var _ packer = &packetPacker{}
|
||||
|
||||
func newPacketPacker(
|
||||
destConnID protocol.ConnectionID,
|
||||
srcConnID protocol.ConnectionID,
|
||||
|
@ -78,37 +105,26 @@ func newPacketPacker(
|
|||
getPacketNumberLen func(protocol.PacketNumber) protocol.PacketNumberLen,
|
||||
remoteAddr net.Addr, // only used for determining the max packet size
|
||||
token []byte,
|
||||
divNonce []byte,
|
||||
cryptoStream cryptoStream,
|
||||
cryptoSetup sealingManager,
|
||||
streamFramer streamFrameSource,
|
||||
framer frameSource,
|
||||
acks ackFrameSource,
|
||||
perspective protocol.Perspective,
|
||||
version protocol.VersionNumber,
|
||||
) *packetPacker {
|
||||
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
|
||||
}
|
||||
}
|
||||
return &packetPacker{
|
||||
cryptoStream: cryptoStream,
|
||||
cryptoSetup: cryptoSetup,
|
||||
divNonce: divNonce,
|
||||
token: token,
|
||||
destConnID: destConnID,
|
||||
srcConnID: srcConnID,
|
||||
perspective: perspective,
|
||||
version: version,
|
||||
streams: streamFramer,
|
||||
framer: framer,
|
||||
acks: acks,
|
||||
getPacketNumberLen: getPacketNumberLen,
|
||||
packetNumberGenerator: newPacketNumberGenerator(initialPacketNumber, protocol.SkipPacketAveragePeriodLength),
|
||||
maxPacketSize: maxPacketSize,
|
||||
maxPacketSize: getMaxPacketSize(remoteAddr),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,20 +142,14 @@ func (p *packetPacker) PackConnectionClose(ccf *wire.ConnectionCloseFrame) (*pac
|
|||
}, err
|
||||
}
|
||||
|
||||
func (p *packetPacker) PackAckPacket() (*packedPacket, error) {
|
||||
if p.ackFrame == nil {
|
||||
return nil, errors.New("packet packer BUG: no ack frame queued")
|
||||
func (p *packetPacker) MaybePackAckPacket() (*packedPacket, error) {
|
||||
ack := p.acks.GetAckFrame()
|
||||
if ack == nil {
|
||||
return nil, nil
|
||||
}
|
||||
encLevel, sealer := p.cryptoSetup.GetSealer()
|
||||
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
|
||||
frames = append(frames, p.stopWaiting)
|
||||
p.stopWaiting = nil
|
||||
}
|
||||
p.ackFrame = nil
|
||||
frames := []wire.Frame{ack}
|
||||
raw, err := p.writeAndSealPacket(header, frames, sealer)
|
||||
return &packedPacket{
|
||||
header: header,
|
||||
|
@ -173,7 +183,7 @@ func (p *packetPacker) PackRetransmission(packet *ackhandler.Packet) ([]*packedP
|
|||
encLevel, sealer := p.cryptoSetup.GetSealer()
|
||||
for len(controlFrames) > 0 || len(streamFrames) > 0 {
|
||||
var frames []wire.Frame
|
||||
var payloadLength protocol.ByteCount
|
||||
var length protocol.ByteCount
|
||||
|
||||
header := p.getHeader(encLevel)
|
||||
headerLength, err := header.GetLength(p.version)
|
||||
|
@ -182,48 +192,23 @@ func (p *packetPacker) PackRetransmission(packet *ackhandler.Packet) ([]*packedP
|
|||
}
|
||||
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 {
|
||||
frameLen := frame.Length(p.version)
|
||||
if length+frameLen > maxSize {
|
||||
break
|
||||
}
|
||||
payloadLength += length
|
||||
length += frameLen
|
||||
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
|
||||
for len(streamFrames) > 0 && length+protocol.MinStreamFrameSize < maxSize {
|
||||
frame := streamFrames[0]
|
||||
frame.DataLenPresent = false
|
||||
frameToAdd := frame
|
||||
|
||||
sf, err := frame.MaybeSplitOffFrame(maxSize-payloadLength, p.version)
|
||||
sf, err := frame.MaybeSplitOffFrame(maxSize-length, p.version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -232,7 +217,8 @@ func (p *packetPacker) PackRetransmission(packet *ackhandler.Packet) ([]*packedP
|
|||
} else {
|
||||
streamFrames = streamFrames[1:]
|
||||
}
|
||||
payloadLength += frameToAdd.Length(p.version)
|
||||
frame.DataLenPresent = true
|
||||
length += frameToAdd.Length(p.version)
|
||||
frames = append(frames, frameToAdd)
|
||||
}
|
||||
if sf, ok := frames[len(frames)-1].(*wire.StreamFrame); ok {
|
||||
|
@ -249,7 +235,6 @@ func (p *packetPacker) PackRetransmission(packet *ackhandler.Packet) ([]*packedP
|
|||
encryptionLevel: encLevel,
|
||||
})
|
||||
}
|
||||
p.stopWaiting = nil
|
||||
return packets, nil
|
||||
}
|
||||
|
||||
|
@ -265,24 +250,11 @@ func (p *packetPacker) packHandshakeRetransmission(packet *ackhandler.Packet) (*
|
|||
}
|
||||
header := p.getHeader(packet.EncryptionLevel)
|
||||
header.Type = packet.PacketType
|
||||
var frames []wire.Frame
|
||||
if p.version.UsesStopWaitingFrames() { // for gQUIC: pack a STOP_WAITING first
|
||||
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
|
||||
}
|
||||
raw, err := p.writeAndSealPacket(header, frames, sealer)
|
||||
raw, err := p.writeAndSealPacket(header, packet.Frames, sealer)
|
||||
return &packedPacket{
|
||||
header: header,
|
||||
raw: raw,
|
||||
frames: frames,
|
||||
frames: packet.Frames,
|
||||
encryptionLevel: packet.EncryptionLevel,
|
||||
}, err
|
||||
}
|
||||
|
@ -290,13 +262,16 @@ func (p *packetPacker) packHandshakeRetransmission(packet *ackhandler.Packet) (*
|
|||
// 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) {
|
||||
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
|
||||
packet, err := p.maybePackCryptoPacket()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if hasCryptoStreamFrame {
|
||||
return p.packCryptoPacket()
|
||||
if packet != nil {
|
||||
return packet, nil
|
||||
}
|
||||
// if this is the first packet to be send, make sure it contains stream data
|
||||
if !p.hasSentPacket && packet == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
encLevel, sealer := p.cryptoSetup.GetSealer()
|
||||
|
@ -306,54 +281,45 @@ func (p *packetPacker) PackPacket() (*packedPacket, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if p.stopWaiting != nil {
|
||||
p.stopWaiting.PacketNumber = header.PacketNumber
|
||||
p.stopWaiting.PacketNumberLen = header.PacketNumberLen
|
||||
}
|
||||
|
||||
maxSize := p.maxPacketSize - protocol.ByteCount(sealer.Overhead()) - headerLength
|
||||
payloadFrames, err := p.composeNextPacket(maxSize, p.canSendData(encLevel))
|
||||
frames, err := p.composeNextPacket(maxSize, p.canSendData(encLevel))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check if we have enough frames to send
|
||||
if len(payloadFrames) == 0 {
|
||||
if len(frames) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
// Don't send out packets that only contain a StopWaitingFrame
|
||||
if len(payloadFrames) == 1 && p.stopWaiting != nil {
|
||||
return nil, nil
|
||||
}
|
||||
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 {
|
||||
// check if this packet only contains an ACK
|
||||
if !ackhandler.HasRetransmittableFrames(frames) {
|
||||
if p.numNonRetransmittableAcks >= protocol.MaxNonRetransmittableAcks {
|
||||
frames = append(frames, &wire.PingFrame{})
|
||||
p.numNonRetransmittableAcks = 0
|
||||
} else {
|
||||
p.numNonRetransmittableAcks++
|
||||
}
|
||||
} else {
|
||||
p.numNonRetransmittableAcks = 0
|
||||
}
|
||||
p.stopWaiting = nil
|
||||
p.ackFrame = nil
|
||||
|
||||
raw, err := p.writeAndSealPacket(header, payloadFrames, sealer)
|
||||
raw, err := p.writeAndSealPacket(header, frames, sealer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &packedPacket{
|
||||
header: header,
|
||||
raw: raw,
|
||||
frames: payloadFrames,
|
||||
frames: frames,
|
||||
encryptionLevel: encLevel,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *packetPacker) packCryptoPacket() (*packedPacket, error) {
|
||||
func (p *packetPacker) maybePackCryptoPacket() (*packedPacket, error) {
|
||||
if !p.cryptoStream.hasData() {
|
||||
return nil, nil
|
||||
}
|
||||
encLevel, sealer := p.cryptoSetup.GetSealerForCryptoStream()
|
||||
header := p.getHeader(encLevel)
|
||||
headerLength, err := header.GetLength(p.version)
|
||||
|
@ -361,7 +327,7 @@ func (p *packetPacker) packCryptoPacket() (*packedPacket, error) {
|
|||
return nil, err
|
||||
}
|
||||
maxLen := p.maxPacketSize - protocol.ByteCount(sealer.Overhead()) - protocol.NonForwardSecurePacketSizeReduction - headerLength
|
||||
sf := p.streams.PopCryptoStreamFrame(maxLen)
|
||||
sf, _ := p.cryptoStream.popStreamFrame(maxLen)
|
||||
sf.DataLenPresent = false
|
||||
frames := []wire.Frame{sf}
|
||||
raw, err := p.writeAndSealPacket(header, frames, sealer)
|
||||
|
@ -380,74 +346,37 @@ func (p *packetPacker) composeNextPacket(
|
|||
maxFrameSize protocol.ByteCount,
|
||||
canSendStreamFrames bool,
|
||||
) ([]wire.Frame, error) {
|
||||
var payloadLength protocol.ByteCount
|
||||
var payloadFrames []wire.Frame
|
||||
var length protocol.ByteCount
|
||||
var frames []wire.Frame
|
||||
|
||||
// STOP_WAITING and ACK will always fit
|
||||
if p.ackFrame != nil { // ACKs need to go first, so that the sentPacketHandler will recognize them
|
||||
payloadFrames = append(payloadFrames, p.ackFrame)
|
||||
l := p.ackFrame.Length(p.version)
|
||||
payloadLength += l
|
||||
}
|
||||
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)
|
||||
// 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)
|
||||
}
|
||||
|
||||
p.controlFrameMutex.Lock()
|
||||
for len(p.controlFrames) > 0 {
|
||||
frame := p.controlFrames[len(p.controlFrames)-1]
|
||||
length := frame.Length(p.version)
|
||||
if payloadLength+length > maxFrameSize {
|
||||
break
|
||||
}
|
||||
payloadFrames = append(payloadFrames, frame)
|
||||
payloadLength += length
|
||||
p.controlFrames = p.controlFrames[:len(p.controlFrames)-1]
|
||||
}
|
||||
p.controlFrameMutex.Unlock()
|
||||
|
||||
if payloadLength > maxFrameSize {
|
||||
return nil, fmt.Errorf("Packet Packer BUG: packet payload (%d) too large (%d)", payloadLength, maxFrameSize)
|
||||
}
|
||||
var lengthAdded protocol.ByteCount
|
||||
frames, lengthAdded = p.framer.AppendControlFrames(frames, maxFrameSize-length)
|
||||
length += lengthAdded
|
||||
|
||||
if !canSendStreamFrames {
|
||||
return payloadFrames, nil
|
||||
return frames, nil
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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
|
||||
// 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() {
|
||||
maxFrameSize++
|
||||
} else {
|
||||
maxFrameSize += 2
|
||||
}
|
||||
// the length is encoded to either 1 or 2 bytes
|
||||
maxFrameSize++
|
||||
|
||||
fs := p.streams.PopStreamFrames(maxFrameSize - payloadLength)
|
||||
if len(fs) != 0 {
|
||||
fs[len(fs)-1].DataLenPresent = false
|
||||
}
|
||||
|
||||
for _, f := range fs {
|
||||
payloadFrames = append(payloadFrames, f)
|
||||
}
|
||||
return payloadFrames, nil
|
||||
}
|
||||
|
||||
func (p *packetPacker) QueueControlFrame(frame wire.Frame) {
|
||||
switch f := frame.(type) {
|
||||
case *wire.StopWaitingFrame:
|
||||
p.stopWaiting = f
|
||||
case *wire.AckFrame:
|
||||
p.ackFrame = f
|
||||
default:
|
||||
p.controlFrameMutex.Lock()
|
||||
p.controlFrames = append(p.controlFrames, f)
|
||||
p.controlFrameMutex.Unlock()
|
||||
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
|
||||
}
|
||||
}
|
||||
return frames, nil
|
||||
}
|
||||
|
||||
func (p *packetPacker) getHeader(encLevel protocol.EncryptionLevel) *wire.Header {
|
||||
|
@ -455,17 +384,15 @@ func (p *packetPacker) getHeader(encLevel protocol.EncryptionLevel) *wire.Header
|
|||
packetNumberLen := p.getPacketNumberLen(pnum)
|
||||
|
||||
header := &wire.Header{
|
||||
PacketNumber: pnum,
|
||||
PacketNumberLen: packetNumberLen,
|
||||
Version: p.version,
|
||||
PacketNumber: pnum,
|
||||
PacketNumberLen: packetNumberLen,
|
||||
Version: p.version,
|
||||
DestConnectionID: p.destConnID,
|
||||
}
|
||||
|
||||
if p.version.UsesIETFHeaderFormat() && encLevel != protocol.EncryptionForwardSecure {
|
||||
if encLevel != protocol.EncryptionForwardSecure {
|
||||
header.IsLongHeader = true
|
||||
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
|
||||
|
@ -477,24 +404,12 @@ func (p *packetPacker) getHeader(encLevel protocol.EncryptionLevel) *wire.Header
|
|||
}
|
||||
}
|
||||
|
||||
if !p.omitConnectionID || encLevel != protocol.EncryptionForwardSecure {
|
||||
header.DestConnectionID = p.destConnID
|
||||
}
|
||||
if !p.version.UsesTLS() {
|
||||
if p.perspective == protocol.PerspectiveServer && encLevel == protocol.EncryptionSecure {
|
||||
header.Type = protocol.PacketType0RTT
|
||||
header.DiversificationNonce = p.divNonce
|
||||
}
|
||||
if p.perspective == protocol.PerspectiveClient && encLevel != protocol.EncryptionForwardSecure {
|
||||
header.VersionFlag = true
|
||||
}
|
||||
}
|
||||
return header
|
||||
}
|
||||
|
||||
func (p *packetPacker) writeAndSealPacket(
|
||||
header *wire.Header,
|
||||
payloadFrames []wire.Frame,
|
||||
frames []wire.Frame,
|
||||
sealer handshake.Sealer,
|
||||
) ([]byte, error) {
|
||||
raw := *getPacketBuffer()
|
||||
|
@ -507,7 +422,7 @@ func (p *packetPacker) writeAndSealPacket(
|
|||
header.PayloadLen = protocol.ByteCount(protocol.MinInitialPacketSize) - headerLen
|
||||
} else {
|
||||
payloadLen := protocol.ByteCount(sealer.Overhead())
|
||||
for _, frame := range payloadFrames {
|
||||
for _, frame := range frames {
|
||||
payloadLen += frame.Length(p.version)
|
||||
}
|
||||
header.PayloadLen = payloadLen
|
||||
|
@ -521,18 +436,17 @@ func (p *packetPacker) writeAndSealPacket(
|
|||
|
||||
// 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]
|
||||
lastFrame := frames[len(frames)-1]
|
||||
if sf, ok := lastFrame.(*wire.StreamFrame); ok {
|
||||
sf.DataLenPresent = true
|
||||
}
|
||||
}
|
||||
for _, frame := range payloadFrames {
|
||||
for _, frame := range frames {
|
||||
if err := frame.Write(buffer, p.version); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// 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 this is an Initial packet, we need to pad it to fulfill the minimum size requirement
|
||||
if header.Type == protocol.PacketTypeInitial {
|
||||
paddingLen := protocol.MinInitialPacketSize - sealer.Overhead() - buffer.Len()
|
||||
if paddingLen > 0 {
|
||||
|
@ -563,14 +477,12 @@ func (p *packetPacker) canSendData(encLevel protocol.EncryptionLevel) bool {
|
|||
return encLevel == protocol.EncryptionForwardSecure
|
||||
}
|
||||
|
||||
func (p *packetPacker) SetOmitConnectionID() {
|
||||
p.omitConnectionID = true
|
||||
}
|
||||
|
||||
func (p *packetPacker) ChangeDestConnectionID(connID protocol.ConnectionID) {
|
||||
p.destConnID = connID
|
||||
}
|
||||
|
||||
func (p *packetPacker) SetMaxPacketSize(size protocol.ByteCount) {
|
||||
p.maxPacketSize = utils.MinByteCount(p.maxPacketSize, size)
|
||||
func (p *packetPacker) HandleTransportParameters(params *handshake.TransportParameters) {
|
||||
if params.MaxPacketSize != 0 {
|
||||
p.maxPacketSize = utils.MinByteCount(p.maxPacketSize, params.MaxPacketSize)
|
||||
}
|
||||
}
|
||||
|
|
455
vendor/github.com/lucas-clemente/quic-go/packet_packer_legacy.go
generated
vendored
Normal file
455
vendor/github.com/lucas-clemente/quic-go/packet_packer_legacy.go
generated
vendored
Normal file
|
@ -0,0 +1,455 @@
|
|||
package quic
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"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/wire"
|
||||
)
|
||||
|
||||
// sentAndReceivedPacketManager is only needed until STOP_WAITING is removed
|
||||
type sentAndReceivedPacketManager struct {
|
||||
ackhandler.SentPacketHandler
|
||||
ackhandler.ReceivedPacketHandler
|
||||
}
|
||||
|
||||
var _ ackFrameSource = &sentAndReceivedPacketManager{}
|
||||
|
||||
type packetPackerLegacy struct {
|
||||
destConnID protocol.ConnectionID
|
||||
srcConnID protocol.ConnectionID
|
||||
|
||||
perspective protocol.Perspective
|
||||
version protocol.VersionNumber
|
||||
cryptoSetup sealingManager
|
||||
|
||||
divNonce []byte
|
||||
|
||||
packetNumberGenerator *packetNumberGenerator
|
||||
getPacketNumberLen func(protocol.PacketNumber) protocol.PacketNumberLen
|
||||
cryptoStream cryptoStream
|
||||
framer frameSource
|
||||
acks ackFrameSource
|
||||
|
||||
omitConnectionID bool
|
||||
maxPacketSize protocol.ByteCount
|
||||
hasSentPacket bool // has the packetPacker already sent a packet
|
||||
numNonRetransmittableAcks int
|
||||
}
|
||||
|
||||
var _ packer = &packetPackerLegacy{}
|
||||
|
||||
func newPacketPackerLegacy(
|
||||
destConnID protocol.ConnectionID,
|
||||
srcConnID protocol.ConnectionID,
|
||||
getPacketNumberLen func(protocol.PacketNumber) protocol.PacketNumberLen,
|
||||
remoteAddr net.Addr, // only used for determining the max packet size
|
||||
divNonce []byte,
|
||||
cryptoStream cryptoStream,
|
||||
cryptoSetup sealingManager,
|
||||
framer frameSource,
|
||||
acks ackFrameSource,
|
||||
perspective protocol.Perspective,
|
||||
version protocol.VersionNumber,
|
||||
) *packetPackerLegacy {
|
||||
return &packetPackerLegacy{
|
||||
cryptoStream: cryptoStream,
|
||||
cryptoSetup: cryptoSetup,
|
||||
divNonce: divNonce,
|
||||
destConnID: destConnID,
|
||||
srcConnID: srcConnID,
|
||||
perspective: perspective,
|
||||
version: version,
|
||||
framer: framer,
|
||||
acks: acks,
|
||||
getPacketNumberLen: getPacketNumberLen,
|
||||
packetNumberGenerator: newPacketNumberGenerator(1, protocol.SkipPacketAveragePeriodLength),
|
||||
maxPacketSize: getMaxPacketSize(remoteAddr),
|
||||
}
|
||||
}
|
||||
|
||||
// PackConnectionClose packs a packet that ONLY contains a ConnectionCloseFrame
|
||||
func (p *packetPackerLegacy) 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
|
||||
}
|
||||
|
||||
func (p *packetPackerLegacy) MaybePackAckPacket() (*packedPacket, error) {
|
||||
ack := p.acks.GetAckFrame()
|
||||
if ack == nil {
|
||||
return nil, nil
|
||||
}
|
||||
encLevel, sealer := p.cryptoSetup.GetSealer()
|
||||
header := p.getHeader(encLevel)
|
||||
frames := []wire.Frame{ack}
|
||||
// add a STOP_WAITING frame, if necessary
|
||||
if p.version.UsesStopWaitingFrames() {
|
||||
if swf := p.acks.GetStopWaitingFrame(false); swf != nil {
|
||||
swf.PacketNumber = header.PacketNumber
|
||||
swf.PacketNumberLen = header.PacketNumberLen
|
||||
frames = append(frames, swf)
|
||||
}
|
||||
}
|
||||
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 *packetPackerLegacy) 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()
|
||||
var swf *wire.StopWaitingFrame
|
||||
// add a STOP_WAITING for *every* retransmission
|
||||
if p.version.UsesStopWaitingFrames() {
|
||||
swf = p.acks.GetStopWaitingFrame(true)
|
||||
}
|
||||
for len(controlFrames) > 0 || len(streamFrames) > 0 {
|
||||
var frames []wire.Frame
|
||||
var length protocol.ByteCount
|
||||
|
||||
header := p.getHeader(encLevel)
|
||||
headerLength, err := header.GetLength(p.version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
maxSize := p.maxPacketSize - protocol.ByteCount(sealer.Overhead()) - headerLength
|
||||
|
||||
if p.version.UsesStopWaitingFrames() {
|
||||
// create a new STOP_WAIITNG Frame, since we might need to send more than one packet as a retransmission
|
||||
stopWaitingFrame := &wire.StopWaitingFrame{
|
||||
LeastUnacked: swf.LeastUnacked,
|
||||
PacketNumber: header.PacketNumber,
|
||||
PacketNumberLen: header.PacketNumberLen,
|
||||
}
|
||||
length += stopWaitingFrame.Length(p.version)
|
||||
frames = append(frames, stopWaitingFrame)
|
||||
}
|
||||
|
||||
for len(controlFrames) > 0 {
|
||||
frame := controlFrames[0]
|
||||
frameLen := frame.Length(p.version)
|
||||
if length+frameLen > maxSize {
|
||||
break
|
||||
}
|
||||
length += frameLen
|
||||
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
|
||||
maxSize += 2
|
||||
|
||||
for len(streamFrames) > 0 && length+protocol.MinStreamFrameSize < maxSize {
|
||||
frame := streamFrames[0]
|
||||
frameToAdd := frame
|
||||
|
||||
sf, err := frame.MaybeSplitOffFrame(maxSize-length, p.version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if sf != nil {
|
||||
frameToAdd = sf
|
||||
} else {
|
||||
streamFrames = streamFrames[1:]
|
||||
}
|
||||
length += 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,
|
||||
})
|
||||
}
|
||||
return packets, nil
|
||||
}
|
||||
|
||||
// packHandshakeRetransmission retransmits a handshake packet, that was sent with less than forward-secure encryption
|
||||
func (p *packetPackerLegacy) 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
|
||||
var frames []wire.Frame
|
||||
if p.version.UsesStopWaitingFrames() { // pack a STOP_WAITING first
|
||||
swf := p.acks.GetStopWaitingFrame(true)
|
||||
swf.PacketNumber = header.PacketNumber
|
||||
swf.PacketNumberLen = header.PacketNumberLen
|
||||
frames = append([]wire.Frame{swf}, packet.Frames...)
|
||||
} else {
|
||||
frames = packet.Frames
|
||||
}
|
||||
raw, err := p.writeAndSealPacket(header, frames, sealer)
|
||||
return &packedPacket{
|
||||
header: header,
|
||||
raw: raw,
|
||||
frames: frames,
|
||||
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 *packetPackerLegacy) PackPacket() (*packedPacket, error) {
|
||||
packet, err := p.maybePackCryptoPacket()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if packet != nil {
|
||||
return packet, nil
|
||||
}
|
||||
// if this is the first packet to be send, make sure it contains stream data
|
||||
if !p.hasSentPacket && packet == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
encLevel, sealer := p.cryptoSetup.GetSealer()
|
||||
|
||||
header := p.getHeader(encLevel)
|
||||
headerLength, err := header.GetLength(p.version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
maxSize := p.maxPacketSize - protocol.ByteCount(sealer.Overhead()) - headerLength
|
||||
frames, err := p.composeNextPacket(header, maxSize, p.canSendData(encLevel))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check if we have enough frames to send
|
||||
if len(frames) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
// check if this packet only contains an ACK (and maybe a STOP_WAITING)
|
||||
if !ackhandler.HasRetransmittableFrames(frames) {
|
||||
if p.numNonRetransmittableAcks >= protocol.MaxNonRetransmittableAcks {
|
||||
frames = append(frames, &wire.PingFrame{})
|
||||
p.numNonRetransmittableAcks = 0
|
||||
} else {
|
||||
p.numNonRetransmittableAcks++
|
||||
}
|
||||
} else {
|
||||
p.numNonRetransmittableAcks = 0
|
||||
}
|
||||
|
||||
raw, err := p.writeAndSealPacket(header, frames, sealer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &packedPacket{
|
||||
header: header,
|
||||
raw: raw,
|
||||
frames: frames,
|
||||
encryptionLevel: encLevel,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *packetPackerLegacy) maybePackCryptoPacket() (*packedPacket, error) {
|
||||
if !p.cryptoStream.hasData() {
|
||||
return nil, nil
|
||||
}
|
||||
encLevel, sealer := p.cryptoSetup.GetSealerForCryptoStream()
|
||||
header := p.getHeader(encLevel)
|
||||
headerLength, err := header.GetLength(p.version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
maxLen := p.maxPacketSize - protocol.ByteCount(sealer.Overhead()) - protocol.NonForwardSecurePacketSizeReduction - headerLength
|
||||
sf, _ := p.cryptoStream.popStreamFrame(maxLen)
|
||||
sf.DataLenPresent = false
|
||||
frames := []wire.Frame{sf}
|
||||
raw, err := p.writeAndSealPacket(header, frames, sealer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &packedPacket{
|
||||
header: header,
|
||||
raw: raw,
|
||||
frames: frames,
|
||||
encryptionLevel: encLevel,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *packetPackerLegacy) composeNextPacket(
|
||||
header *wire.Header, // only needed to fill in the STOP_WAITING frame
|
||||
maxFrameSize protocol.ByteCount,
|
||||
canSendStreamFrames bool,
|
||||
) ([]wire.Frame, error) {
|
||||
var length protocol.ByteCount
|
||||
var frames []wire.Frame
|
||||
|
||||
// STOP_WAITING and ACK will always fit
|
||||
// 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)
|
||||
// add a STOP_WAITING, for gQUIC
|
||||
if p.version.UsesStopWaitingFrames() {
|
||||
if swf := p.acks.GetStopWaitingFrame(false); swf != nil {
|
||||
swf.PacketNumber = header.PacketNumber
|
||||
swf.PacketNumberLen = header.PacketNumberLen
|
||||
frames = append(frames, swf)
|
||||
length += swf.Length(p.version)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var lengthAdded protocol.ByteCount
|
||||
frames, lengthAdded = p.framer.AppendControlFrames(frames, maxFrameSize-length)
|
||||
length += lengthAdded
|
||||
|
||||
if !canSendStreamFrames {
|
||||
return frames, nil
|
||||
}
|
||||
|
||||
// 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
|
||||
maxFrameSize += 2
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
return frames, nil
|
||||
}
|
||||
|
||||
func (p *packetPackerLegacy) getHeader(encLevel protocol.EncryptionLevel) *wire.Header {
|
||||
pnum := p.packetNumberGenerator.Peek()
|
||||
packetNumberLen := p.getPacketNumberLen(pnum)
|
||||
|
||||
header := &wire.Header{
|
||||
PacketNumber: pnum,
|
||||
PacketNumberLen: packetNumberLen,
|
||||
Version: p.version,
|
||||
}
|
||||
|
||||
if p.version.UsesIETFHeaderFormat() && encLevel != protocol.EncryptionForwardSecure {
|
||||
header.IsLongHeader = true
|
||||
header.SrcConnectionID = p.srcConnID
|
||||
header.PacketNumberLen = protocol.PacketNumberLen4
|
||||
if !p.hasSentPacket && p.perspective == protocol.PerspectiveClient {
|
||||
header.Type = protocol.PacketTypeInitial
|
||||
} else {
|
||||
header.Type = protocol.PacketTypeHandshake
|
||||
}
|
||||
}
|
||||
|
||||
if !p.omitConnectionID || encLevel != protocol.EncryptionForwardSecure {
|
||||
header.DestConnectionID = p.destConnID
|
||||
}
|
||||
if p.perspective == protocol.PerspectiveServer && encLevel == protocol.EncryptionSecure {
|
||||
header.Type = protocol.PacketType0RTT
|
||||
header.DiversificationNonce = p.divNonce
|
||||
}
|
||||
if p.perspective == protocol.PerspectiveClient && encLevel != protocol.EncryptionForwardSecure {
|
||||
header.VersionFlag = true
|
||||
}
|
||||
return header
|
||||
}
|
||||
|
||||
func (p *packetPackerLegacy) writeAndSealPacket(
|
||||
header *wire.Header,
|
||||
frames []wire.Frame,
|
||||
sealer handshake.Sealer,
|
||||
) ([]byte, error) {
|
||||
raw := *getPacketBuffer()
|
||||
buffer := bytes.NewBuffer(raw[:0])
|
||||
|
||||
if err := header.Write(buffer, p.perspective, p.version); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payloadStartIndex := buffer.Len()
|
||||
|
||||
for _, frame := range frames {
|
||||
if err := frame.Write(buffer, p.version); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
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()]
|
||||
|
||||
num := p.packetNumberGenerator.Pop()
|
||||
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 *packetPackerLegacy) canSendData(encLevel protocol.EncryptionLevel) bool {
|
||||
if p.perspective == protocol.PerspectiveClient {
|
||||
return encLevel >= protocol.EncryptionSecure
|
||||
}
|
||||
return encLevel == protocol.EncryptionForwardSecure
|
||||
}
|
||||
|
||||
func (p *packetPackerLegacy) ChangeDestConnectionID(connID protocol.ConnectionID) {
|
||||
panic("changing connection IDs not supported by gQUIC")
|
||||
}
|
||||
|
||||
func (p *packetPackerLegacy) HandleTransportParameters(params *handshake.TransportParameters) {
|
||||
p.omitConnectionID = params.OmitConnectionID
|
||||
}
|
33
vendor/github.com/lucas-clemente/quic-go/receive_stream.go
generated
vendored
33
vendor/github.com/lucas-clemente/quic-go/receive_stream.go
generated
vendored
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/lucas-clemente/quic-go/internal/flowcontrol"
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/internal/wire"
|
||||
)
|
||||
|
||||
|
@ -43,8 +44,8 @@ type receiveStream struct {
|
|||
canceledRead bool // set when CancelRead() is called
|
||||
resetRemotely bool // set when HandleRstStreamFrame() is called
|
||||
|
||||
readChan chan struct{}
|
||||
readDeadline time.Time
|
||||
readChan chan struct{}
|
||||
deadline time.Time
|
||||
|
||||
flowController flowcontrol.StreamFlowController
|
||||
version protocol.VersionNumber
|
||||
|
@ -108,6 +109,7 @@ func (s *receiveStream) readImpl(p []byte) (bool /*stream completed */, int, err
|
|||
return false, bytesRead, s.closeForShutdownErr
|
||||
}
|
||||
|
||||
var deadlineTimer *utils.Timer
|
||||
for {
|
||||
// Stop waiting on errors
|
||||
if s.closedForShutdown {
|
||||
|
@ -120,9 +122,15 @@ func (s *receiveStream) readImpl(p []byte) (bool /*stream completed */, int, err
|
|||
return false, bytesRead, s.resetRemotelyErr
|
||||
}
|
||||
|
||||
deadline := s.readDeadline
|
||||
if !deadline.IsZero() && !time.Now().Before(deadline) {
|
||||
return false, bytesRead, errDeadline
|
||||
deadline := s.deadline
|
||||
if !deadline.IsZero() {
|
||||
if !time.Now().Before(deadline) {
|
||||
return false, bytesRead, errDeadline
|
||||
}
|
||||
if deadlineTimer == nil {
|
||||
deadlineTimer = utils.NewTimer()
|
||||
}
|
||||
deadlineTimer.Reset(deadline)
|
||||
}
|
||||
|
||||
if s.currentFrame != nil || s.currentFrameIsLast {
|
||||
|
@ -135,7 +143,8 @@ func (s *receiveStream) readImpl(p []byte) (bool /*stream completed */, int, err
|
|||
} else {
|
||||
select {
|
||||
case <-s.readChan:
|
||||
case <-time.After(time.Until(deadline)):
|
||||
case <-deadlineTimer.Chan():
|
||||
deadlineTimer.SetRead()
|
||||
}
|
||||
}
|
||||
s.mutex.Lock()
|
||||
|
@ -164,7 +173,9 @@ func (s *receiveStream) readImpl(p []byte) (bool /*stream completed */, int, err
|
|||
s.flowController.AddBytesRead(protocol.ByteCount(m))
|
||||
}
|
||||
// increase the flow control window, if necessary
|
||||
s.flowController.MaybeQueueWindowUpdate()
|
||||
if s.streamID != s.version.CryptoStreamID() {
|
||||
s.flowController.MaybeQueueWindowUpdate()
|
||||
}
|
||||
|
||||
if s.readPosInFrame >= len(s.currentFrame) && s.currentFrameIsLast {
|
||||
s.finRead = true
|
||||
|
@ -270,13 +281,9 @@ func (s *receiveStream) onClose(offset protocol.ByteCount) {
|
|||
|
||||
func (s *receiveStream) SetReadDeadline(t time.Time) error {
|
||||
s.mutex.Lock()
|
||||
oldDeadline := s.readDeadline
|
||||
s.readDeadline = t
|
||||
s.deadline = t
|
||||
s.mutex.Unlock()
|
||||
// if the new deadline is before the currently set deadline, wake up Read()
|
||||
if t.Before(oldDeadline) {
|
||||
s.signalRead()
|
||||
}
|
||||
s.signalRead()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
84
vendor/github.com/lucas-clemente/quic-go/send_stream.go
generated
vendored
84
vendor/github.com/lucas-clemente/quic-go/send_stream.go
generated
vendored
|
@ -15,6 +15,7 @@ import (
|
|||
type sendStreamI interface {
|
||||
SendStream
|
||||
handleStopSendingFrame(*wire.StopSendingFrame)
|
||||
hasData() bool
|
||||
popStreamFrame(maxBytes protocol.ByteCount) (*wire.StreamFrame, bool)
|
||||
closeForShutdown(error)
|
||||
handleMaxStreamDataFrame(*wire.MaxStreamDataFrame)
|
||||
|
@ -40,8 +41,9 @@ type sendStream struct {
|
|||
finSent bool // set when a STREAM_FRAME with FIN bit has b
|
||||
|
||||
dataForWriting []byte
|
||||
writeChan chan struct{}
|
||||
writeDeadline time.Time
|
||||
|
||||
writeChan chan struct{}
|
||||
deadline time.Time
|
||||
|
||||
flowController flowcontrol.StreamFlowController
|
||||
|
||||
|
@ -85,49 +87,60 @@ func (s *sendStream) Write(p []byte) (int, error) {
|
|||
if s.closeForShutdownErr != nil {
|
||||
return 0, s.closeForShutdownErr
|
||||
}
|
||||
if !s.writeDeadline.IsZero() && !time.Now().Before(s.writeDeadline) {
|
||||
if !s.deadline.IsZero() && !time.Now().Before(s.deadline) {
|
||||
return 0, errDeadline
|
||||
}
|
||||
if len(p) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
s.dataForWriting = make([]byte, len(p))
|
||||
copy(s.dataForWriting, p)
|
||||
s.sender.onHasStreamData(s.streamID)
|
||||
s.dataForWriting = p
|
||||
|
||||
var bytesWritten int
|
||||
var err error
|
||||
var (
|
||||
deadlineTimer *utils.Timer
|
||||
bytesWritten int
|
||||
notifiedSender bool
|
||||
)
|
||||
for {
|
||||
bytesWritten = len(p) - len(s.dataForWriting)
|
||||
deadline := s.writeDeadline
|
||||
if !deadline.IsZero() && !time.Now().Before(deadline) {
|
||||
s.dataForWriting = nil
|
||||
err = errDeadline
|
||||
break
|
||||
deadline := s.deadline
|
||||
if !deadline.IsZero() {
|
||||
if !time.Now().Before(deadline) {
|
||||
s.dataForWriting = nil
|
||||
return bytesWritten, errDeadline
|
||||
}
|
||||
if deadlineTimer == nil {
|
||||
deadlineTimer = utils.NewTimer()
|
||||
}
|
||||
deadlineTimer.Reset(deadline)
|
||||
}
|
||||
if s.dataForWriting == nil || s.canceledWrite || s.closedForShutdown {
|
||||
break
|
||||
}
|
||||
|
||||
s.mutex.Unlock()
|
||||
if !notifiedSender {
|
||||
s.sender.onHasStreamData(s.streamID) // must be called without holding the mutex
|
||||
notifiedSender = true
|
||||
}
|
||||
if deadline.IsZero() {
|
||||
<-s.writeChan
|
||||
} else {
|
||||
select {
|
||||
case <-s.writeChan:
|
||||
case <-time.After(time.Until(deadline)):
|
||||
case <-deadlineTimer.Chan():
|
||||
deadlineTimer.SetRead()
|
||||
}
|
||||
}
|
||||
s.mutex.Lock()
|
||||
}
|
||||
|
||||
if s.closeForShutdownErr != nil {
|
||||
err = s.closeForShutdownErr
|
||||
return bytesWritten, s.closeForShutdownErr
|
||||
} else if s.cancelWriteErr != nil {
|
||||
err = s.cancelWriteErr
|
||||
return bytesWritten, s.cancelWriteErr
|
||||
}
|
||||
return bytesWritten, err
|
||||
return bytesWritten, nil
|
||||
}
|
||||
|
||||
// popStreamFrame returns the next STREAM frame that is supposed to be sent on this stream
|
||||
|
@ -181,12 +194,18 @@ func (s *sendStream) popStreamFrameImpl(maxBytes protocol.ByteCount) (bool /* co
|
|||
return frame.FinBit, frame, s.dataForWriting != nil
|
||||
}
|
||||
|
||||
func (s *sendStream) hasData() bool {
|
||||
s.mutex.Lock()
|
||||
hasData := len(s.dataForWriting) > 0
|
||||
s.mutex.Unlock()
|
||||
return hasData
|
||||
}
|
||||
|
||||
func (s *sendStream) getDataForWriting(maxBytes protocol.ByteCount) ([]byte, bool /* should send FIN */) {
|
||||
if s.dataForWriting == nil {
|
||||
return nil, s.finishedWriting && !s.finSent
|
||||
}
|
||||
|
||||
// TODO(#657): Flow control for the crypto stream
|
||||
if s.streamID != s.version.CryptoStreamID() {
|
||||
maxBytes = utils.MinByteCount(maxBytes, s.flowController.SendWindowSize())
|
||||
}
|
||||
|
@ -196,10 +215,12 @@ func (s *sendStream) getDataForWriting(maxBytes protocol.ByteCount) ([]byte, boo
|
|||
|
||||
var ret []byte
|
||||
if protocol.ByteCount(len(s.dataForWriting)) > maxBytes {
|
||||
ret = s.dataForWriting[:maxBytes]
|
||||
ret = make([]byte, int(maxBytes))
|
||||
copy(ret, s.dataForWriting[:maxBytes])
|
||||
s.dataForWriting = s.dataForWriting[maxBytes:]
|
||||
} else {
|
||||
ret = s.dataForWriting
|
||||
ret = make([]byte, len(s.dataForWriting))
|
||||
copy(ret, s.dataForWriting)
|
||||
s.dataForWriting = nil
|
||||
s.signalWrite()
|
||||
}
|
||||
|
@ -210,13 +231,14 @@ func (s *sendStream) getDataForWriting(maxBytes protocol.ByteCount) ([]byte, boo
|
|||
|
||||
func (s *sendStream) Close() error {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
if s.canceledWrite {
|
||||
s.mutex.Unlock()
|
||||
return fmt.Errorf("Close called for canceled stream %d", s.streamID)
|
||||
}
|
||||
s.finishedWriting = true
|
||||
s.sender.onHasStreamData(s.streamID) // need to send the FIN
|
||||
s.mutex.Unlock()
|
||||
|
||||
s.sender.onHasStreamData(s.streamID) // need to send the FIN, must be called without holding the mutex
|
||||
s.ctxCancel()
|
||||
return nil
|
||||
}
|
||||
|
@ -227,7 +249,7 @@ func (s *sendStream) CancelWrite(errorCode protocol.ApplicationErrorCode) error
|
|||
s.mutex.Unlock()
|
||||
|
||||
if completed {
|
||||
s.sender.onStreamCompleted(s.streamID)
|
||||
s.sender.onStreamCompleted(s.streamID) // must be called without holding the mutex
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@ -260,12 +282,13 @@ func (s *sendStream) handleStopSendingFrame(frame *wire.StopSendingFrame) {
|
|||
}
|
||||
|
||||
func (s *sendStream) handleMaxStreamDataFrame(frame *wire.MaxStreamDataFrame) {
|
||||
s.flowController.UpdateSendWindow(frame.ByteOffset)
|
||||
s.mutex.Lock()
|
||||
if s.dataForWriting != nil {
|
||||
hasStreamData := s.dataForWriting != nil
|
||||
s.mutex.Unlock()
|
||||
s.flowController.UpdateSendWindow(frame.ByteOffset)
|
||||
if hasStreamData {
|
||||
s.sender.onHasStreamData(s.streamID)
|
||||
}
|
||||
s.mutex.Unlock()
|
||||
}
|
||||
|
||||
// must be called after locking the mutex
|
||||
|
@ -291,12 +314,9 @@ func (s *sendStream) Context() context.Context {
|
|||
|
||||
func (s *sendStream) SetWriteDeadline(t time.Time) error {
|
||||
s.mutex.Lock()
|
||||
oldDeadline := s.writeDeadline
|
||||
s.writeDeadline = t
|
||||
s.deadline = t
|
||||
s.mutex.Unlock()
|
||||
if t.Before(oldDeadline) {
|
||||
s.signalWrite()
|
||||
}
|
||||
s.signalWrite()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
3
vendor/github.com/lucas-clemente/quic-go/server.go
generated
vendored
3
vendor/github.com/lucas-clemente/quic-go/server.go
generated
vendored
|
@ -123,6 +123,9 @@ func Listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (Listener,
|
|||
}
|
||||
|
||||
func listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (*server, error) {
|
||||
if tlsConf == nil || (len(tlsConf.Certificates) == 0 && tlsConf.GetCertificate == nil) {
|
||||
return nil, errors.New("quic: neither Certificates nor GetCertificate set in tls.Config")
|
||||
}
|
||||
certChain := crypto.NewCertChain(tlsConf)
|
||||
kex, err := crypto.NewCurve25519KEX()
|
||||
if err != nil {
|
||||
|
|
5
vendor/github.com/lucas-clemente/quic-go/server_tls.go
generated
vendored
5
vendor/github.com/lucas-clemente/quic-go/server_tls.go
generated
vendored
|
@ -118,9 +118,6 @@ func (s *serverTLS) handleInitialImpl(p *receivedPacket) (quicSession, protocol.
|
|||
mconf := s.mintConf.Clone()
|
||||
mconf.ExtensionHandler = extHandler
|
||||
|
||||
// A server is allowed to perform multiple Retries.
|
||||
// It doesn't make much sense, but it's something that our API allows.
|
||||
// In that case it must use a source connection ID of at least 8 bytes.
|
||||
connID, err := protocol.GenerateConnectionID(s.config.ConnectionIDLength)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -152,7 +149,7 @@ func (s *serverTLS) sendRetry(remoteAddr net.Addr, hdr *wire.Header) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
connID, err := protocol.GenerateConnectionIDForInitial()
|
||||
connID, err := protocol.GenerateConnectionID(s.config.ConnectionIDLength)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
110
vendor/github.com/lucas-clemente/quic-go/session.go
generated
vendored
110
vendor/github.com/lucas-clemente/quic-go/session.go
generated
vendored
|
@ -92,12 +92,12 @@ type session struct {
|
|||
|
||||
sentPacketHandler ackhandler.SentPacketHandler
|
||||
receivedPacketHandler ackhandler.ReceivedPacketHandler
|
||||
streamFramer *streamFramer
|
||||
framer *framer
|
||||
windowUpdateQueue *windowUpdateQueue
|
||||
connFlowController flowcontrol.ConnectionFlowController
|
||||
|
||||
unpacker unpacker
|
||||
packer *packetPacker
|
||||
packer packer
|
||||
|
||||
cryptoStreamHandler cryptoStreamHandler
|
||||
|
||||
|
@ -205,17 +205,17 @@ func newSession(
|
|||
s.cryptoStreamHandler = cs
|
||||
s.unpacker = newPacketUnpackerGQUIC(cs, s.version)
|
||||
s.streamsMap = newStreamsMapLegacy(s.newStream, s.config.MaxIncomingStreams, s.perspective)
|
||||
s.streamFramer = newStreamFramer(s.cryptoStream, s.streamsMap, s.version)
|
||||
s.packer = newPacketPacker(
|
||||
s.framer = newFramer(s.cryptoStream, s.streamsMap, s.version)
|
||||
s.packer = newPacketPackerLegacy(
|
||||
destConnID,
|
||||
srcConnID,
|
||||
1,
|
||||
s.sentPacketHandler.GetPacketNumberLen,
|
||||
s.RemoteAddr(),
|
||||
nil, // no token
|
||||
divNonce,
|
||||
s.cryptoStream,
|
||||
cs,
|
||||
s.streamFramer,
|
||||
s.framer,
|
||||
sentAndReceivedPacketManager{s.sentPacketHandler, s.receivedPacketHandler},
|
||||
s.perspective,
|
||||
s.version,
|
||||
)
|
||||
|
@ -226,7 +226,6 @@ func newSession(
|
|||
var newClientSession = func(
|
||||
conn connection,
|
||||
sessionRunner sessionRunner,
|
||||
hostname string,
|
||||
v protocol.VersionNumber,
|
||||
destConnID protocol.ConnectionID,
|
||||
srcConnID protocol.ConnectionID,
|
||||
|
@ -261,7 +260,6 @@ var newClientSession = func(
|
|||
}
|
||||
cs, err := newCryptoSetupClient(
|
||||
s.cryptoStream,
|
||||
hostname,
|
||||
destConnID,
|
||||
s.version,
|
||||
tlsConf,
|
||||
|
@ -278,17 +276,17 @@ var newClientSession = func(
|
|||
s.cryptoStreamHandler = cs
|
||||
s.unpacker = newPacketUnpackerGQUIC(cs, s.version)
|
||||
s.streamsMap = newStreamsMapLegacy(s.newStream, s.config.MaxIncomingStreams, s.perspective)
|
||||
s.streamFramer = newStreamFramer(s.cryptoStream, s.streamsMap, s.version)
|
||||
s.packer = newPacketPacker(
|
||||
s.framer = newFramer(s.cryptoStream, s.streamsMap, s.version)
|
||||
s.packer = newPacketPackerLegacy(
|
||||
destConnID,
|
||||
srcConnID,
|
||||
1,
|
||||
s.sentPacketHandler.GetPacketNumberLen,
|
||||
s.RemoteAddr(),
|
||||
nil, // no token
|
||||
nil, // no diversification nonce
|
||||
s.cryptoStream,
|
||||
cs,
|
||||
s.streamFramer,
|
||||
s.framer,
|
||||
sentAndReceivedPacketManager{s.sentPacketHandler, s.receivedPacketHandler},
|
||||
s.perspective,
|
||||
s.version,
|
||||
)
|
||||
|
@ -333,7 +331,7 @@ func newTLSServerSession(
|
|||
}
|
||||
s.cryptoStreamHandler = cs
|
||||
s.streamsMap = newStreamsMap(s, s.newFlowController, s.config.MaxIncomingStreams, s.config.MaxIncomingUniStreams, s.perspective, s.version)
|
||||
s.streamFramer = newStreamFramer(s.cryptoStream, s.streamsMap, s.version)
|
||||
s.framer = newFramer(s.cryptoStream, s.streamsMap, s.version)
|
||||
s.packer = newPacketPacker(
|
||||
s.destConnID,
|
||||
s.srcConnID,
|
||||
|
@ -341,9 +339,10 @@ func newTLSServerSession(
|
|||
s.sentPacketHandler.GetPacketNumberLen,
|
||||
s.RemoteAddr(),
|
||||
nil, // no token
|
||||
nil, // no diversification nonce
|
||||
s.cryptoStream,
|
||||
cs,
|
||||
s.streamFramer,
|
||||
s.framer,
|
||||
sentAndReceivedPacketManager{s.sentPacketHandler, s.receivedPacketHandler},
|
||||
s.perspective,
|
||||
s.version,
|
||||
)
|
||||
|
@ -397,7 +396,7 @@ var newTLSClientSession = func(
|
|||
s.cryptoStreamHandler = cs
|
||||
s.unpacker = newPacketUnpacker(cs, s.version)
|
||||
s.streamsMap = newStreamsMap(s, s.newFlowController, s.config.MaxIncomingStreams, s.config.MaxIncomingUniStreams, s.perspective, s.version)
|
||||
s.streamFramer = newStreamFramer(s.cryptoStream, s.streamsMap, s.version)
|
||||
s.framer = newFramer(s.cryptoStream, s.streamsMap, s.version)
|
||||
s.packer = newPacketPacker(
|
||||
s.destConnID,
|
||||
s.srcConnID,
|
||||
|
@ -405,9 +404,10 @@ var newTLSClientSession = func(
|
|||
s.sentPacketHandler.GetPacketNumberLen,
|
||||
s.RemoteAddr(),
|
||||
token,
|
||||
nil, // no diversification nonce
|
||||
s.cryptoStream,
|
||||
cs,
|
||||
s.streamFramer,
|
||||
s.framer,
|
||||
sentAndReceivedPacketManager{s.sentPacketHandler, s.receivedPacketHandler},
|
||||
s.perspective,
|
||||
s.version,
|
||||
)
|
||||
|
@ -417,6 +417,7 @@ var newTLSClientSession = func(
|
|||
func (s *session) preSetup() {
|
||||
s.rttStats = &congestion.RTTStats{}
|
||||
s.sentPacketHandler = ackhandler.NewSentPacketHandler(s.rttStats, s.logger, s.version)
|
||||
s.receivedPacketHandler = ackhandler.NewReceivedPacketHandler(s.rttStats, s.logger, s.version)
|
||||
s.connFlowController = flowcontrol.NewConnectionFlowController(
|
||||
protocol.ReceiveConnectionFlowControlWindow,
|
||||
protocol.ByteCount(s.config.MaxReceiveConnectionFlowControlWindow),
|
||||
|
@ -439,8 +440,7 @@ func (s *session) postSetup() error {
|
|||
s.lastNetworkActivityTime = now
|
||||
s.sessionCreationTime = now
|
||||
|
||||
s.receivedPacketHandler = ackhandler.NewReceivedPacketHandler(s.rttStats, s.logger, s.version)
|
||||
s.windowUpdateQueue = newWindowUpdateQueue(s.streamsMap, s.cryptoStream, s.connFlowController, s.packer.QueueControlFrame)
|
||||
s.windowUpdateQueue = newWindowUpdateQueue(s.streamsMap, s.connFlowController, s.framer.QueueControlFrame)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -496,6 +496,7 @@ runLoop:
|
|||
putPacketBuffer(&p.header.Raw)
|
||||
case p := <-s.paramsChan:
|
||||
s.processTransportParameters(&p)
|
||||
continue
|
||||
case _, ok := <-s.handshakeEvent:
|
||||
// when the handshake is completed, the channel will be closed
|
||||
s.handleHandshakeEvent(!ok)
|
||||
|
@ -517,7 +518,7 @@ runLoop:
|
|||
if s.config.KeepAlive && !s.keepAlivePingSent && s.handshakeComplete && time.Since(s.lastNetworkActivityTime) >= s.peerParams.IdleTimeout/2 {
|
||||
// send a PING frame since there is no activity in the session
|
||||
s.logger.Debugf("Sending a keep-alive ping to keep the connection alive.")
|
||||
s.packer.QueueControlFrame(&wire.PingFrame{})
|
||||
s.framer.QueueControlFrame(&wire.PingFrame{})
|
||||
s.keepAlivePingSent = true
|
||||
} else if !pacingDeadline.IsZero() && now.Before(pacingDeadline) {
|
||||
// If we get to this point before the pacing deadline, we should wait until that deadline.
|
||||
|
@ -527,18 +528,21 @@ runLoop:
|
|||
continue
|
||||
}
|
||||
|
||||
if err := s.sendPackets(); err != nil {
|
||||
s.closeLocal(err)
|
||||
}
|
||||
|
||||
if !s.receivedTooManyUndecrytablePacketsTime.IsZero() && s.receivedTooManyUndecrytablePacketsTime.Add(protocol.PublicResetTimeout).Before(now) && len(s.undecryptablePackets) != 0 {
|
||||
s.closeLocal(qerr.Error(qerr.DecryptionFailure, "too many undecryptable packets received"))
|
||||
continue
|
||||
}
|
||||
if !s.handshakeComplete && now.Sub(s.sessionCreationTime) >= s.config.HandshakeTimeout {
|
||||
s.closeLocal(qerr.Error(qerr.HandshakeTimeout, "Crypto handshake did not complete in time."))
|
||||
continue
|
||||
}
|
||||
if s.handshakeComplete && now.Sub(s.lastNetworkActivityTime) >= s.config.IdleTimeout {
|
||||
s.closeLocal(qerr.Error(qerr.NetworkIdleTimeout, "No recent network activity."))
|
||||
continue
|
||||
}
|
||||
|
||||
if err := s.sendPackets(); err != nil {
|
||||
s.closeLocal(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -906,12 +910,7 @@ func (s *session) handleCloseError(closeErr closeError) error {
|
|||
func (s *session) processTransportParameters(params *handshake.TransportParameters) {
|
||||
s.peerParams = params
|
||||
s.streamsMap.UpdateLimits(params)
|
||||
if params.OmitConnectionID {
|
||||
s.packer.SetOmitConnectionID()
|
||||
}
|
||||
if params.MaxPacketSize != 0 {
|
||||
s.packer.SetMaxPacketSize(params.MaxPacketSize)
|
||||
}
|
||||
s.packer.HandleTransportParameters(params)
|
||||
s.connFlowController.UpdateSendWindow(params.ConnectionFlowControlWindow)
|
||||
// the crypto stream is the only open stream at this moment
|
||||
// so we don't need to update stream flow control windows
|
||||
|
@ -933,6 +932,12 @@ sendLoop:
|
|||
case ackhandler.SendNone:
|
||||
break sendLoop
|
||||
case ackhandler.SendAck:
|
||||
// If we already sent packets, and the send mode switches to SendAck,
|
||||
// we've just become congestion limited.
|
||||
// There's no need to try to send an ACK at this moment.
|
||||
if numPacketsSent > 0 {
|
||||
return nil
|
||||
}
|
||||
// We can at most send a single ACK only packet.
|
||||
// There will only be a new ACK after receiving new packets.
|
||||
// SendAck is only returned when we're congestion limited, so we don't need to set the pacingt timer.
|
||||
|
@ -978,21 +983,13 @@ sendLoop:
|
|||
}
|
||||
|
||||
func (s *session) maybeSendAckOnlyPacket() error {
|
||||
ack := s.receivedPacketHandler.GetAckFrame()
|
||||
if ack == nil {
|
||||
return nil
|
||||
}
|
||||
s.packer.QueueControlFrame(ack)
|
||||
|
||||
if s.version.UsesStopWaitingFrames() { // for gQUIC, maybe add a STOP_WAITING
|
||||
if swf := s.sentPacketHandler.GetStopWaitingFrame(false); swf != nil {
|
||||
s.packer.QueueControlFrame(swf)
|
||||
}
|
||||
}
|
||||
packet, err := s.packer.PackAckPacket()
|
||||
packet, err := s.packer.MaybePackAckPacket()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if packet == nil {
|
||||
return nil
|
||||
}
|
||||
s.sentPacketHandler.SentPacket(packet.ToAckHandlerPacket())
|
||||
return s.sendPackedPacket(packet)
|
||||
}
|
||||
|
@ -1023,9 +1020,6 @@ func (s *session) maybeSendRetransmission() (bool, error) {
|
|||
s.logger.Debugf("Dequeueing retransmission for packet 0x%x", retransmitPacket.PacketNumber)
|
||||
}
|
||||
|
||||
if s.version.UsesStopWaitingFrames() {
|
||||
s.packer.QueueControlFrame(s.sentPacketHandler.GetStopWaitingFrame(true))
|
||||
}
|
||||
packets, err := s.packer.PackRetransmission(retransmitPacket)
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
@ -1050,9 +1044,6 @@ func (s *session) sendProbePacket() error {
|
|||
}
|
||||
s.logger.Debugf("Sending a retransmission for %#x as a probe packet.", p.PacketNumber)
|
||||
|
||||
if s.version.UsesStopWaitingFrames() {
|
||||
s.packer.QueueControlFrame(s.sentPacketHandler.GetStopWaitingFrame(true))
|
||||
}
|
||||
packets, err := s.packer.PackRetransmission(p)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1072,19 +1063,10 @@ func (s *session) sendProbePacket() error {
|
|||
|
||||
func (s *session) sendPacket() (bool, error) {
|
||||
if isBlocked, offset := s.connFlowController.IsNewlyBlocked(); isBlocked {
|
||||
s.packer.QueueControlFrame(&wire.BlockedFrame{Offset: offset})
|
||||
s.framer.QueueControlFrame(&wire.BlockedFrame{Offset: offset})
|
||||
}
|
||||
s.windowUpdateQueue.QueueAll()
|
||||
|
||||
if ack := s.receivedPacketHandler.GetAckFrame(); ack != nil {
|
||||
s.packer.QueueControlFrame(ack)
|
||||
if s.version.UsesStopWaitingFrames() {
|
||||
if swf := s.sentPacketHandler.GetStopWaitingFrame(false); swf != nil {
|
||||
s.packer.QueueControlFrame(swf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
packet, err := s.packer.PackPacket()
|
||||
if err != nil || packet == nil {
|
||||
return false, err
|
||||
|
@ -1245,7 +1227,7 @@ func (s *session) tryDecryptingQueuedPackets() {
|
|||
}
|
||||
|
||||
func (s *session) queueControlFrame(f wire.Frame) {
|
||||
s.packer.QueueControlFrame(f)
|
||||
s.framer.QueueControlFrame(f)
|
||||
s.scheduleSending()
|
||||
}
|
||||
|
||||
|
@ -1260,7 +1242,9 @@ func (s *session) onHasConnectionWindowUpdate() {
|
|||
}
|
||||
|
||||
func (s *session) onHasStreamData(id protocol.StreamID) {
|
||||
s.streamFramer.AddActiveStream(id)
|
||||
if id != s.version.CryptoStreamID() {
|
||||
s.framer.AddActiveStream(id)
|
||||
}
|
||||
s.scheduleSending()
|
||||
}
|
||||
|
||||
|
|
1
vendor/github.com/lucas-clemente/quic-go/stream.go
generated
vendored
1
vendor/github.com/lucas-clemente/quic-go/stream.go
generated
vendored
|
@ -52,6 +52,7 @@ type streamI interface {
|
|||
handleRstStreamFrame(*wire.RstStreamFrame) error
|
||||
getWindowUpdate() protocol.ByteCount
|
||||
// for sending
|
||||
hasData() bool
|
||||
handleStopSendingFrame(*wire.StopSendingFrame)
|
||||
popStreamFrame(maxBytes protocol.ByteCount) (*wire.StreamFrame, bool)
|
||||
handleMaxStreamDataFrame(*wire.MaxStreamDataFrame)
|
||||
|
|
16
vendor/github.com/lucas-clemente/quic-go/window_update_queue.go
generated
vendored
16
vendor/github.com/lucas-clemente/quic-go/window_update_queue.go
generated
vendored
|
@ -14,7 +14,6 @@ type windowUpdateQueue struct {
|
|||
queue map[protocol.StreamID]bool // used as a set
|
||||
queuedConn bool // connection-level window update
|
||||
|
||||
cryptoStream cryptoStream
|
||||
streamGetter streamGetter
|
||||
connFlowController flowcontrol.ConnectionFlowController
|
||||
callback func(wire.Frame)
|
||||
|
@ -22,14 +21,12 @@ type windowUpdateQueue struct {
|
|||
|
||||
func newWindowUpdateQueue(
|
||||
streamGetter streamGetter,
|
||||
cryptoStream cryptoStream,
|
||||
connFC flowcontrol.ConnectionFlowController,
|
||||
cb func(wire.Frame),
|
||||
) *windowUpdateQueue {
|
||||
return &windowUpdateQueue{
|
||||
queue: make(map[protocol.StreamID]bool),
|
||||
streamGetter: streamGetter,
|
||||
cryptoStream: cryptoStream,
|
||||
connFlowController: connFC,
|
||||
callback: cb,
|
||||
}
|
||||
|
@ -55,17 +52,12 @@ func (q *windowUpdateQueue) QueueAll() {
|
|||
q.queuedConn = false
|
||||
}
|
||||
// queue all stream-level window updates
|
||||
var offset protocol.ByteCount
|
||||
for id := range q.queue {
|
||||
if id == q.cryptoStream.StreamID() {
|
||||
offset = q.cryptoStream.getWindowUpdate()
|
||||
} else {
|
||||
str, err := q.streamGetter.GetOrOpenReceiveStream(id)
|
||||
if err != nil || str == nil { // the stream can be nil if it was completed before dequeing the window update
|
||||
continue
|
||||
}
|
||||
offset = str.getWindowUpdate()
|
||||
str, err := q.streamGetter.GetOrOpenReceiveStream(id)
|
||||
if err != nil || str == nil { // the stream can be nil if it was completed before dequeing the window update
|
||||
continue
|
||||
}
|
||||
offset := str.getWindowUpdate()
|
||||
if offset == 0 { // can happen if we received a final offset, right after queueing the window update
|
||||
continue
|
||||
}
|
||||
|
|
2
vendor/manifest
vendored
2
vendor/manifest
vendored
|
@ -130,7 +130,7 @@
|
|||
"importpath": "github.com/lucas-clemente/quic-go",
|
||||
"repository": "https://github.com/lucas-clemente/quic-go",
|
||||
"vcs": "git",
|
||||
"revision": "71635f6961ad00ca5c088be625624e4a2cd1c066",
|
||||
"revision": "f90751eabaa39364e3861ee5a8b179f140847d7e",
|
||||
"branch": "HEAD",
|
||||
"notests": true
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue