mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-05 05:07:36 +03:00
simplify connection handling when setting the receive buffer
This commit is contained in:
parent
1cd78f131f
commit
600502ab06
6 changed files with 38 additions and 54 deletions
|
@ -4,7 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"syscall"
|
||||||
|
|
||||||
"github.com/quic-go/quic-go/internal/protocol"
|
"github.com/quic-go/quic-go/internal/protocol"
|
||||||
"github.com/quic-go/quic-go/internal/utils"
|
"github.com/quic-go/quic-go/internal/utils"
|
||||||
|
@ -15,7 +15,26 @@ func setReceiveBuffer(c net.PacketConn, logger utils.Logger) error {
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.New("connection doesn't allow setting of receive buffer size. Not a *net.UDPConn?")
|
return errors.New("connection doesn't allow setting of receive buffer size. Not a *net.UDPConn?")
|
||||||
}
|
}
|
||||||
size, err := inspectReadBuffer(c)
|
|
||||||
|
var syscallConn syscall.RawConn
|
||||||
|
if sc, ok := c.(interface {
|
||||||
|
SyscallConn() (syscall.RawConn, error)
|
||||||
|
}); ok {
|
||||||
|
var err error
|
||||||
|
syscallConn, err = sc.SyscallConn()
|
||||||
|
if err != nil {
|
||||||
|
syscallConn = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The connection has a SetReadBuffer method, but we couldn't obtain a syscall.RawConn.
|
||||||
|
// This shouldn't happen for a net.UDPConn, but is possible if the connection just implements the
|
||||||
|
// net.PacketConn interface and the SetReadBuffer method.
|
||||||
|
// We have no way of checking if increasing the buffer size actually worked.
|
||||||
|
if syscallConn == nil {
|
||||||
|
return conn.SetReadBuffer(protocol.DesiredReceiveBufferSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
size, err := inspectReadBuffer(syscallConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to determine receive buffer size: %w", err)
|
return fmt.Errorf("failed to determine receive buffer size: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -25,11 +44,11 @@ func setReceiveBuffer(c net.PacketConn, logger utils.Logger) error {
|
||||||
}
|
}
|
||||||
// Ignore the error. We check if we succeeded by querying the buffer size afterward.
|
// Ignore the error. We check if we succeeded by querying the buffer size afterward.
|
||||||
_ = conn.SetReadBuffer(protocol.DesiredReceiveBufferSize)
|
_ = conn.SetReadBuffer(protocol.DesiredReceiveBufferSize)
|
||||||
newSize, err := inspectReadBuffer(c)
|
newSize, err := inspectReadBuffer(syscallConn)
|
||||||
if newSize < protocol.DesiredReceiveBufferSize {
|
if newSize < protocol.DesiredReceiveBufferSize {
|
||||||
// Try again with RCVBUFFORCE on Linux
|
// Try again with RCVBUFFORCE on Linux
|
||||||
_ = forceSetReceiveBuffer(c, protocol.DesiredReceiveBufferSize)
|
_ = forceSetReceiveBuffer(syscallConn, protocol.DesiredReceiveBufferSize)
|
||||||
newSize, err = inspectReadBuffer(c)
|
newSize, err = inspectReadBuffer(syscallConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to determine receive buffer size: %w", err)
|
return fmt.Errorf("failed to determine receive buffer size: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
package quic
|
package quic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
@ -24,19 +22,9 @@ const (
|
||||||
|
|
||||||
const batchSize = 8 // needs to smaller than MaxUint8 (otherwise the type of oobConn.readPos has to be changed)
|
const batchSize = 8 // needs to smaller than MaxUint8 (otherwise the type of oobConn.readPos has to be changed)
|
||||||
|
|
||||||
func forceSetReceiveBuffer(c interface{}, bytes int) error {
|
func forceSetReceiveBuffer(c syscall.RawConn, bytes int) error {
|
||||||
conn, ok := c.(interface {
|
|
||||||
SyscallConn() (syscall.RawConn, error)
|
|
||||||
})
|
|
||||||
if !ok {
|
|
||||||
return errors.New("doesn't have a SyscallConn")
|
|
||||||
}
|
|
||||||
rawConn, err := conn.SyscallConn()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("couldn't get syscall.RawConn: %w", err)
|
|
||||||
}
|
|
||||||
var serr error
|
var serr error
|
||||||
if err := rawConn.Control(func(fd uintptr) {
|
if err := c.Control(func(fd uintptr) {
|
||||||
serr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUFFORCE, bytes)
|
serr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUFFORCE, bytes)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -21,15 +21,18 @@ var _ = Describe("Can change the receive buffer size", func() {
|
||||||
|
|
||||||
c, err := net.ListenPacket("udp", "127.0.0.1:0")
|
c, err := net.ListenPacket("udp", "127.0.0.1:0")
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
forceSetReceiveBuffer(c, 256<<10)
|
defer c.Close()
|
||||||
|
syscallConn, err := c.(*net.UDPConn).SyscallConn()
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
forceSetReceiveBuffer(syscallConn, 256<<10)
|
||||||
|
|
||||||
size, err := inspectReadBuffer(c)
|
size, err := inspectReadBuffer(syscallConn)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
// The kernel doubles this value (to allow space for bookkeeping overhead)
|
// The kernel doubles this value (to allow space for bookkeeping overhead)
|
||||||
Expect(size).To(Equal(512 << 10))
|
Expect(size).To(Equal(512 << 10))
|
||||||
|
|
||||||
forceSetReceiveBuffer(c, 512<<10)
|
forceSetReceiveBuffer(syscallConn, 512<<10)
|
||||||
size, err = inspectReadBuffer(c)
|
size, err = inspectReadBuffer(syscallConn)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
// The kernel doubles this value (to allow space for bookkeeping overhead)
|
// The kernel doubles this value (to allow space for bookkeeping overhead)
|
||||||
Expect(size).To(Equal(1024 << 10))
|
Expect(size).To(Equal(1024 << 10))
|
||||||
|
|
|
@ -8,8 +8,6 @@ func newConn(c net.PacketConn) (rawConn, error) {
|
||||||
return &basicConn{PacketConn: c}, nil
|
return &basicConn{PacketConn: c}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func inspectReadBuffer(interface{}) (int, error) {
|
func inspectReadBuffer(any) (int, error) { return 0, nil }
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *packetInfo) OOB() []byte { return nil }
|
func (i *packetInfo) OOB() []byte { return nil }
|
||||||
|
|
|
@ -5,7 +5,6 @@ package quic
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"net"
|
"net"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
@ -32,20 +31,10 @@ type batchConn interface {
|
||||||
ReadBatch(ms []ipv4.Message, flags int) (int, error)
|
ReadBatch(ms []ipv4.Message, flags int) (int, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func inspectReadBuffer(c interface{}) (int, error) {
|
func inspectReadBuffer(c syscall.RawConn) (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 size int
|
||||||
var serr error
|
var serr error
|
||||||
if err := rawConn.Control(func(fd uintptr) {
|
if err := c.Control(func(fd uintptr) {
|
||||||
size, serr = unix.GetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUF)
|
size, serr = unix.GetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUF)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
|
|
@ -3,9 +3,6 @@
|
||||||
package quic
|
package quic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
|
@ -15,20 +12,10 @@ func newConn(c OOBCapablePacketConn) (rawConn, error) {
|
||||||
return &basicConn{PacketConn: c}, nil
|
return &basicConn{PacketConn: c}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func inspectReadBuffer(c net.PacketConn) (int, error) {
|
func inspectReadBuffer(c syscall.RawConn) (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 size int
|
||||||
var serr error
|
var serr error
|
||||||
if err := rawConn.Control(func(fd uintptr) {
|
if err := c.Control(func(fd uintptr) {
|
||||||
size, serr = windows.GetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_RCVBUF)
|
size, serr = windows.GetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_RCVBUF)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue