aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/google.golang.org/grpc/naming
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/google.golang.org/grpc/naming')
-rw-r--r--vendor/google.golang.org/grpc/naming/dns_resolver.go292
-rw-r--r--vendor/google.golang.org/grpc/naming/go17.go34
-rw-r--r--vendor/google.golang.org/grpc/naming/go18.go28
-rw-r--r--vendor/google.golang.org/grpc/naming/naming.go59
4 files changed, 413 insertions, 0 deletions
diff --git a/vendor/google.golang.org/grpc/naming/dns_resolver.go b/vendor/google.golang.org/grpc/naming/dns_resolver.go
new file mode 100644
index 0000000..efd37e3
--- /dev/null
+++ b/vendor/google.golang.org/grpc/naming/dns_resolver.go
@@ -0,0 +1,292 @@
1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package naming
20
21import (
22 "errors"
23 "fmt"
24 "net"
25 "strconv"
26 "time"
27
28 "golang.org/x/net/context"
29 "google.golang.org/grpc/grpclog"
30)
31
32const (
33 defaultPort = "443"
34 defaultFreq = time.Minute * 30
35)
36
37var (
38 errMissingAddr = errors.New("missing address")
39 errWatcherClose = errors.New("watcher has been closed")
40)
41
42// NewDNSResolverWithFreq creates a DNS Resolver that can resolve DNS names, and
43// create watchers that poll the DNS server using the frequency set by freq.
44func NewDNSResolverWithFreq(freq time.Duration) (Resolver, error) {
45 return &dnsResolver{freq: freq}, nil
46}
47
48// NewDNSResolver creates a DNS Resolver that can resolve DNS names, and create
49// watchers that poll the DNS server using the default frequency defined by defaultFreq.
50func NewDNSResolver() (Resolver, error) {
51 return NewDNSResolverWithFreq(defaultFreq)
52}
53
54// dnsResolver handles name resolution for names following the DNS scheme
55type dnsResolver struct {
56 // frequency of polling the DNS server that the watchers created by this resolver will use.
57 freq time.Duration
58}
59
60// formatIP returns ok = false if addr is not a valid textual representation of an IP address.
61// If addr is an IPv4 address, return the addr and ok = true.
62// If addr is an IPv6 address, return the addr enclosed in square brackets and ok = true.
63func formatIP(addr string) (addrIP string, ok bool) {
64 ip := net.ParseIP(addr)
65 if ip == nil {
66 return "", false
67 }
68 if ip.To4() != nil {
69 return addr, true
70 }
71 return "[" + addr + "]", true
72}
73
74// parseTarget takes the user input target string, returns formatted host and port info.
75// If target doesn't specify a port, set the port to be the defaultPort.
76// If target is in IPv6 format and host-name is enclosed in sqarue brackets, brackets
77// are strippd when setting the host.
78// examples:
79// target: "www.google.com" returns host: "www.google.com", port: "443"
80// target: "ipv4-host:80" returns host: "ipv4-host", port: "80"
81// target: "[ipv6-host]" returns host: "ipv6-host", port: "443"
82// target: ":80" returns host: "localhost", port: "80"
83// target: ":" returns host: "localhost", port: "443"
84func parseTarget(target string) (host, port string, err error) {
85 if target == "" {
86 return "", "", errMissingAddr
87 }
88
89 if ip := net.ParseIP(target); ip != nil {
90 // target is an IPv4 or IPv6(without brackets) address
91 return target, defaultPort, nil
92 }
93 if host, port, err := net.SplitHostPort(target); err == nil {
94 // target has port, i.e ipv4-host:port, [ipv6-host]:port, host-name:port
95 if host == "" {
96 // Keep consistent with net.Dial(): If the host is empty, as in ":80", the local system is assumed.
97 host = "localhost"
98 }
99 if port == "" {
100 // If the port field is empty(target ends with colon), e.g. "[::1]:", defaultPort is used.
101 port = defaultPort
102 }
103 return host, port, nil
104 }
105 if host, port, err := net.SplitHostPort(target + ":" + defaultPort); err == nil {
106 // target doesn't have port
107 return host, port, nil
108 }
109 return "", "", fmt.Errorf("invalid target address %v", target)
110}
111
112// Resolve creates a watcher that watches the name resolution of the target.
113func (r *dnsResolver) Resolve(target string) (Watcher, error) {
114 host, port, err := parseTarget(target)
115 if err != nil {
116 return nil, err
117 }
118
119 if net.ParseIP(host) != nil {
120 ipWatcher := &ipWatcher{
121 updateChan: make(chan *Update, 1),
122 }
123 host, _ = formatIP(host)
124 ipWatcher.updateChan <- &Update{Op: Add, Addr: host + ":" + port}
125 return ipWatcher, nil
126 }
127
128 ctx, cancel := context.WithCancel(context.Background())
129 return &dnsWatcher{
130 r: r,
131 host: host,
132 port: port,
133 ctx: ctx,
134 cancel: cancel,
135 t: time.NewTimer(0),
136 }, nil
137}
138
139// dnsWatcher watches for the name resolution update for a specific target
140type dnsWatcher struct {
141 r *dnsResolver
142 host string
143 port string
144 // The latest resolved address list
145 curAddrs []*Update
146 ctx context.Context
147 cancel context.CancelFunc
148 t *time.Timer
149}
150
151// ipWatcher watches for the name resolution update for an IP address.
152type ipWatcher struct {
153 updateChan chan *Update
154}
155
156// Next returns the adrress resolution Update for the target. For IP address,
157// the resolution is itself, thus polling name server is unncessary. Therefore,
158// Next() will return an Update the first time it is called, and will be blocked
159// for all following calls as no Update exisits until watcher is closed.
160func (i *ipWatcher) Next() ([]*Update, error) {
161 u, ok := <-i.updateChan
162 if !ok {
163 return nil, errWatcherClose
164 }
165 return []*Update{u}, nil
166}
167
168// Close closes the ipWatcher.
169func (i *ipWatcher) Close() {
170 close(i.updateChan)
171}
172
173// AddressType indicates the address type returned by name resolution.
174type AddressType uint8
175
176const (
177 // Backend indicates the server is a backend server.
178 Backend AddressType = iota
179 // GRPCLB indicates the server is a grpclb load balancer.
180 GRPCLB
181)
182
183// AddrMetadataGRPCLB contains the information the name resolver for grpclb should provide. The
184// name resolver used by the grpclb balancer is required to provide this type of metadata in
185// its address updates.
186type AddrMetadataGRPCLB struct {
187 // AddrType is the type of server (grpc load balancer or backend).
188 AddrType AddressType
189 // ServerName is the name of the grpc load balancer. Used for authentication.
190 ServerName string
191}
192
193// compileUpdate compares the old resolved addresses and newly resolved addresses,
194// and generates an update list
195func (w *dnsWatcher) compileUpdate(newAddrs []*Update) []*Update {
196 update := make(map[Update]bool)
197 for _, u := range newAddrs {
198 update[*u] = true
199 }
200 for _, u := range w.curAddrs {
201 if _, ok := update[*u]; ok {
202 delete(update, *u)
203 continue
204 }
205 update[Update{Addr: u.Addr, Op: Delete, Metadata: u.Metadata}] = true
206 }
207 res := make([]*Update, 0, len(update))
208 for k := range update {
209 tmp := k
210 res = append(res, &tmp)
211 }
212 return res
213}
214
215func (w *dnsWatcher) lookupSRV() []*Update {
216 var newAddrs []*Update
217 _, srvs, err := lookupSRV(w.ctx, "grpclb", "tcp", w.host)
218 if err != nil {
219 grpclog.Infof("grpc: failed dns SRV record lookup due to %v.\n", err)
220 return nil
221 }
222 for _, s := range srvs {
223 lbAddrs, err := lookupHost(w.ctx, s.Target)
224 if err != nil {
225 grpclog.Warningf("grpc: failed load banlacer address dns lookup due to %v.\n", err)
226 continue
227 }
228 for _, a := range lbAddrs {
229 a, ok := formatIP(a)
230 if !ok {
231 grpclog.Errorf("grpc: failed IP parsing due to %v.\n", err)
232 continue
233 }
234 newAddrs = append(newAddrs, &Update{Addr: a + ":" + strconv.Itoa(int(s.Port)),
235 Metadata: AddrMetadataGRPCLB{AddrType: GRPCLB, ServerName: s.Target}})
236 }
237 }
238 return newAddrs
239}
240
241func (w *dnsWatcher) lookupHost() []*Update {
242 var newAddrs []*Update
243 addrs, err := lookupHost(w.ctx, w.host)
244 if err != nil {
245 grpclog.Warningf("grpc: failed dns A record lookup due to %v.\n", err)
246 return nil
247 }
248 for _, a := range addrs {
249 a, ok := formatIP(a)
250 if !ok {
251 grpclog.Errorf("grpc: failed IP parsing due to %v.\n", err)
252 continue
253 }
254 newAddrs = append(newAddrs, &Update{Addr: a + ":" + w.port})
255 }
256 return newAddrs
257}
258
259func (w *dnsWatcher) lookup() []*Update {
260 newAddrs := w.lookupSRV()
261 if newAddrs == nil {
262 // If failed to get any balancer address (either no corresponding SRV for the
263 // target, or caused by failure during resolution/parsing of the balancer target),
264 // return any A record info available.
265 newAddrs = w.lookupHost()
266 }
267 result := w.compileUpdate(newAddrs)
268 w.curAddrs = newAddrs
269 return result
270}
271
272// Next returns the resolved address update(delta) for the target. If there's no
273// change, it will sleep for 30 mins and try to resolve again after that.
274func (w *dnsWatcher) Next() ([]*Update, error) {
275 for {
276 select {
277 case <-w.ctx.Done():
278 return nil, errWatcherClose
279 case <-w.t.C:
280 }
281 result := w.lookup()
282 // Next lookup should happen after an interval defined by w.r.freq.
283 w.t.Reset(w.r.freq)
284 if len(result) > 0 {
285 return result, nil
286 }
287 }
288}
289
290func (w *dnsWatcher) Close() {
291 w.cancel()
292}
diff --git a/vendor/google.golang.org/grpc/naming/go17.go b/vendor/google.golang.org/grpc/naming/go17.go
new file mode 100644
index 0000000..a537b08
--- /dev/null
+++ b/vendor/google.golang.org/grpc/naming/go17.go
@@ -0,0 +1,34 @@
1// +build go1.6, !go1.8
2
3/*
4 *
5 * Copyright 2017 gRPC authors.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */
20
21package naming
22
23import (
24 "net"
25
26 "golang.org/x/net/context"
27)
28
29var (
30 lookupHost = func(ctx context.Context, host string) ([]string, error) { return net.LookupHost(host) }
31 lookupSRV = func(ctx context.Context, service, proto, name string) (string, []*net.SRV, error) {
32 return net.LookupSRV(service, proto, name)
33 }
34)
diff --git a/vendor/google.golang.org/grpc/naming/go18.go b/vendor/google.golang.org/grpc/naming/go18.go
new file mode 100644
index 0000000..b5a0f84
--- /dev/null
+++ b/vendor/google.golang.org/grpc/naming/go18.go
@@ -0,0 +1,28 @@
1// +build go1.8
2
3/*
4 *
5 * Copyright 2017 gRPC authors.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */
20
21package naming
22
23import "net"
24
25var (
26 lookupHost = net.DefaultResolver.LookupHost
27 lookupSRV = net.DefaultResolver.LookupSRV
28)
diff --git a/vendor/google.golang.org/grpc/naming/naming.go b/vendor/google.golang.org/grpc/naming/naming.go
new file mode 100644
index 0000000..1af7e32
--- /dev/null
+++ b/vendor/google.golang.org/grpc/naming/naming.go
@@ -0,0 +1,59 @@
1/*
2 *
3 * Copyright 2014 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// Package naming defines the naming API and related data structures for gRPC.
20// The interface is EXPERIMENTAL and may be suject to change.
21package naming
22
23// Operation defines the corresponding operations for a name resolution change.
24type Operation uint8
25
26const (
27 // Add indicates a new address is added.
28 Add Operation = iota
29 // Delete indicates an exisiting address is deleted.
30 Delete
31)
32
33// Update defines a name resolution update. Notice that it is not valid having both
34// empty string Addr and nil Metadata in an Update.
35type Update struct {
36 // Op indicates the operation of the update.
37 Op Operation
38 // Addr is the updated address. It is empty string if there is no address update.
39 Addr string
40 // Metadata is the updated metadata. It is nil if there is no metadata update.
41 // Metadata is not required for a custom naming implementation.
42 Metadata interface{}
43}
44
45// Resolver creates a Watcher for a target to track its resolution changes.
46type Resolver interface {
47 // Resolve creates a Watcher for target.
48 Resolve(target string) (Watcher, error)
49}
50
51// Watcher watches for the updates on the specified target.
52type Watcher interface {
53 // Next blocks until an update or error happens. It may return one or more
54 // updates. The first call should get the full set of the results. It should
55 // return an error if and only if Watcher cannot recover.
56 Next() ([]*Update, error)
57 // Close closes the Watcher.
58 Close()
59}