You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
92 lines
1.9 KiB
92 lines
1.9 KiB
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) |
|
ips := make([]net.IP, 0) |
|
for _, iface := range ifaces { |
|
if (iface.Flags & net.FlagUp) == 0 { |
|
continue |
|
} |
|
if iface.Index >= minIndex && len(ips) != 0 { |
|
continue |
|
} |
|
addrs, err := iface.Addrs() |
|
if err != nil { |
|
continue |
|
} |
|
for i, 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 |
|
if i == 0 { |
|
ips = make([]net.IP, 0, 1) |
|
} |
|
ips = append(ips, ip) |
|
if ip.To4() != nil { |
|
break |
|
} |
|
} |
|
} |
|
} |
|
if len(ips) != 0 { |
|
return net.JoinHostPort(ips[len(ips)-1].String(), port), nil |
|
} |
|
return "", nil |
|
}
|
|
|