Skip to content

Instantly share code, notes, and snippets.

@tobyxdd
Created February 20, 2022 03:42
Show Gist options
  • Save tobyxdd/1964cc8d559fb367010c80c1dafee1b1 to your computer and use it in GitHub Desktop.
Save tobyxdd/1964cc8d559fb367010c80c1dafee1b1 to your computer and use it in GitHub Desktop.
diff --git a/conn.go b/conn.go
index 2f4e3a23..811279c9 100644
--- a/conn.go
+++ b/conn.go
@@ -29,6 +29,19 @@ type OOBCapablePacketConn interface {
var _ OOBCapablePacketConn = &net.UDPConn{}
func wrapConn(pc net.PacketConn) (connection, error) {
+ conn, ok := pc.(interface {
+ SyscallConn() (syscall.RawConn, error)
+ })
+ if ok {
+ rawConn, err := conn.SyscallConn()
+ if err != nil {
+ return nil, err
+ }
+ err = setDF(rawConn)
+ if err != nil {
+ return nil, err
+ }
+ }
c, ok := pc.(OOBCapablePacketConn)
if !ok {
utils.DefaultLogger.Infof("PacketConn is not a net.UDPConn. Disabling optimizations possible on UDP connections.")
diff --git a/conn_oob_opts.go b/conn_df.go
similarity index 59%
rename from conn_oob_opts.go
rename to conn_df.go
index 4d29c7c4..544fea3e 100644
--- a/conn_oob_opts.go
+++ b/conn_df.go
@@ -3,6 +3,9 @@
package quic
-func setOOBSockOpts(fd uintptr) {
+import "syscall"
+
+func setDF(rawConn syscall.RawConn) error {
// no-op on unsupported platforms
+ return nil
}
diff --git a/conn_df_linux.go b/conn_df_linux.go
new file mode 100644
index 00000000..89948ff8
--- /dev/null
+++ b/conn_df_linux.go
@@ -0,0 +1,34 @@
+//go:build linux
+// +build linux
+
+package quic
+
+import (
+ "errors"
+ "github.com/lucas-clemente/quic-go/internal/utils"
+ "golang.org/x/sys/unix"
+ "syscall"
+)
+
+func setDF(rawConn syscall.RawConn) error {
+ // Enabling IP_MTU_DISCOVER will force the kernel to return "sendto: message too long"
+ // and the datagram will not be fragmented
+ var errDFIPv4, errDFIPv6 error
+ if err := rawConn.Control(func(fd uintptr) {
+ errDFIPv4 = unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_MTU_DISCOVER, unix.IP_PMTUDISC_DO)
+ errDFIPv6 = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_MTU_DISCOVER, unix.IPV6_PMTUDISC_DO)
+ }); err != nil {
+ return 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 errors.New("setting DF failed for both IPv4 and IPv6")
+ }
+ return nil
+}
diff --git a/conn_df_windows.go b/conn_df_windows.go
new file mode 100644
index 00000000..0f5a5b0b
--- /dev/null
+++ b/conn_df_windows.go
@@ -0,0 +1,40 @@
+//go:build windows
+// +build windows
+
+package quic
+
+import (
+ "errors"
+ "github.com/lucas-clemente/quic-go/internal/utils"
+ "golang.org/x/sys/windows"
+ "syscall"
+)
+
+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 setDF(rawConn syscall.RawConn) error {
+ 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 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 errors.New("setting DF failed for both IPv4 and IPv6")
+ }
+ return nil
+}
diff --git a/conn_oob.go b/conn_oob.go
index f1aebfaa..b4678137 100644
--- a/conn_oob.go
+++ b/conn_oob.go
@@ -87,8 +87,6 @@ func newConn(c OOBCapablePacketConn) (*oobConn, error) {
errPIIPv4 = unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, ipv4RECVPKTINFO, 1)
errPIIPv6 = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, ipv6RECVPKTINFO, 1)
}
-
- setOOBSockOpts(fd)
}); err != nil {
return nil, err
}
diff --git a/conn_oob_opts_linux.go b/conn_oob_opts_linux.go
deleted file mode 100644
index 81e7ca58..00000000
--- a/conn_oob_opts_linux.go
+++ /dev/null
@@ -1,15 +0,0 @@
-//go:build linux
-// +build linux
-
-package quic
-
-import (
- "golang.org/x/sys/unix"
-)
-
-func setOOBSockOpts(fd uintptr) {
- // Enabling IP_MTU_DISCOVER will force the kernel to return "sendto: message too long"
- // and the datagram will not be fragmented
- unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_MTU_DISCOVER, unix.IP_PMTUDISC_DO)
- unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_MTU_DISCOVER, unix.IPV6_PMTUDISC_DO)
-}
diff --git a/conn_windows.go b/conn_windows.go
index 72906b89..4869d67a 100644
--- a/conn_windows.go
+++ b/conn_windows.go
@@ -9,40 +9,10 @@ import (
"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
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment