package host import ( "fmt" "net" "strconv" ) func isValidIP(addr string) bool { ip := net.ParseIP(addr) return ip.IsGlobalUnicast() && !ip.IsInterfaceLocalMulticast() } // Port return a real port. func Port(lis net.Listener) (int, bool) { if addr, ok := lis.Addr().(*net.TCPAddr); ok { return addr.Port, true } return 0, false } // Extract returns a private addr and port. func Extract(hostPort string, lis net.Listener) (string, error) { addr, port, err := net.SplitHostPort(hostPort) if err != nil { return "", err } if lis != nil { if p, ok := Port(lis); ok { port = strconv.Itoa(p) } else { return "", fmt.Errorf("failed to extract port: %v", lis.Addr()) } } if len(addr) > 0 && (addr != "0.0.0.0" && addr != "[::]" && addr != "::") { return net.JoinHostPort(addr, port), nil } ifaces, err := net.Interfaces() if err != nil { return "", err } for _, iface := range ifaces { addrs, err := iface.Addrs() if err != nil { continue } for _, rawAddr := range addrs { var ip net.IP switch addr := rawAddr.(type) { case *net.IPAddr: ip = addr.IP case *net.IPNet: ip = addr.IP default: continue } if isValidIP(ip.String()) { return net.JoinHostPort(ip.String(), port), nil } } } return "", nil }