cloudflared/vendor/github.com/lucas-clemente/quic-go/mtu_discoverer.go
Nuno Diegues 475939a77f TUN-6191: Update quic-go to v0.27.1 and with custom patch to allow keep alive period to be configurable
The idle period is set to 5sec.

We now also ping every second since last activity.
This makes the quic.Connection less prone to being closed with
no network activity, since we send multiple pings per idle
period, and thus a single packet loss cannot cause the problem.
2022-06-07 12:25:18 +01:00

75 lines
1.9 KiB
Go

package quic
import (
"time"
"github.com/lucas-clemente/quic-go/internal/ackhandler"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/internal/wire"
)
type mtuDiscoverer interface {
ShouldSendProbe(now time.Time) bool
GetPing() (ping ackhandler.Frame, datagramSize protocol.ByteCount)
}
const (
// At some point, we have to stop searching for a higher MTU.
// We're happy to send a packet that's 10 bytes smaller than the actual MTU.
maxMTUDiff = 20
// send a probe packet every mtuProbeDelay RTTs
mtuProbeDelay = 5
)
type mtuFinder struct {
lastProbeTime time.Time
probeInFlight bool
mtuIncreased func(protocol.ByteCount)
rttStats *utils.RTTStats
current protocol.ByteCount
max protocol.ByteCount // the maximum value, as advertised by the peer (or our maximum size buffer)
}
var _ mtuDiscoverer = &mtuFinder{}
func newMTUDiscoverer(rttStats *utils.RTTStats, start, max protocol.ByteCount, mtuIncreased func(protocol.ByteCount)) mtuDiscoverer {
return &mtuFinder{
current: start,
rttStats: rttStats,
lastProbeTime: time.Now(), // to make sure the first probe packet is not sent immediately
mtuIncreased: mtuIncreased,
max: max,
}
}
func (f *mtuFinder) done() bool {
return f.max-f.current <= maxMTUDiff+1
}
func (f *mtuFinder) ShouldSendProbe(now time.Time) bool {
if f.probeInFlight || f.done() {
return false
}
return !now.Before(f.lastProbeTime.Add(mtuProbeDelay * f.rttStats.SmoothedRTT()))
}
func (f *mtuFinder) GetPing() (ackhandler.Frame, protocol.ByteCount) {
size := (f.max + f.current) / 2
f.lastProbeTime = time.Now()
f.probeInFlight = true
return ackhandler.Frame{
Frame: &wire.PingFrame{},
OnLost: func(wire.Frame) {
f.probeInFlight = false
f.max = size
},
OnAcked: func(wire.Frame) {
f.probeInFlight = false
f.current = size
f.mtuIncreased(size)
},
}, size
}