github.com/binbinly/pkg@v0.0.11-0.20240321014439-f4fbf666eb0f/util/host.go (about)

     1  package util
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"os"
     7  	"strconv"
     8  )
     9  
    10  // ExtractHostPort from address
    11  func ExtractHostPort(addr string) (host string, port uint64, err error) {
    12  	var ports string
    13  	host, ports, err = net.SplitHostPort(addr)
    14  	if err != nil {
    15  		return
    16  	}
    17  	port, err = strconv.ParseUint(ports, 10, 16) //nolint:gomnd
    18  	if err != nil {
    19  		return
    20  	}
    21  	return
    22  }
    23  
    24  // Port return a real port.
    25  func Port(lis net.Listener) (int, bool) {
    26  	if addr, ok := lis.Addr().(*net.TCPAddr); ok {
    27  		return addr.Port, true
    28  	}
    29  	return 0, false
    30  }
    31  
    32  // Hostname 获取主机名
    33  func Hostname() string {
    34  	name, err := os.Hostname()
    35  	if err != nil {
    36  		name = "unknown"
    37  	}
    38  	return name
    39  }
    40  
    41  // Extract returns a private addr and port.
    42  func Extract(hostPort string, lis net.Listener) (string, error) {
    43  	if hostPort == "" {
    44  		return "", fmt.Errorf("hostPort cannot be empty")
    45  	}
    46  
    47  	addr, port, err := net.SplitHostPort(hostPort)
    48  	if err != nil && lis == nil {
    49  		return "", err
    50  	}
    51  	if lis != nil {
    52  		if p, ok := Port(lis); ok {
    53  			port = strconv.Itoa(p)
    54  		} else {
    55  			return "", fmt.Errorf("failed to extract port: %v", lis.Addr())
    56  		}
    57  	}
    58  	if len(addr) > 0 && (addr != "0.0.0.0" && addr != "[::]" && addr != "::") {
    59  		return net.JoinHostPort(addr, port), nil
    60  	}
    61  	ifaces, err := net.Interfaces()
    62  	if err != nil {
    63  		return "", err
    64  	}
    65  	for _, iface := range ifaces {
    66  		addrs, err := iface.Addrs()
    67  		if err != nil {
    68  			continue
    69  		}
    70  		for _, rawAddr := range addrs {
    71  			var ip net.IP
    72  			switch addr := rawAddr.(type) {
    73  			case *net.IPAddr:
    74  				ip = addr.IP
    75  			case *net.IPNet:
    76  				ip = addr.IP
    77  			default:
    78  				continue
    79  			}
    80  
    81  			if ip == nil {
    82  				continue
    83  			}
    84  
    85  			if isValidIP(ip.String()) {
    86  				return net.JoinHostPort(ip.String(), port), nil
    87  			}
    88  		}
    89  	}
    90  	return "", nil
    91  }
    92  
    93  func isValidIP(ip string) bool {
    94  	parsedIP := net.ParseIP(ip)
    95  	if parsedIP == nil {
    96  		return false
    97  	}
    98  	return parsedIP.IsGlobalUnicast()
    99  }