forked from quic-go/quic-go
This commit introduces additional platform-dependent checking when the kernel returns an error. Previously, the session is terminated when PingFrame sends a discovery packet larger than the limit. With this commit, the error is checked, and if it is "datagram too large", the error is ignored. Additionally, 1. This commit re-enables MTU discovery on Windows unless it is disabled explicitly by user (Undo #3276), 2. Set IP_DONTFRAGMENT and IPV6_DONTFRAG with error checking on Windows, and 3. Set IP_MTU_DISCOVERY to PMTUDISC_DO for both IPv4 and IPv6 on Linux so that the kernel will return "message too long". Fixes #3273 #3327
71 lines
2.0 KiB
Go
71 lines
2.0 KiB
Go
//go:build windows
|
|
// +build windows
|
|
|
|
package quic
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"syscall"
|
|
|
|
"github.com/lucas-clemente/quic-go/internal/utils"
|
|
"golang.org/x/sys/windows"
|
|
)
|
|
|
|
const (
|
|
// same for both IPv4 and IPv6 on Windows
|
|
// https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Networking/WinSock/constant.IP_DONTFRAG.html
|
|
// https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Networking/WinSock/constant.IPV6_DONTFRAG.html
|
|
IP_DONTFRAGMENT = 14
|
|
IPV6_DONTFRAG = 14
|
|
)
|
|
|
|
func newConn(c OOBCapablePacketConn) (connection, error) {
|
|
rawConn, err := c.SyscallConn()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("couldn't get syscall.RawConn: %w", err)
|
|
}
|
|
var errDFIPv4, errDFIPv6 error
|
|
if err := rawConn.Control(func(fd uintptr) {
|
|
errDFIPv4 = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IP, IP_DONTFRAGMENT, 1)
|
|
errDFIPv6 = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IPV6, IPV6_DONTFRAG, 1)
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
switch {
|
|
case errDFIPv4 == nil && errDFIPv6 == nil:
|
|
utils.DefaultLogger.Debugf("Setting DF for IPv4 and IPv6.")
|
|
case errDFIPv4 == nil && errDFIPv6 != nil:
|
|
utils.DefaultLogger.Debugf("Setting DF for IPv4.")
|
|
case errDFIPv4 != nil && errDFIPv6 == nil:
|
|
utils.DefaultLogger.Debugf("Setting DF for IPv6.")
|
|
case errDFIPv4 != nil && errDFIPv6 != nil:
|
|
return nil, errors.New("setting Df failed for both IPv4 and IPv6")
|
|
}
|
|
return &basicConn{PacketConn: c}, nil
|
|
}
|
|
|
|
func inspectReadBuffer(c net.PacketConn) (int, error) {
|
|
conn, ok := c.(interface {
|
|
SyscallConn() (syscall.RawConn, error)
|
|
})
|
|
if !ok {
|
|
return 0, errors.New("doesn't have a SyscallConn")
|
|
}
|
|
rawConn, err := conn.SyscallConn()
|
|
if err != nil {
|
|
return 0, fmt.Errorf("couldn't get syscall.RawConn: %w", err)
|
|
}
|
|
var size int
|
|
var serr error
|
|
if err := rawConn.Control(func(fd uintptr) {
|
|
size, serr = windows.GetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_RCVBUF)
|
|
}); err != nil {
|
|
return 0, err
|
|
}
|
|
return size, serr
|
|
}
|
|
|
|
func (i *packetInfo) OOB() []byte { return nil }
|