darvaza-proxy / x

extra helpers for darvaza projects
MIT License
1 stars 0 forks source link

Improve net/bind to use SO_REUSEPORT and friends #16

Open karasz opened 8 months ago

karasz commented 8 months ago

All the Listeners from the bind folder should have the option of being created with SO_REUSEPORT, so a Config should look like:

// Config is the configuration for Bind()
type Config struct {
.......
    Port uint16
    // PortStrict tells us not to try other ports
    PortStrict bool
    // PortAttempts indicates how many times we will try finding a port
    PortAttempts int
    // Defaultport indicates the port to try on the first attempt if Port is zero
    DefaultPort uint16
        // PortReuse indicates that the listener is able to reuse the port between threads/processes
        PortReuse bool

.....

    // ListenTCP is the helper to use to listen on TCP ports
    ListenTCP func(network string, laddr *net.TCPAddr) (*net.TCPListener, error)
    // ListenUDP is the helper to use to listen on UDP ports
    ListenUDP func(network string, laddr *net.UDPAddr) (*net.UDPConn, error)
.......
}

also default ListenTCP and ListenUDP should be created

var listenConfig = net.ListenConfig{
    Control: Control,
}

func ListenTCP(network, address string) (net.Listener, error) {
    return listenConfig.Listen(context.Background(), "tcp", address)
}
func ListenUDP(network, address string) (net.PacketConn, error) {
    return listenConfig.ListenPacket(context.Background(), "udp", address)
}

with Control function implemented for windows, linux, unix

example for unix:

import (
    "syscall"

    "golang.org/x/sys/unix"
)

func Control(network, address string, c syscall.RawConn) (err error) {
    controlErr := c.Control(func(fd uintptr) {
        err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
        if err != nil {
            return
        }
        err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1)
    })
    if controlErr != nil {
        err = controlErr
    }
    return
}