github.com/sagernet/quic-go@v0.43.1-beta.1/ech/sys_conn_buffers.go (about) 1 package quic 2 3 import ( 4 "errors" 5 "fmt" 6 "net" 7 "syscall" 8 9 "github.com/sagernet/quic-go/internal/protocol" 10 "github.com/sagernet/quic-go/internal/utils" 11 ) 12 13 //go:generate sh -c "echo '// Code generated by go generate. DO NOT EDIT.\n// Source: sys_conn_buffers.go\n' > sys_conn_buffers_write.go && sed -e 's/SetReadBuffer/SetWriteBuffer/g' -e 's/setReceiveBuffer/setSendBuffer/g' -e 's/inspectReadBuffer/inspectWriteBuffer/g' -e 's/protocol\\.DesiredReceiveBufferSize/protocol\\.DesiredSendBufferSize/g' -e 's/forceSetReceiveBuffer/forceSetSendBuffer/g' -e 's/receive buffer/send buffer/g' sys_conn_buffers.go | sed '/^\\/\\/go:generate/d' >> sys_conn_buffers_write.go" 14 func setReceiveBuffer(c net.PacketConn) error { 15 conn, ok := c.(interface{ SetReadBuffer(int) error }) 16 if !ok { 17 return errors.New("connection doesn't allow setting of receive buffer size. Not a *net.UDPConn?") 18 } 19 20 var syscallConn syscall.RawConn 21 if sc, ok := c.(interface { 22 SyscallConn() (syscall.RawConn, error) 23 }); ok { 24 var err error 25 syscallConn, err = sc.SyscallConn() 26 if err != nil { 27 syscallConn = nil 28 } 29 } 30 // The connection has a SetReadBuffer method, but we couldn't obtain a syscall.RawConn. 31 // This shouldn't happen for a net.UDPConn, but is possible if the connection just implements the 32 // net.PacketConn interface and the SetReadBuffer method. 33 // We have no way of checking if increasing the buffer size actually worked. 34 if syscallConn == nil { 35 return conn.SetReadBuffer(protocol.DesiredReceiveBufferSize) 36 } 37 38 size, err := inspectReadBuffer(syscallConn) 39 if err != nil { 40 return fmt.Errorf("failed to determine receive buffer size: %w", err) 41 } 42 if size >= protocol.DesiredReceiveBufferSize { 43 utils.DefaultLogger.Debugf("Conn has receive buffer of %d kiB (wanted: at least %d kiB)", size/1024, protocol.DesiredReceiveBufferSize/1024) 44 return nil 45 } 46 // Ignore the error. We check if we succeeded by querying the buffer size afterward. 47 _ = conn.SetReadBuffer(protocol.DesiredReceiveBufferSize) 48 newSize, err := inspectReadBuffer(syscallConn) 49 if newSize < protocol.DesiredReceiveBufferSize { 50 // Try again with RCVBUFFORCE on Linux 51 _ = forceSetReceiveBuffer(syscallConn, protocol.DesiredReceiveBufferSize) 52 newSize, err = inspectReadBuffer(syscallConn) 53 if err != nil { 54 return fmt.Errorf("failed to determine receive buffer size: %w", err) 55 } 56 } 57 if err != nil { 58 return fmt.Errorf("failed to determine receive buffer size: %w", err) 59 } 60 if newSize == size { 61 return fmt.Errorf("failed to increase receive buffer size (wanted: %d kiB, got %d kiB)", protocol.DesiredReceiveBufferSize/1024, newSize/1024) 62 } 63 if newSize < protocol.DesiredReceiveBufferSize { 64 return fmt.Errorf("failed to sufficiently increase receive buffer size (was: %d kiB, wanted: %d kiB, got: %d kiB)", size/1024, protocol.DesiredReceiveBufferSize/1024, newSize/1024) 65 } 66 utils.DefaultLogger.Debugf("Increased receive buffer size to %d kiB", newSize/1024) 67 return nil 68 }