-
Notifications
You must be signed in to change notification settings - Fork 2.7k
/
resolver.go
121 lines (108 loc) · 2.67 KB
/
resolver.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright 2016 CodisLabs. All Rights Reserved.
// Licensed under the MIT (MIT-LICENSE.txt) license.
package utils
import (
"net"
"os"
"strconv"
"time"
"golang.org/x/net/context"
"github.com/CodisLabs/codis/pkg/utils/errors"
)
func LookupIP(host string) []net.IP {
ipAddrs, _ := net.LookupIP(host)
return ipAddrs
}
func LookupIPTimeout(host string, timeout time.Duration) []net.IP {
cntx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
var ch = make(chan []net.IP, 1)
go func() {
ch <- LookupIP(host)
}()
select {
case ipAddrs := <-ch:
return ipAddrs
case <-cntx.Done():
return nil
}
}
func ResolveTCPAddr(addr string) *net.TCPAddr {
tcpAddr, _ := net.ResolveTCPAddr("tcp", addr)
return tcpAddr
}
func ResolveTCPAddrTimeout(addr string, timeout time.Duration) *net.TCPAddr {
cntx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
var ch = make(chan *net.TCPAddr, 1)
go func() {
ch <- ResolveTCPAddr(addr)
}()
select {
case tcpAddr := <-ch:
return tcpAddr
case <-cntx.Done():
return nil
}
}
var (
Hostname, _ = os.Hostname()
HostIPs, InterfaceIPs []string
)
func init() {
if ipAddrs := LookupIPTimeout(Hostname, 30*time.Millisecond); len(ipAddrs) != 0 {
for _, ip := range ipAddrs {
if ip.IsGlobalUnicast() {
HostIPs = append(HostIPs, ip.String())
}
}
}
if ifAddrs, _ := net.InterfaceAddrs(); len(ifAddrs) != 0 {
for i := range ifAddrs {
var ip net.IP
switch in := ifAddrs[i].(type) {
case *net.IPNet:
ip = in.IP
case *net.IPAddr:
ip = in.IP
}
if ip.IsGlobalUnicast() {
InterfaceIPs = append(InterfaceIPs, ip.String())
}
}
}
}
func ReplaceUnspecifiedIP(network string, listenAddr, globalAddr string) (string, error) {
if globalAddr == "" {
return replaceUnspecifiedIP(network, listenAddr, true)
} else {
return replaceUnspecifiedIP(network, globalAddr, false)
}
}
func replaceUnspecifiedIP(network string, address string, replace bool) (string, error) {
switch network {
default:
return "", errors.Trace(net.UnknownNetworkError(network))
case "unix", "unixpacket":
return address, nil
case "tcp", "tcp4", "tcp6":
tcpAddr, err := net.ResolveTCPAddr(network, address)
if err != nil {
return "", errors.Trace(err)
}
if tcpAddr.Port != 0 {
if !tcpAddr.IP.IsUnspecified() {
return address, nil
}
if replace {
if len(HostIPs) != 0 {
return net.JoinHostPort(Hostname, strconv.Itoa(tcpAddr.Port)), nil
}
if len(InterfaceIPs) != 0 {
return net.JoinHostPort(InterfaceIPs[0], strconv.Itoa(tcpAddr.Port)), nil
}
}
}
return "", errors.Errorf("resolve address '%s' to '%s'", address, tcpAddr.String())
}
}