-
Notifications
You must be signed in to change notification settings - Fork 0
/
host.go
90 lines (85 loc) · 1.82 KB
/
host.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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
if err != nil {
return
}
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 {
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
}
lowest := int(^uint(0) >> 1)
var result net.IP
for _, iface := range ifaces {
if (iface.Flags & net.FlagUp) == 0 {
continue
}
if iface.Index < lowest || result == nil {
lowest = iface.Index
} else if 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()) {
result = ip
}
}
}
if result != nil {
return net.JoinHostPort(result.String(), port), nil
}
return "", nil
}