package host import ( "fmt" "net" "strconv" ) // ExtractHostPort from address func ExtractHostPort(addr string) (host string, port uint64, err error) { var ports string host, ports, err = net.SplitHostPort(addr) if err != nil { return } port, err = strconv.ParseUint(ports, 10, 16) //nolint:gomnd return } 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 && lis == nil { return "", err } if lis != nil { p, ok := Port(lis) if !ok { return "", fmt.Errorf("failed to extract port: %v", lis.Addr()) } port = strconv.Itoa(p) } 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 } minIndex := int(^uint(0) >> 1) var result net.IP for _, iface := range ifaces { if (iface.Flags & net.FlagUp) == 0 { continue } if iface.Index >= minIndex && result != nil { continue } 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()) { minIndex = iface.Index result = ip break } } } if result != nil { return net.JoinHostPort(result.String(), port), nil } return "", nil }