Files
gluetun/internal/pmtud/tcp/multi.go
T
Quentin McGaw 5f903d1fbf chore(pmtud): remove calls to syscall in favor of unix and windows
- syscall is deprecated and is not kept up-to-date
- each OS is inherently different hence the syscall being deprecated
2026-02-17 21:46:04 +00:00

90 lines
1.9 KiB
Go

package tcp
import (
"context"
"errors"
"fmt"
"net/netip"
"time"
"github.com/qdm12/gluetun/internal/pmtud/constants"
"github.com/qdm12/gluetun/internal/pmtud/test"
)
var ErrMTUNotFound = errors.New("MTU not found")
type testUnit struct {
mtu uint32
ok bool
}
func PathMTUDiscover(ctx context.Context, addrPort netip.AddrPort,
minMTU, maxPossibleMTU uint32, logger Logger,
) (mtu uint32, err error) {
mtusToTest := test.MakeMTUsToTest(minMTU, maxPossibleMTU)
if len(mtusToTest) == 1 { // only minMTU because minMTU == maxPossibleMTU
return minMTU, nil
}
logger.Debugf("TCP testing the following MTUs: %v", mtusToTest)
tests := make([]testUnit, len(mtusToTest))
for i := range mtusToTest {
tests[i] = testUnit{mtu: mtusToTest[i]}
}
family := constants.AF_INET
if addrPort.Addr().Is6() {
family = constants.AF_INET6
}
fd, stop, err := startRawSocket(family)
if err != nil {
return 0, fmt.Errorf("starting raw socket: %w", err)
}
defer stop()
tracker := newTracker(fd, addrPort.Addr().Is4())
const timeout = time.Second
runCtx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
errCh := make(chan error)
go func() {
errCh <- tracker.listen(runCtx)
}()
doneCh := make(chan struct{})
for i := range tests {
go func(i int) {
err := runTest(runCtx, fd, tracker, addrPort, tests[i].mtu)
tests[i].ok = err == nil
doneCh <- struct{}{}
}(i)
}
for range tests {
select {
case <-doneCh:
case err := <-errCh:
if err == nil { // timeout
break
}
return 0, fmt.Errorf("listening for TCP replies: %w", err)
}
}
if tests[len(tests)-1].ok {
return tests[len(tests)-1].mtu, nil
}
for i := len(tests) - 2; i >= 0; i-- { //nolint:mnd
if tests[i].ok {
stop()
cancel()
return PathMTUDiscover(ctx, addrPort,
tests[i].mtu, tests[i+1].mtu-1, logger)
}
}
return 0, fmt.Errorf("%w: your connection might not be working at all", ErrMTUNotFound)
}