Improve control

This commit is contained in:
世界 2022-07-17 14:30:57 +08:00
parent 6795d518e1
commit 6910a8c5ce
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
13 changed files with 60 additions and 68 deletions

View file

@ -11,11 +11,11 @@ type BindManager interface {
Update() error
}
type simpleBindManager struct {
type myBindManager struct {
interfaceIndexByName map[string]int
}
func (m *simpleBindManager) IndexByName(name string) (int, error) {
func (m *myBindManager) IndexByName(name string) (int, error) {
if index, loaded := m.interfaceIndexByName[name]; loaded {
return index, nil
}
@ -29,7 +29,7 @@ func (m *simpleBindManager) IndexByName(name string) (int, error) {
return 0, E.New("interface ", name, " not found")
}
func (m *simpleBindManager) Update() error {
func (m *myBindManager) Update() error {
interfaces, err := net.Interfaces()
if err != nil {
return err

View file

@ -2,8 +2,6 @@ package control
import (
"syscall"
E "github.com/sagernet/sing/common/exceptions"
)
func NewBindManager() BindManager {
@ -12,11 +10,9 @@ func NewBindManager() BindManager {
func BindToInterface(manager BindManager, interfaceName string) Func {
return func(network, address string, conn syscall.RawConn) error {
var innerErr error
err := conn.Control(func(fd uintptr) {
innerErr = syscall.BindToDevice(int(fd), interfaceName)
return Control(conn, func(fd uintptr) error {
return syscall.BindToDevice(int(fd), interfaceName)
})
return E.Errors(innerErr, err)
}
}
@ -26,11 +22,9 @@ func BindToInterfaceFunc(manager BindManager, interfaceNameFunc func() string) F
if interfaceName == "" {
return nil
}
var innerErr error
err := conn.Control(func(fd uintptr) {
innerErr = syscall.BindToDevice(int(fd), interfaceName)
return Control(conn, func(fd uintptr) error {
return syscall.BindToDevice(int(fd), interfaceName)
})
return E.Errors(innerErr, err)
}
}

View file

@ -6,8 +6,6 @@ import (
"net/netip"
"syscall"
"unsafe"
E "github.com/sagernet/sing/common/exceptions"
)
const (
@ -16,7 +14,7 @@ const (
)
func NewBindManager() BindManager {
return &simpleBindManager{
return &myBindManager{
interfaceIndexByName: make(map[string]int),
}
}
@ -39,28 +37,25 @@ func bindInterfaceIndex(network string, address string, conn syscall.RawConn, in
return err
}
}
var innerErr error
err = conn.Control(func(fd uintptr) {
return Control(conn, func(fd uintptr) error {
handle := syscall.Handle(fd)
// handle ip empty, e.g. net.Listen("udp", ":0")
if ipStr == "" {
innerErr = bind4(handle, interfaceIndex)
if innerErr != nil {
return
err = bind4(handle, interfaceIndex)
if err != nil {
return err
}
// try bind ipv6, if failed, ignore. it's a workaround for windows disable interface ipv6
bind6(handle, interfaceIndex)
return
return nil
}
switch network {
case "tcp4", "udp4", "ip4":
innerErr = bind4(handle, interfaceIndex)
case "tcp6", "udp6":
innerErr = bind6(handle, interfaceIndex)
return bind4(handle, interfaceIndex)
default:
return bind6(handle, interfaceIndex)
}
})
return E.Errors(innerErr, err)
}
func BindToInterface(manager BindManager, interfaceName string) Func {

View file

@ -2,6 +2,8 @@ package control
import (
"syscall"
E "github.com/sagernet/sing/common/exceptions"
)
type Func = func(network, address string, conn syscall.RawConn) error
@ -19,3 +21,11 @@ func Append(oldFunc Func, newFunc Func) Func {
return newFunc(network, address, conn)
}
}
func Control(conn syscall.RawConn, block func(fd uintptr) error) error {
var innerErr error
err := conn.Control(func(fd uintptr) {
innerErr = block(fd)
})
return E.Errors(innerErr, err)
}

View file

@ -2,16 +2,12 @@ package control
import (
"syscall"
E "github.com/sagernet/sing/common/exceptions"
)
func RoutingMark(mark int) Func {
return func(network, address string, conn syscall.RawConn) error {
var innerErr error
err := conn.Control(func(fd uintptr) {
innerErr = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark)
return Control(conn, func(fd uintptr) error {
return syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark)
})
return E.Errors(innerErr, err)
}
}

View file

@ -1,5 +1,3 @@
//go:build linux
package control
import (
@ -36,10 +34,8 @@ func sendAncillaryFileDescriptors(protectPath string, fileDescriptors []int) err
func ProtectPath(protectPath string) Func {
return func(network, address string, conn syscall.RawConn) error {
var innerErr error
err := conn.Control(func(fd uintptr) {
innerErr = sendAncillaryFileDescriptors(protectPath, []int{int(fd)})
return Control(conn, func(fd uintptr) error {
return sendAncillaryFileDescriptors(protectPath, []int{int(fd)})
})
return E.Errors(innerErr, err)
}
}

View file

@ -1,4 +1,4 @@
//go:build !linux
//go:build !android
package control

View file

@ -1,21 +0,0 @@
package control
import (
"syscall"
E "github.com/sagernet/sing/common/exceptions"
)
func ReuseAddr() Func {
return func(network, address string, conn syscall.RawConn) error {
var innerErr error
err := conn.Control(func(fd uintptr) {
const SO_REUSEPORT = 0xf
innerErr = E.Errors(
syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1),
syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, SO_REUSEPORT, 1),
)
})
return E.Errors(innerErr, err)
}
}

View file

@ -1,4 +1,4 @@
//go:build !linux && !windows
//go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows
package control

View file

@ -0,0 +1,22 @@
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
package control
import (
"syscall"
E "github.com/sagernet/sing/common/exceptions"
"golang.org/x/sys/unix"
)
func ReuseAddr() Func {
return func(network, address string, conn syscall.RawConn) error {
return Control(conn, func(fd uintptr) error {
return E.Errors(
unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1),
unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1),
)
})
}
}

View file

@ -2,16 +2,12 @@ package control
import (
"syscall"
E "github.com/sagernet/sing/common/exceptions"
)
func ReuseAddr() Func {
return func(network, address string, conn syscall.RawConn) error {
var innerErr error
err := conn.Control(func(fd uintptr) {
innerErr = syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
return Control(conn, func(fd uintptr) error {
return syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
})
return E.Errors(innerErr, err)
}
}

2
go.mod
View file

@ -1,3 +1,5 @@
module github.com/sagernet/sing
go 1.18
require golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8

2
go.sum
View file

@ -0,0 +1,2 @@
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=