mirror of
https://github.com/yggdrasil-network/yggstack.git
synced 2025-04-28 22:25:08 +03:00
Fix unix domain socket creation/cleanup logic
* If there is another instance still listening on the same Unix domain socket, bail out * If there is a leftover from crashed yggstack etc, clean the socket file and proceed Signed-off-by: Vasyl Gello <vasek.gello@gmail.com>
This commit is contained in:
parent
23d4321be4
commit
ef1c547a3f
1 changed files with 61 additions and 33 deletions
|
@ -12,6 +12,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
@ -273,44 +274,48 @@ func main() {
|
||||||
|
|
||||||
// Create SOCKS server
|
// Create SOCKS server
|
||||||
{
|
{
|
||||||
if socks != nil {
|
if socks != nil && *socks != "" {
|
||||||
if nameserver != nil {
|
|
||||||
if strings.Contains(*socks, ":") {
|
|
||||||
logger.Infof("Starting SOCKS server on %s", *socks)
|
|
||||||
resolver := types.NewNameResolver(s, *nameserver)
|
|
||||||
socksOptions := []socks5.Option{
|
socksOptions := []socks5.Option{
|
||||||
socks5.WithDial(s.DialContext),
|
socks5.WithDial(s.DialContext),
|
||||||
socks5.WithResolver(resolver),
|
}
|
||||||
|
if nameserver != nil && *nameserver != "" {
|
||||||
|
resolver := types.NewNameResolver(s, *nameserver)
|
||||||
|
socksOptions = append(socksOptions, socks5.WithResolver(resolver))
|
||||||
|
} else {
|
||||||
|
logger.Warningf("DNS nameserver is not set!")
|
||||||
|
logger.Warningf("SOCKS server will not be able to resolve hostnames other than .pk.ygg !")
|
||||||
}
|
}
|
||||||
if logger.GetLevel("debug") {
|
if logger.GetLevel("debug") {
|
||||||
socksOptions = append(socksOptions, socks5.WithLogger(logger))
|
socksOptions = append(socksOptions, socks5.WithLogger(logger))
|
||||||
}
|
}
|
||||||
server := socks5.NewServer(socksOptions...)
|
server := socks5.NewServer(socksOptions...)
|
||||||
|
if strings.Contains(*socks, ":") {
|
||||||
|
logger.Infof("Starting SOCKS server on %s", *socks)
|
||||||
go server.ListenAndServe("tcp", *socks) // nolint:errcheck
|
go server.ListenAndServe("tcp", *socks) // nolint:errcheck
|
||||||
} else {
|
} else {
|
||||||
logger.Infof("Starting SOCKS server with socket file %s", *socks)
|
logger.Infof("Starting SOCKS server with socket file %s", *socks)
|
||||||
_, err := os.Stat(*socks)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
n.socks5Listener, err = net.Listen("unix", *socks)
|
n.socks5Listener, err = net.Listen("unix", *socks)
|
||||||
|
if err != nil {
|
||||||
|
// If address in use, try connecting to
|
||||||
|
// the socket to see if other yggstack
|
||||||
|
// instance is listening on it
|
||||||
|
|
||||||
|
if isErrorAddressAlreadyInUse(err) {
|
||||||
|
_, err = net.Dial("unix", *socks)
|
||||||
|
if err != nil {
|
||||||
|
// Unlink dead socket if not connected
|
||||||
|
err = os.RemoveAll(*socks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
resolver := types.NewNameResolver(s, *nameserver)
|
|
||||||
socksOptions := []socks5.Option{
|
|
||||||
socks5.WithDial(s.DialContext),
|
|
||||||
socks5.WithResolver(resolver),
|
|
||||||
}
|
|
||||||
if logger.GetLevel("debug") {
|
|
||||||
socksOptions = append(socksOptions, socks5.WithLogger(logger))
|
|
||||||
}
|
|
||||||
server := socks5.NewServer(socksOptions...)
|
|
||||||
go server.Serve(n.socks5Listener) // nolint:errcheck
|
|
||||||
} else if err != nil {
|
|
||||||
logger.Errorf("Cannot create socket file %s: %s", *socks, err)
|
|
||||||
} else {
|
} else {
|
||||||
panic(errors.New(fmt.Sprintf("Socket file %s already exists", *socks)))
|
panic(fmt.Errorf("Another yggstack instance is listening on socket '%s'", *socks))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
go server.Serve(n.socks5Listener) // nolint:errcheck
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -349,11 +354,34 @@ func main() {
|
||||||
_ = n.multicast.Stop()
|
_ = n.multicast.Stop()
|
||||||
if n.socks5Listener != nil {
|
if n.socks5Listener != nil {
|
||||||
_ = n.socks5Listener.Close()
|
_ = n.socks5Listener.Close()
|
||||||
|
_ = os.RemoveAll(*socks)
|
||||||
logger.Infof("Stopped UNIX socket listener")
|
logger.Infof("Stopped UNIX socket listener")
|
||||||
}
|
}
|
||||||
n.core.Stop()
|
n.core.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper to detect if socket address is in use
|
||||||
|
// https://stackoverflow.com/a/52152912
|
||||||
|
func isErrorAddressAlreadyInUse(err error) bool {
|
||||||
|
var eOsSyscall *os.SyscallError
|
||||||
|
if !errors.As(err, &eOsSyscall) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
var errErrno syscall.Errno // doesn't need a "*" (ptr) because it's already a ptr (uintptr)
|
||||||
|
if !errors.As(eOsSyscall, &errErrno) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if errors.Is(errErrno, syscall.EADDRINUSE) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
const WSAEADDRINUSE = 10048
|
||||||
|
if runtime.GOOS == "windows" && errErrno == WSAEADDRINUSE {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to set logging level
|
||||||
func setLogLevel(loglevel string, logger *log.Logger) {
|
func setLogLevel(loglevel string, logger *log.Logger) {
|
||||||
levels := [...]string{"error", "warn", "info", "debug", "trace"}
|
levels := [...]string{"error", "warn", "info", "debug", "trace"}
|
||||||
loglevel = strings.ToLower(loglevel)
|
loglevel = strings.ToLower(loglevel)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue