2021-02-17 17:14:47 +08:00
|
|
|
package host
|
|
|
|
|
|
|
|
import (
|
2021-06-15 11:39:28 +08:00
|
|
|
"fmt"
|
2021-02-17 17:14:47 +08:00
|
|
|
"net"
|
|
|
|
"strconv"
|
|
|
|
)
|
|
|
|
|
2021-06-28 10:20:48 +08:00
|
|
|
// ExtractHostPort from address
|
|
|
|
func ExtractHostPort(addr string) (host string, port uint64, err error) {
|
2021-08-31 10:14:57 +08:00
|
|
|
var ports string
|
2021-06-28 10:20:48 +08:00
|
|
|
host, ports, err = net.SplitHostPort(addr)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2021-08-31 10:14:57 +08:00
|
|
|
port, err = strconv.ParseUint(ports, 10, 16) //nolint:gomnd
|
2021-06-28 10:20:48 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-05-31 16:55:30 +08:00
|
|
|
func isValidIP(addr string) bool {
|
2021-04-08 17:45:11 +08:00
|
|
|
ip := net.ParseIP(addr)
|
2021-05-31 17:17:33 +08:00
|
|
|
return ip.IsGlobalUnicast() && !ip.IsInterfaceLocalMulticast()
|
2021-02-17 17:14:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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.
|
2021-04-08 17:45:11 +08:00
|
|
|
func Extract(hostPort string, lis net.Listener) (string, error) {
|
|
|
|
addr, port, err := net.SplitHostPort(hostPort)
|
2021-09-15 18:02:26 +08:00
|
|
|
if err != nil && lis == nil {
|
2021-02-17 17:14:47 +08:00
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
if lis != nil {
|
2022-05-20 22:36:18 +08:00
|
|
|
p, ok := Port(lis)
|
|
|
|
if !ok {
|
2021-06-15 11:39:28 +08:00
|
|
|
return "", fmt.Errorf("failed to extract port: %v", lis.Addr())
|
2021-02-17 17:14:47 +08:00
|
|
|
}
|
2022-05-20 22:36:18 +08:00
|
|
|
port = strconv.Itoa(p)
|
2021-02-17 17:14:47 +08:00
|
|
|
}
|
|
|
|
if len(addr) > 0 && (addr != "0.0.0.0" && addr != "[::]" && addr != "::") {
|
|
|
|
return net.JoinHostPort(addr, port), nil
|
|
|
|
}
|
|
|
|
ifaces, err := net.Interfaces()
|
|
|
|
if err != nil {
|
2021-03-05 22:40:38 +08:00
|
|
|
return "", err
|
2021-02-17 17:14:47 +08:00
|
|
|
}
|
2021-12-16 22:41:44 +08:00
|
|
|
lowest := int(^uint(0) >> 1)
|
|
|
|
var result net.IP
|
2021-02-17 17:14:47 +08:00
|
|
|
for _, iface := range ifaces {
|
2021-12-16 22:41:44 +08:00
|
|
|
if (iface.Flags & net.FlagUp) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if iface.Index < lowest || result == nil {
|
|
|
|
lowest = iface.Index
|
2022-05-20 22:36:18 +08:00
|
|
|
}
|
|
|
|
if result != nil {
|
2021-12-16 22:41:44 +08:00
|
|
|
continue
|
|
|
|
}
|
2021-02-17 17:14:47 +08:00
|
|
|
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
|
|
|
|
}
|
2021-05-31 16:55:30 +08:00
|
|
|
if isValidIP(ip.String()) {
|
2021-12-16 22:41:44 +08:00
|
|
|
result = ip
|
2021-02-17 17:14:47 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-16 22:41:44 +08:00
|
|
|
if result != nil {
|
|
|
|
return net.JoinHostPort(result.String(), port), nil
|
|
|
|
}
|
2021-02-17 17:14:47 +08:00
|
|
|
return "", nil
|
|
|
|
}
|