mirror of
				https://github.com/yggdrasil-network/yggstack.git
				synced 2025-11-04 00:15:06 +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