Browse code

bump google.golang.org/api v0.8.0

full diff: https://github.com/googleapis/google-api-go-client/compare/de943baf05a022a8f921b544b7827bacaba1aed5...v0.8.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2019/08/26 22:59:14
Showing 49 changed files
... ...
@@ -116,7 +116,7 @@ github.com/bsphere/le_go                            7a984a84b5492ae539b79b62fb4a
116 116
 
117 117
 # gcplogs deps
118 118
 golang.org/x/oauth2                                 bf48bf16ab8d622ce64ec6ce98d2c98f916b6303
119
-google.golang.org/api                               de943baf05a022a8f921b544b7827bacaba1aed5
119
+google.golang.org/api                               dec2ee309f5b09fc59bc40676447c15736284d78 # v0.8.0
120 120
 github.com/golang/groupcache                        869f871628b6baa9cfbc11732cdf6546b17c1298
121 121
 go.opencensus.io                                    d835ff86be02193d324330acdb7d65546b05f814 # v0.22.3
122 122
 cloud.google.com/go                                 ceeb313ad77b789a7fa5287b36a1d127b69b7093 # v0.44.3
123 123
deleted file mode 100644
... ...
@@ -1,94 +0,0 @@
1
-// Copyright 2018, OpenCensus Authors
2
-//
3
-// Licensed under the Apache License, Version 2.0 (the "License");
4
-// you may not use this file except in compliance with the License.
5
-// You may obtain a copy of the License at
6
-//
7
-//     http://www.apache.org/licenses/LICENSE-2.0
8
-//
9
-// Unless required by applicable law or agreed to in writing, software
10
-// distributed under the License is distributed on an "AS IS" BASIS,
11
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
-// See the License for the specific language governing permissions and
13
-// limitations under the License.
14
-
15
-// Package propagation implement X-Cloud-Trace-Context header propagation used
16
-// by Google Cloud products.
17
-package propagation // import "go.opencensus.io/exporter/stackdriver/propagation"
18
-
19
-import (
20
-	"encoding/binary"
21
-	"encoding/hex"
22
-	"fmt"
23
-	"net/http"
24
-	"strconv"
25
-	"strings"
26
-
27
-	"go.opencensus.io/trace"
28
-	"go.opencensus.io/trace/propagation"
29
-)
30
-
31
-const (
32
-	httpHeaderMaxSize = 200
33
-	httpHeader        = `X-Cloud-Trace-Context`
34
-)
35
-
36
-var _ propagation.HTTPFormat = (*HTTPFormat)(nil)
37
-
38
-// HTTPFormat implements propagation.HTTPFormat to propagate
39
-// traces in HTTP headers for Google Cloud Platform and Stackdriver Trace.
40
-type HTTPFormat struct{}
41
-
42
-// SpanContextFromRequest extracts a Stackdriver Trace span context from incoming requests.
43
-func (f *HTTPFormat) SpanContextFromRequest(req *http.Request) (sc trace.SpanContext, ok bool) {
44
-	h := req.Header.Get(httpHeader)
45
-	// See https://cloud.google.com/trace/docs/faq for the header HTTPFormat.
46
-	// Return if the header is empty or missing, or if the header is unreasonably
47
-	// large, to avoid making unnecessary copies of a large string.
48
-	if h == "" || len(h) > httpHeaderMaxSize {
49
-		return trace.SpanContext{}, false
50
-	}
51
-
52
-	// Parse the trace id field.
53
-	slash := strings.Index(h, `/`)
54
-	if slash == -1 {
55
-		return trace.SpanContext{}, false
56
-	}
57
-	tid, h := h[:slash], h[slash+1:]
58
-
59
-	buf, err := hex.DecodeString(tid)
60
-	if err != nil {
61
-		return trace.SpanContext{}, false
62
-	}
63
-	copy(sc.TraceID[:], buf)
64
-
65
-	// Parse the span id field.
66
-	spanstr := h
67
-	semicolon := strings.Index(h, `;`)
68
-	if semicolon != -1 {
69
-		spanstr, h = h[:semicolon], h[semicolon+1:]
70
-	}
71
-	sid, err := strconv.ParseUint(spanstr, 10, 64)
72
-	if err != nil {
73
-		return trace.SpanContext{}, false
74
-	}
75
-	binary.BigEndian.PutUint64(sc.SpanID[:], sid)
76
-
77
-	// Parse the options field, options field is optional.
78
-	if !strings.HasPrefix(h, "o=") {
79
-		return sc, true
80
-	}
81
-	o, err := strconv.ParseUint(h[2:], 10, 64)
82
-	if err != nil {
83
-		return trace.SpanContext{}, false
84
-	}
85
-	sc.TraceOptions = trace.TraceOptions(o)
86
-	return sc, true
87
-}
88
-
89
-// SpanContextToRequest modifies the given request to include a Stackdriver Trace header.
90
-func (f *HTTPFormat) SpanContextToRequest(sc trace.SpanContext, req *http.Request) {
91
-	sid := binary.BigEndian.Uint64(sc.SpanID[:])
92
-	header := fmt.Sprintf("%s/%d;o=%d", hex.EncodeToString(sc.TraceID[:]), sid, int64(sc.TraceOptions))
93
-	req.Header.Set(httpHeader, header)
94
-}
... ...
@@ -29,9 +29,9 @@ func main() {
29 29
 * For a longer tutorial, see the [Getting Started guide](https://github.com/google/google-api-go-client/blob/master/GettingStarted.md).
30 30
 * For examples, see the [examples directory](https://github.com/google/google-api-go-client/tree/master/examples).
31 31
 * For support, use the [golang-nuts](https://groups.google.com/group/golang-nuts) mailing list.
32
+* The code review instance may be found [here](https://code-review.googlesource.com).
32 33
 
33 34
 ## Status
34
-[![Build Status](https://travis-ci.org/google/google-api-go-client.png)](https://travis-ci.org/google/google-api-go-client)
35 35
 [![GoDoc](https://godoc.org/google.golang.org/api?status.svg)](https://godoc.org/google.golang.org/api)
36 36
 
37 37
 These are auto-generated Go libraries from the Google Discovery Service's JSON description files of the available "new style" Google APIs.
... ...
@@ -43,7 +43,7 @@ These client libraries are officially supported by Google.  However, the librari
43 43
 
44 44
 If you're working with Google Cloud Platform APIs such as Datastore or Pub/Sub,
45 45
 consider using the
46
-[Cloud Client Libraries for Go](https://github.com/GoogleCloudPlatform/google-cloud-go)
46
+[Cloud Client Libraries for Go](https://github.com/googleapis/google-cloud-go)
47 47
 instead. These are the new and
48 48
 idiomatic Go libraries targeted specifically at Google Cloud Platform Services.
49 49
 
... ...
@@ -71,7 +71,7 @@ Some credentials types require you to specify scopes, and service entry points m
71 71
 
72 72
 ```go
73 73
 import (
74
-        "golang.org/x/net/context"
74
+        "context"
75 75
         "golang.org/x/oauth2/google"
76 76
         "google.golang.org/api/compute/v1"
77 77
 )
78 78
new file mode 100644
... ...
@@ -0,0 +1,23 @@
0
+module google.golang.org/api
1
+
2
+go 1.9
3
+
4
+require (
5
+	cloud.google.com/go v0.38.0 // indirect
6
+	github.com/golang/protobuf v1.3.1 // indirect
7
+	github.com/google/go-cmp v0.3.0
8
+	github.com/googleapis/gax-go/v2 v2.0.5
9
+	github.com/hashicorp/golang-lru v0.5.1 // indirect
10
+	go.opencensus.io v0.21.0
11
+	golang.org/x/lint v0.0.0-20190409202823-959b441ac422
12
+	golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c // indirect
13
+	golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
14
+	golang.org/x/sync v0.0.0-20190423024810-112230192c58
15
+	golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b
16
+	golang.org/x/text v0.3.2 // indirect
17
+	golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c
18
+	google.golang.org/appengine v1.5.0
19
+	google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873
20
+	google.golang.org/grpc v1.20.1
21
+	honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a
22
+)
... ...
@@ -1,4 +1,4 @@
1
-// Copyright 2017 Google Inc. All Rights Reserved.
1
+// Copyright 2017 Google LLC
2 2
 //
3 3
 // Licensed under the Apache License, Version 2.0 (the "License");
4 4
 // you may not use this file except in compliance with the License.
... ...
@@ -15,28 +15,88 @@
15 15
 package internal
16 16
 
17 17
 import (
18
+	"context"
19
+	"encoding/json"
18 20
 	"fmt"
19 21
 	"io/ioutil"
20 22
 
21
-	"golang.org/x/net/context"
23
+	"golang.org/x/oauth2"
24
+
22 25
 	"golang.org/x/oauth2/google"
23 26
 )
24 27
 
25 28
 // Creds returns credential information obtained from DialSettings, or if none, then
26 29
 // it returns default credential information.
27
-func Creds(ctx context.Context, ds *DialSettings) (*google.DefaultCredentials, error) {
30
+func Creds(ctx context.Context, ds *DialSettings) (*google.Credentials, error) {
28 31
 	if ds.Credentials != nil {
29 32
 		return ds.Credentials, nil
30 33
 	}
34
+	if ds.CredentialsJSON != nil {
35
+		return credentialsFromJSON(ctx, ds.CredentialsJSON, ds.Endpoint, ds.Scopes, ds.Audiences)
36
+	}
31 37
 	if ds.CredentialsFile != "" {
32 38
 		data, err := ioutil.ReadFile(ds.CredentialsFile)
33 39
 		if err != nil {
34 40
 			return nil, fmt.Errorf("cannot read credentials file: %v", err)
35 41
 		}
36
-		return google.CredentialsFromJSON(ctx, data, ds.Scopes...)
42
+		return credentialsFromJSON(ctx, data, ds.Endpoint, ds.Scopes, ds.Audiences)
37 43
 	}
38 44
 	if ds.TokenSource != nil {
39
-		return &google.DefaultCredentials{TokenSource: ds.TokenSource}, nil
45
+		return &google.Credentials{TokenSource: ds.TokenSource}, nil
46
+	}
47
+	cred, err := google.FindDefaultCredentials(ctx, ds.Scopes...)
48
+	if err != nil {
49
+		return nil, err
50
+	}
51
+	if len(cred.JSON) > 0 {
52
+		return credentialsFromJSON(ctx, cred.JSON, ds.Endpoint, ds.Scopes, ds.Audiences)
53
+	}
54
+	// For GAE and GCE, the JSON is empty so return the default credentials directly.
55
+	return cred, nil
56
+}
57
+
58
+// JSON key file type.
59
+const (
60
+	serviceAccountKey = "service_account"
61
+)
62
+
63
+// credentialsFromJSON returns a google.Credentials based on the input.
64
+//
65
+// - If the JSON is a service account and no scopes provided, returns self-signed JWT auth flow
66
+// - Otherwise, returns OAuth 2.0 flow.
67
+func credentialsFromJSON(ctx context.Context, data []byte, endpoint string, scopes []string, audiences []string) (*google.Credentials, error) {
68
+	cred, err := google.CredentialsFromJSON(ctx, data, scopes...)
69
+	if err != nil {
70
+		return nil, err
71
+	}
72
+	if len(data) > 0 && len(scopes) == 0 {
73
+		var f struct {
74
+			Type string `json:"type"`
75
+			// The rest JSON fields are omitted because they are not used.
76
+		}
77
+		if err := json.Unmarshal(cred.JSON, &f); err != nil {
78
+			return nil, err
79
+		}
80
+		if f.Type == serviceAccountKey {
81
+			ts, err := selfSignedJWTTokenSource(data, endpoint, audiences)
82
+			if err != nil {
83
+				return nil, err
84
+			}
85
+			cred.TokenSource = ts
86
+		}
87
+	}
88
+	return cred, err
89
+}
90
+
91
+func selfSignedJWTTokenSource(data []byte, endpoint string, audiences []string) (oauth2.TokenSource, error) {
92
+	// Use the API endpoint as the default audience
93
+	audience := endpoint
94
+	if len(audiences) > 0 {
95
+		// TODO(shinfan): Update golang oauth to support multiple audiences.
96
+		if len(audiences) > 1 {
97
+			return nil, fmt.Errorf("multiple audiences support is not implemented")
98
+		}
99
+		audience = audiences[0]
40 100
 	}
41
-	return google.FindDefaultCredentials(ctx, ds.Scopes...)
101
+	return google.JWTAccessTokenSourceFromJSON(data, audience)
42 102
 }
... ...
@@ -1,4 +1,4 @@
1
-// Copyright 2016 Google Inc. All Rights Reserved.
1
+// Copyright 2016 Google LLC
2 2
 //
3 3
 // Licensed under the Apache License, Version 2.0 (the "License");
4 4
 // you may not use this file except in compliance with the License.
... ...
@@ -16,6 +16,7 @@ package internal
16 16
 
17 17
 import (
18 18
 	"errors"
19
+
19 20
 	"google.golang.org/grpc/naming"
20 21
 )
21 22
 
... ...
@@ -37,7 +38,7 @@ func NewPoolResolver(size int, o *DialSettings) *PoolResolver {
37 37
 // provided to NewPoolResolver.
38 38
 func (r *PoolResolver) Resolve(target string) (naming.Watcher, error) {
39 39
 	if r.dialOpt.Endpoint == "" {
40
-		return nil, errors.New("No endpoint configured")
40
+		return nil, errors.New("no endpoint configured")
41 41
 	}
42 42
 	addrs := make([]*naming.Update, 0, r.poolSize)
43 43
 	for i := 0; i < r.poolSize; i++ {
... ...
@@ -54,6 +55,7 @@ func (r *PoolResolver) Next() ([]*naming.Update, error) {
54 54
 	return <-r.ch, nil
55 55
 }
56 56
 
57
+// Close releases resources associated with the pool and causes Next to unblock.
57 58
 func (r *PoolResolver) Close() {
58 59
 	close(r.ch)
59 60
 }
... ...
@@ -1,4 +1,4 @@
1
-// Copyright 2017 Google Inc. All Rights Reserved.
1
+// Copyright 2017 Google LLC
2 2
 //
3 3
 // Licensed under the Apache License, Version 2.0 (the "License");
4 4
 // you may not use this file except in compliance with the License.
... ...
@@ -30,14 +30,21 @@ type DialSettings struct {
30 30
 	Endpoint        string
31 31
 	Scopes          []string
32 32
 	TokenSource     oauth2.TokenSource
33
-	Credentials     *google.DefaultCredentials
33
+	Credentials     *google.Credentials
34 34
 	CredentialsFile string // if set, Token Source is ignored.
35
+	CredentialsJSON []byte
35 36
 	UserAgent       string
36 37
 	APIKey          string
38
+	Audiences       []string
37 39
 	HTTPClient      *http.Client
38 40
 	GRPCDialOpts    []grpc.DialOption
39 41
 	GRPCConn        *grpc.ClientConn
40 42
 	NoAuth          bool
43
+
44
+	// Google API system parameters. For more information please read:
45
+	// https://cloud.google.com/apis/docs/system-parameters
46
+	QuotaProject  string
47
+	RequestReason string
41 48
 }
42 49
 
43 50
 // Validate reports an error if ds is invalid.
... ...
@@ -49,7 +56,27 @@ func (ds *DialSettings) Validate() error {
49 49
 	// Credentials should not appear with other options.
50 50
 	// We currently allow TokenSource and CredentialsFile to coexist.
51 51
 	// TODO(jba): make TokenSource & CredentialsFile an error (breaking change).
52
-	if ds.Credentials != nil && (ds.APIKey != "" || ds.TokenSource != nil || ds.CredentialsFile != "") {
52
+	nCreds := 0
53
+	if ds.Credentials != nil {
54
+		nCreds++
55
+	}
56
+	if ds.CredentialsJSON != nil {
57
+		nCreds++
58
+	}
59
+	if ds.CredentialsFile != "" {
60
+		nCreds++
61
+	}
62
+	if ds.APIKey != "" {
63
+		nCreds++
64
+	}
65
+	if ds.TokenSource != nil {
66
+		nCreds++
67
+	}
68
+	if len(ds.Scopes) > 0 && len(ds.Audiences) > 0 {
69
+		return errors.New("WithScopes is incompatible with WithAudience")
70
+	}
71
+	// Accept only one form of credentials, except we allow TokenSource and CredentialsFile for backwards compatibility.
72
+	if nCreds > 1 && !(nCreds == 2 && ds.TokenSource != nil && ds.CredentialsFile != "") {
53 73
 		return errors.New("multiple credential options provided")
54 74
 	}
55 75
 	if ds.HTTPClient != nil && ds.GRPCConn != nil {
... ...
@@ -58,5 +85,12 @@ func (ds *DialSettings) Validate() error {
58 58
 	if ds.HTTPClient != nil && ds.GRPCDialOpts != nil {
59 59
 		return errors.New("WithHTTPClient is incompatible with gRPC dial options")
60 60
 	}
61
+	if ds.HTTPClient != nil && ds.QuotaProject != "" {
62
+		return errors.New("WithHTTPClient is incompatible with QuotaProject")
63
+	}
64
+	if ds.HTTPClient != nil && ds.RequestReason != "" {
65
+		return errors.New("WithHTTPClient is incompatible with RequestReason")
66
+	}
67
+
61 68
 	return nil
62 69
 }
... ...
@@ -1,4 +1,4 @@
1
-// Copyright 2016 Google Inc. All Rights Reserved.
1
+// Copyright 2016 Google LLC
2 2
 //
3 3
 // Licensed under the Apache License, Version 2.0 (the "License");
4 4
 // you may not use this file except in compliance with the License.
... ...
@@ -1,4 +1,4 @@
1
-// Copyright 2018 Google Inc. All Rights Reserved.
1
+// Copyright 2018 Google LLC
2 2
 //
3 3
 // Licensed under the Apache License, Version 2.0 (the "License");
4 4
 // you may not use this file except in compliance with the License.
... ...
@@ -27,6 +27,7 @@ func (w *withCreds) Apply(o *internal.DialSettings) {
27 27
 	o.Credentials = (*google.Credentials)(w)
28 28
 }
29 29
 
30
+// WithCredentials returns a ClientOption that authenticates API calls.
30 31
 func WithCredentials(creds *google.Credentials) ClientOption {
31 32
 	return (*withCreds)(creds)
32 33
 }
... ...
@@ -1,4 +1,4 @@
1
-// Copyright 2018 Google Inc. All Rights Reserved.
1
+// Copyright 2018 Google LLC
2 2
 //
3 3
 // Licensed under the Apache License, Version 2.0 (the "License");
4 4
 // you may not use this file except in compliance with the License.
... ...
@@ -1,4 +1,4 @@
1
-// Copyright 2017 Google Inc. All Rights Reserved.
1
+// Copyright 2017 Google LLC
2 2
 //
3 3
 // Licensed under the Apache License, Version 2.0 (the "License");
4 4
 // you may not use this file except in compliance with the License.
... ...
@@ -61,6 +61,20 @@ func WithServiceAccountFile(filename string) ClientOption {
61 61
 	return WithCredentialsFile(filename)
62 62
 }
63 63
 
64
+// WithCredentialsJSON returns a ClientOption that authenticates
65
+// API calls with the given service account or refresh token JSON
66
+// credentials.
67
+func WithCredentialsJSON(p []byte) ClientOption {
68
+	return withCredentialsJSON(p)
69
+}
70
+
71
+type withCredentialsJSON []byte
72
+
73
+func (w withCredentialsJSON) Apply(o *internal.DialSettings) {
74
+	o.CredentialsJSON = make([]byte, len(w))
75
+	copy(o.CredentialsJSON, w)
76
+}
77
+
64 78
 // WithEndpoint returns a ClientOption that overrides the default endpoint
65 79
 // to be used for a service.
66 80
 func WithEndpoint(url string) ClientOption {
... ...
@@ -82,9 +96,8 @@ func WithScopes(scope ...string) ClientOption {
82 82
 type withScopes []string
83 83
 
84 84
 func (w withScopes) Apply(o *internal.DialSettings) {
85
-	s := make([]string, len(w))
86
-	copy(s, w)
87
-	o.Scopes = s
85
+	o.Scopes = make([]string, len(w))
86
+	copy(o.Scopes, w)
88 87
 }
89 88
 
90 89
 // WithUserAgent returns a ClientOption that sets the User-Agent.
... ...
@@ -153,6 +166,9 @@ func (w withGRPCConnectionPool) Apply(o *internal.DialSettings) {
153 153
 
154 154
 // WithAPIKey returns a ClientOption that specifies an API key to be used
155 155
 // as the basis for authentication.
156
+//
157
+// API Keys can only be used for JSON-over-HTTP APIs, including those under
158
+// the import path google.golang.org/api/....
156 159
 func WithAPIKey(apiKey string) ClientOption {
157 160
 	return withAPIKey(apiKey)
158 161
 }
... ...
@@ -161,6 +177,19 @@ type withAPIKey string
161 161
 
162 162
 func (w withAPIKey) Apply(o *internal.DialSettings) { o.APIKey = string(w) }
163 163
 
164
+// WithAudiences returns a ClientOption that specifies an audience to be used
165
+// as the audience field ("aud") for the JWT token authentication.
166
+func WithAudiences(audience ...string) ClientOption {
167
+	return withAudiences(audience)
168
+}
169
+
170
+type withAudiences []string
171
+
172
+func (w withAudiences) Apply(o *internal.DialSettings) {
173
+	o.Audiences = make([]string, len(w))
174
+	copy(o.Audiences, w)
175
+}
176
+
164 177
 // WithoutAuthentication returns a ClientOption that specifies that no
165 178
 // authentication should be used. It is suitable only for testing and for
166 179
 // accessing public resources, like public Google Cloud Storage buckets.
... ...
@@ -173,3 +202,34 @@ func WithoutAuthentication() ClientOption {
173 173
 type withoutAuthentication struct{}
174 174
 
175 175
 func (w withoutAuthentication) Apply(o *internal.DialSettings) { o.NoAuth = true }
176
+
177
+// WithQuotaProject returns a ClientOption that specifies the project used
178
+// for quota and billing purposes.
179
+//
180
+// For more information please read:
181
+// https://cloud.google.com/apis/docs/system-parameters
182
+func WithQuotaProject(quotaProject string) ClientOption {
183
+	return withQuotaProject(quotaProject)
184
+}
185
+
186
+type withQuotaProject string
187
+
188
+func (w withQuotaProject) Apply(o *internal.DialSettings) {
189
+	o.QuotaProject = string(w)
190
+}
191
+
192
+// WithRequestReason returns a ClientOption that specifies a reason for
193
+// making the request, which is intended to be recorded in audit logging.
194
+// An example reason would be a support-case ticket number.
195
+//
196
+// For more information please read:
197
+// https://cloud.google.com/apis/docs/system-parameters
198
+func WithRequestReason(requestReason string) ClientOption {
199
+	return withRequestReason(requestReason)
200
+}
201
+
202
+type withRequestReason string
203
+
204
+func (w withRequestReason) Apply(o *internal.DialSettings) {
205
+	o.RequestReason = string(w)
206
+}
... ...
@@ -1,4 +1,4 @@
1
-// Copyright 2016 Google Inc. All Rights Reserved.
1
+// Copyright 2016 Google LLC
2 2
 //
3 3
 // Licensed under the Apache License, Version 2.0 (the "License");
4 4
 // you may not use this file except in compliance with the License.
... ...
@@ -22,13 +22,13 @@
22 22
 package bundler
23 23
 
24 24
 import (
25
+	"context"
25 26
 	"errors"
26 27
 	"math"
27 28
 	"reflect"
28 29
 	"sync"
29 30
 	"time"
30 31
 
31
-	"golang.org/x/net/context"
32 32
 	"golang.org/x/sync/semaphore"
33 33
 )
34 34
 
... ...
@@ -1,4 +1,4 @@
1
-// Copyright 2015 Google Inc. All Rights Reserved.
1
+// Copyright 2015 Google LLC
2 2
 //
3 3
 // Licensed under the Apache License, Version 2.0 (the "License");
4 4
 // you may not use this file except in compliance with the License.
... ...
@@ -12,15 +12,12 @@
12 12
 // See the License for the specific language governing permissions and
13 13
 // limitations under the License.
14 14
 
15
-// Package transport supports network connections to HTTP and GRPC servers.
16
-// This package is not intended for use by end developers. Use the
17
-// google.golang.org/api/option package to configure API clients.
18 15
 package transport
19 16
 
20 17
 import (
18
+	"context"
21 19
 	"net/http"
22 20
 
23
-	"golang.org/x/net/context"
24 21
 	"google.golang.org/grpc"
25 22
 
26 23
 	"google.golang.org/api/option"
27 24
new file mode 100644
... ...
@@ -0,0 +1,21 @@
0
+// Copyright 2019 Google LLC
1
+//
2
+// Licensed under the Apache License, Version 2.0 (the "License");
3
+// you may not use this file except in compliance with the License.
4
+// You may obtain a copy of the License at
5
+//
6
+//      http://www.apache.org/licenses/LICENSE-2.0
7
+//
8
+// Unless required by applicable law or agreed to in writing, software
9
+// distributed under the License is distributed on an "AS IS" BASIS,
10
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+// See the License for the specific language governing permissions and
12
+// limitations under the License.
13
+
14
+// Package transport provides utility methods for creating authenticated
15
+// transports to Google's HTTP and gRPC APIs. It is intended to be used in
16
+// conjunction with google.golang.org/api/option.
17
+//
18
+// This package is not intended for use by end developers. Use the
19
+// google.golang.org/api/option package to configure API clients.
20
+package transport
... ...
@@ -1,4 +1,4 @@
1
-// Copyright 2018 Google Inc. All Rights Reserved.
1
+// Copyright 2018 Google LLC
2 2
 //
3 3
 // Licensed under the Apache License, Version 2.0 (the "License");
4 4
 // you may not use this file except in compliance with the License.
... ...
@@ -17,7 +17,8 @@
17 17
 package transport
18 18
 
19 19
 import (
20
-	"golang.org/x/net/context"
20
+	"context"
21
+
21 22
 	"golang.org/x/oauth2/google"
22 23
 	"google.golang.org/api/internal"
23 24
 	"google.golang.org/api/option"
... ...
@@ -1,4 +1,4 @@
1
-// Copyright 2015 Google Inc. All Rights Reserved.
1
+// Copyright 2015 Google LLC
2 2
 //
3 3
 // Licensed under the Apache License, Version 2.0 (the "License");
4 4
 // you may not use this file except in compliance with the License.
... ...
@@ -12,25 +12,37 @@
12 12
 // See the License for the specific language governing permissions and
13 13
 // limitations under the License.
14 14
 
15
-// Package transport/grpc supports network connections to GRPC servers.
15
+// Package grpc supports network connections to GRPC servers.
16 16
 // This package is not intended for use by end developers. Use the
17 17
 // google.golang.org/api/option package to configure API clients.
18 18
 package grpc
19 19
 
20 20
 import (
21
+	"context"
21 22
 	"errors"
23
+	"log"
24
+	"os"
25
+	"strings"
22 26
 
23
-	"golang.org/x/net/context"
27
+	"go.opencensus.io/plugin/ocgrpc"
28
+	"golang.org/x/oauth2"
24 29
 	"google.golang.org/api/internal"
25 30
 	"google.golang.org/api/option"
26 31
 	"google.golang.org/grpc"
27 32
 	"google.golang.org/grpc/credentials"
33
+	grpcgoogle "google.golang.org/grpc/credentials/google"
28 34
 	"google.golang.org/grpc/credentials/oauth"
35
+
36
+	// Install grpclb, which is required for direct path.
37
+	_ "google.golang.org/grpc/balancer/grpclb"
29 38
 )
30 39
 
31 40
 // Set at init time by dial_appengine.go. If nil, we're not on App Engine.
32 41
 var appengineDialerHook func(context.Context) grpc.DialOption
33 42
 
43
+// Set at init time by dial_socketopt.go. If nil, socketopt is not supported.
44
+var timeoutDialerOption grpc.DialOption
45
+
34 46
 // Dial returns a GRPC connection for use communicating with a Google cloud
35 47
 // service, configured with the given ClientOptions.
36 48
 func Dial(ctx context.Context, opts ...option.ClientOption) (*grpc.ClientConn, error) {
... ...
@@ -62,19 +74,47 @@ func dial(ctx context.Context, insecure bool, opts []option.ClientOption) (*grpc
62 62
 	if insecure {
63 63
 		grpcOpts = []grpc.DialOption{grpc.WithInsecure()}
64 64
 	} else if !o.NoAuth {
65
+		if o.APIKey != "" {
66
+			log.Print("API keys are not supported for gRPC APIs. Remove the WithAPIKey option from your client-creating call.")
67
+		}
65 68
 		creds, err := internal.Creds(ctx, &o)
66 69
 		if err != nil {
67 70
 			return nil, err
68 71
 		}
69
-		grpcOpts = []grpc.DialOption{
70
-			grpc.WithPerRPCCredentials(oauth.TokenSource{creds.TokenSource}),
71
-			grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, "")),
72
+		// Attempt Direct Path only if:
73
+		// * The endpoint is a host:port (or dns:///host:port).
74
+		// * Credentials are obtained via GCE metadata server, using the default
75
+		//   service account.
76
+		// * Opted in via GOOGLE_CLOUD_ENABLE_DIRECT_PATH environment variable.
77
+		//   For example, GOOGLE_CLOUD_ENABLE_DIRECT_PATH=spanner,pubsub
78
+		if isDirectPathEnabled(o.Endpoint) && isTokenSourceDirectPathCompatible(creds.TokenSource) {
79
+			if !strings.HasPrefix(o.Endpoint, "dns:///") {
80
+				o.Endpoint = "dns:///" + o.Endpoint
81
+			}
82
+			grpcOpts = []grpc.DialOption{
83
+				grpc.WithCredentialsBundle(
84
+					grpcgoogle.NewComputeEngineCredentials(),
85
+				),
86
+			}
87
+			// TODO(cbro): add support for system parameters (quota project, request reason) via chained interceptor.
88
+		} else {
89
+			grpcOpts = []grpc.DialOption{
90
+				grpc.WithPerRPCCredentials(grpcTokenSource{
91
+					TokenSource:   oauth.TokenSource{creds.TokenSource},
92
+					quotaProject:  o.QuotaProject,
93
+					requestReason: o.RequestReason,
94
+				}),
95
+				grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, "")),
96
+			}
72 97
 		}
73 98
 	}
99
+
74 100
 	if appengineDialerHook != nil {
75 101
 		// Use the Socket API on App Engine.
102
+		// appengine dialer will override socketopt dialer
76 103
 		grpcOpts = append(grpcOpts, appengineDialerHook(ctx))
77 104
 	}
105
+
78 106
 	// Add tracing, but before the other options, so that clients can override the
79 107
 	// gRPC stats handler.
80 108
 	// This assumes that gRPC options are processed in order, left to right.
... ...
@@ -83,5 +123,87 @@ func dial(ctx context.Context, insecure bool, opts []option.ClientOption) (*grpc
83 83
 	if o.UserAgent != "" {
84 84
 		grpcOpts = append(grpcOpts, grpc.WithUserAgent(o.UserAgent))
85 85
 	}
86
+
87
+	// TODO(weiranf): This socketopt dialer will be used by default at some
88
+	// point when isDirectPathEnabled will default to true, we guard it by
89
+	// the Directpath env var for now once we can introspect user defined
90
+	// dialer (https://github.com/grpc/grpc-go/issues/2795).
91
+	if timeoutDialerOption != nil && isDirectPathEnabled(o.Endpoint) {
92
+		grpcOpts = append(grpcOpts, timeoutDialerOption)
93
+	}
94
+
86 95
 	return grpc.DialContext(ctx, o.Endpoint, grpcOpts...)
87 96
 }
97
+
98
+func addOCStatsHandler(opts []grpc.DialOption) []grpc.DialOption {
99
+	return append(opts, grpc.WithStatsHandler(&ocgrpc.ClientHandler{}))
100
+}
101
+
102
+// grpcTokenSource supplies PerRPCCredentials from an oauth.TokenSource.
103
+type grpcTokenSource struct {
104
+	oauth.TokenSource
105
+
106
+	// Additional metadata attached as headers.
107
+	quotaProject  string
108
+	requestReason string
109
+}
110
+
111
+// GetRequestMetadata gets the request metadata as a map from a grpcTokenSource.
112
+func (ts grpcTokenSource) GetRequestMetadata(ctx context.Context, uri ...string) (
113
+	map[string]string, error) {
114
+	metadata, err := ts.TokenSource.GetRequestMetadata(ctx, uri...)
115
+	if err != nil {
116
+		return nil, err
117
+	}
118
+
119
+	// Attach system parameter
120
+	if ts.quotaProject != "" {
121
+		metadata["X-goog-user-project"] = ts.quotaProject
122
+	}
123
+	if ts.requestReason != "" {
124
+		metadata["X-goog-request-reason"] = ts.requestReason
125
+	}
126
+	return metadata, nil
127
+}
128
+
129
+func isTokenSourceDirectPathCompatible(ts oauth2.TokenSource) bool {
130
+	if ts == nil {
131
+		return false
132
+	}
133
+	tok, err := ts.Token()
134
+	if err != nil {
135
+		return false
136
+	}
137
+	if tok == nil {
138
+		return false
139
+	}
140
+	if source, _ := tok.Extra("oauth2.google.tokenSource").(string); source != "compute-metadata" {
141
+		return false
142
+	}
143
+	if acct, _ := tok.Extra("oauth2.google.serviceAccount").(string); acct != "default" {
144
+		return false
145
+	}
146
+	return true
147
+}
148
+
149
+func isDirectPathEnabled(endpoint string) bool {
150
+	// Only host:port is supported, not other schemes (e.g., "tcp://" or "unix://").
151
+	// Also don't try direct path if the user has chosen an alternate name resolver
152
+	// (i.e., via ":///" prefix).
153
+	//
154
+	// TODO(cbro): once gRPC has introspectible options, check the user hasn't
155
+	// provided a custom dialer in gRPC options.
156
+	if strings.Contains(endpoint, "://") && !strings.HasPrefix(endpoint, "dns:///") {
157
+		return false
158
+	}
159
+
160
+	// Only try direct path if the user has opted in via the environment variable.
161
+	whitelist := strings.Split(os.Getenv("GOOGLE_CLOUD_ENABLE_DIRECT_PATH"), ",")
162
+	for _, api := range whitelist {
163
+		// Ignore empty string since an empty env variable splits into [""]
164
+		if api != "" && strings.Contains(endpoint, api) {
165
+			return true
166
+		}
167
+	}
168
+	return false
169
+}
... ...
@@ -1,4 +1,4 @@
1
-// Copyright 2016 Google Inc. All Rights Reserved.
1
+// Copyright 2016 Google LLC
2 2
 //
3 3
 // Licensed under the Apache License, Version 2.0 (the "License");
4 4
 // you may not use this file except in compliance with the License.
... ...
@@ -17,10 +17,10 @@
17 17
 package grpc
18 18
 
19 19
 import (
20
+	"context"
20 21
 	"net"
21 22
 	"time"
22 23
 
23
-	"golang.org/x/net/context"
24 24
 	"google.golang.org/appengine"
25 25
 	"google.golang.org/appengine/socket"
26 26
 	"google.golang.org/grpc"
27 27
new file mode 100644
... ...
@@ -0,0 +1,59 @@
0
+// Copyright 2019 Google LLC
1
+//
2
+// Licensed under the Apache License, Version 2.0 (the "License");
3
+// you may not use this file except in compliance with the License.
4
+// You may obtain a copy of the License at
5
+//
6
+//      http://www.apache.org/licenses/LICENSE-2.0
7
+//
8
+// Unless required by applicable law or agreed to in writing, software
9
+// distributed under the License is distributed on an "AS IS" BASIS,
10
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+// See the License for the specific language governing permissions and
12
+// limitations under the License.
13
+
14
+// +build go1.11,linux
15
+
16
+package grpc
17
+
18
+import (
19
+	"context"
20
+	"net"
21
+	"syscall"
22
+
23
+	"golang.org/x/sys/unix"
24
+	"google.golang.org/grpc"
25
+)
26
+
27
+const (
28
+	// defaultTCPUserTimeout is the default TCP_USER_TIMEOUT socket option. By
29
+	// default is 20 seconds.
30
+	tcpUserTimeoutMilliseconds = 20000
31
+)
32
+
33
+func init() {
34
+	// timeoutDialerOption is a grpc.DialOption that contains dialer with
35
+	// socket option TCP_USER_TIMEOUT. This dialer requires go versions 1.11+.
36
+	timeoutDialerOption = grpc.WithContextDialer(dialTCPUserTimeout)
37
+}
38
+
39
+func dialTCPUserTimeout(ctx context.Context, addr string) (net.Conn, error) {
40
+	control := func(network, address string, c syscall.RawConn) error {
41
+		var syscallErr error
42
+		controlErr := c.Control(func(fd uintptr) {
43
+			syscallErr = syscall.SetsockoptInt(
44
+				int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, tcpUserTimeoutMilliseconds)
45
+		})
46
+		if syscallErr != nil {
47
+			return syscallErr
48
+		}
49
+		if controlErr != nil {
50
+			return controlErr
51
+		}
52
+		return nil
53
+	}
54
+	d := &net.Dialer{
55
+		Control: control,
56
+	}
57
+	return d.DialContext(ctx, "tcp", addr)
58
+}
0 59
deleted file mode 100644
... ...
@@ -1,26 +0,0 @@
1
-// Copyright 2018 Google Inc. All Rights Reserved.
2
-//
3
-// Licensed under the Apache License, Version 2.0 (the "License");
4
-// you may not use this file except in compliance with the License.
5
-// You may obtain a copy of the License at
6
-//
7
-//      http://www.apache.org/licenses/LICENSE-2.0
8
-//
9
-// Unless required by applicable law or agreed to in writing, software
10
-// distributed under the License is distributed on an "AS IS" BASIS,
11
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
-// See the License for the specific language governing permissions and
13
-// limitations under the License.
14
-
15
-// +build go1.8
16
-
17
-package grpc
18
-
19
-import (
20
-	"go.opencensus.io/plugin/ocgrpc"
21
-	"google.golang.org/grpc"
22
-)
23
-
24
-func addOCStatsHandler(opts []grpc.DialOption) []grpc.DialOption {
25
-	return append(opts, grpc.WithStatsHandler(&ocgrpc.ClientHandler{}))
26
-}
27 1
deleted file mode 100644
... ...
@@ -1,21 +0,0 @@
1
-// Copyright 2018 Google Inc. All Rights Reserved.
2
-//
3
-// Licensed under the Apache License, Version 2.0 (the "License");
4
-// you may not use this file except in compliance with the License.
5
-// You may obtain a copy of the License at
6
-//
7
-//      http://www.apache.org/licenses/LICENSE-2.0
8
-//
9
-// Unless required by applicable law or agreed to in writing, software
10
-// distributed under the License is distributed on an "AS IS" BASIS,
11
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
-// See the License for the specific language governing permissions and
13
-// limitations under the License.
14
-
15
-// +build !go1.8
16
-
17
-package grpc
18
-
19
-import "google.golang.org/grpc"
20
-
21
-func addOCStatsHandler(opts []grpc.DialOption) []grpc.DialOption { return opts }
... ...
@@ -1,4 +1,4 @@
1
-// Copyright 2015 Google Inc. All Rights Reserved.
1
+// Copyright 2015 Google LLC
2 2
 //
3 3
 // Licensed under the Apache License, Version 2.0 (the "License");
4 4
 // you may not use this file except in compliance with the License.
... ...
@@ -12,73 +12,109 @@
12 12
 // See the License for the specific language governing permissions and
13 13
 // limitations under the License.
14 14
 
15
-// Package transport/http supports network connections to HTTP servers.
15
+// Package http supports network connections to HTTP servers.
16 16
 // This package is not intended for use by end developers. Use the
17 17
 // google.golang.org/api/option package to configure API clients.
18 18
 package http
19 19
 
20 20
 import (
21
+	"context"
21 22
 	"errors"
22 23
 	"net/http"
23 24
 
24
-	"golang.org/x/net/context"
25
+	"go.opencensus.io/plugin/ochttp"
25 26
 	"golang.org/x/oauth2"
26 27
 	"google.golang.org/api/googleapi/transport"
27 28
 	"google.golang.org/api/internal"
28 29
 	"google.golang.org/api/option"
30
+	"google.golang.org/api/transport/http/internal/propagation"
29 31
 )
30 32
 
31 33
 // NewClient returns an HTTP client for use communicating with a Google cloud
32 34
 // service, configured with the given ClientOptions. It also returns the endpoint
33 35
 // for the service as specified in the options.
34 36
 func NewClient(ctx context.Context, opts ...option.ClientOption) (*http.Client, string, error) {
35
-	var o internal.DialSettings
36
-	for _, opt := range opts {
37
-		opt.Apply(&o)
37
+	settings, err := newSettings(opts)
38
+	if err != nil {
39
+		return nil, "", err
38 40
 	}
39
-	if err := o.Validate(); err != nil {
41
+	// TODO(cbro): consider injecting the User-Agent even if an explicit HTTP client is provided?
42
+	if settings.HTTPClient != nil {
43
+		return settings.HTTPClient, settings.Endpoint, nil
44
+	}
45
+	trans, err := newTransport(ctx, defaultBaseTransport(ctx), settings)
46
+	if err != nil {
40 47
 		return nil, "", err
41 48
 	}
42
-	if o.GRPCConn != nil {
43
-		return nil, "", errors.New("unsupported gRPC connection specified")
49
+	return &http.Client{Transport: trans}, settings.Endpoint, nil
50
+}
51
+
52
+// NewTransport creates an http.RoundTripper for use communicating with a Google
53
+// cloud service, configured with the given ClientOptions. Its RoundTrip method delegates to base.
54
+func NewTransport(ctx context.Context, base http.RoundTripper, opts ...option.ClientOption) (http.RoundTripper, error) {
55
+	settings, err := newSettings(opts)
56
+	if err != nil {
57
+		return nil, err
44 58
 	}
45
-	// TODO(cbro): consider injecting the User-Agent even if an explicit HTTP client is provided?
46
-	if o.HTTPClient != nil {
47
-		return o.HTTPClient, o.Endpoint, nil
59
+	if settings.HTTPClient != nil {
60
+		return nil, errors.New("transport/http: WithHTTPClient passed to NewTransport")
48 61
 	}
49
-	trans := baseTransport(ctx)
50
-	trans = userAgentTransport{
51
-		base:      trans,
52
-		userAgent: o.UserAgent,
62
+	return newTransport(ctx, base, settings)
63
+}
64
+
65
+func newTransport(ctx context.Context, base http.RoundTripper, settings *internal.DialSettings) (http.RoundTripper, error) {
66
+	trans := base
67
+	trans = parameterTransport{
68
+		base:          trans,
69
+		userAgent:     settings.UserAgent,
70
+		quotaProject:  settings.QuotaProject,
71
+		requestReason: settings.RequestReason,
53 72
 	}
54 73
 	trans = addOCTransport(trans)
55 74
 	switch {
56
-	case o.NoAuth:
75
+	case settings.NoAuth:
57 76
 		// Do nothing.
58
-	case o.APIKey != "":
77
+	case settings.APIKey != "":
59 78
 		trans = &transport.APIKey{
60 79
 			Transport: trans,
61
-			Key:       o.APIKey,
80
+			Key:       settings.APIKey,
62 81
 		}
63 82
 	default:
64
-		creds, err := internal.Creds(ctx, &o)
83
+		creds, err := internal.Creds(ctx, settings)
65 84
 		if err != nil {
66
-			return nil, "", err
85
+			return nil, err
67 86
 		}
68 87
 		trans = &oauth2.Transport{
69 88
 			Base:   trans,
70 89
 			Source: creds.TokenSource,
71 90
 		}
72 91
 	}
73
-	return &http.Client{Transport: trans}, o.Endpoint, nil
92
+	return trans, nil
74 93
 }
75 94
 
76
-type userAgentTransport struct {
77
-	userAgent string
78
-	base      http.RoundTripper
95
+func newSettings(opts []option.ClientOption) (*internal.DialSettings, error) {
96
+	var o internal.DialSettings
97
+	for _, opt := range opts {
98
+		opt.Apply(&o)
99
+	}
100
+	if err := o.Validate(); err != nil {
101
+		return nil, err
102
+	}
103
+	if o.GRPCConn != nil {
104
+		return nil, errors.New("unsupported gRPC connection specified")
105
+	}
106
+	return &o, nil
107
+}
108
+
109
+type parameterTransport struct {
110
+	userAgent     string
111
+	quotaProject  string
112
+	requestReason string
113
+
114
+	base http.RoundTripper
79 115
 }
80 116
 
81
-func (t userAgentTransport) RoundTrip(req *http.Request) (*http.Response, error) {
117
+func (t parameterTransport) RoundTrip(req *http.Request) (*http.Response, error) {
82 118
 	rt := t.base
83 119
 	if rt == nil {
84 120
 		return nil, errors.New("transport: no Transport specified")
... ...
@@ -92,18 +128,34 @@ func (t userAgentTransport) RoundTrip(req *http.Request) (*http.Response, error)
92 92
 		newReq.Header[k] = vv
93 93
 	}
94 94
 	// TODO(cbro): append to existing User-Agent header?
95
-	newReq.Header["User-Agent"] = []string{t.userAgent}
95
+	newReq.Header.Set("User-Agent", t.userAgent)
96
+
97
+	// Attach system parameters into the header
98
+	if t.quotaProject != "" {
99
+		newReq.Header.Set("X-Goog-User-Project", t.quotaProject)
100
+	}
101
+	if t.requestReason != "" {
102
+		newReq.Header.Set("X-Goog-Request-Reason", t.requestReason)
103
+	}
104
+
96 105
 	return rt.RoundTrip(&newReq)
97 106
 }
98 107
 
99 108
 // Set at init time by dial_appengine.go. If nil, we're not on App Engine.
100 109
 var appengineUrlfetchHook func(context.Context) http.RoundTripper
101 110
 
102
-// baseTransport returns the base HTTP transport.
111
+// defaultBaseTransport returns the base HTTP transport.
103 112
 // On App Engine, this is urlfetch.Transport, otherwise it's http.DefaultTransport.
104
-func baseTransport(ctx context.Context) http.RoundTripper {
113
+func defaultBaseTransport(ctx context.Context) http.RoundTripper {
105 114
 	if appengineUrlfetchHook != nil {
106 115
 		return appengineUrlfetchHook(ctx)
107 116
 	}
108 117
 	return http.DefaultTransport
109 118
 }
119
+
120
+func addOCTransport(trans http.RoundTripper) http.RoundTripper {
121
+	return &ochttp.Transport{
122
+		Base:        trans,
123
+		Propagation: &propagation.HTTPFormat{},
124
+	}
125
+}
... ...
@@ -1,4 +1,4 @@
1
-// Copyright 2016 Google Inc. All Rights Reserved.
1
+// Copyright 2016 Google LLC
2 2
 //
3 3
 // Licensed under the Apache License, Version 2.0 (the "License");
4 4
 // you may not use this file except in compliance with the License.
... ...
@@ -17,9 +17,9 @@
17 17
 package http
18 18
 
19 19
 import (
20
+	"context"
20 21
 	"net/http"
21 22
 
22
-	"golang.org/x/net/context"
23 23
 	"google.golang.org/appengine/urlfetch"
24 24
 )
25 25
 
26 26
deleted file mode 100644
... ...
@@ -1,31 +0,0 @@
1
-// Copyright 2018 Google Inc. All Rights Reserved.
2
-//
3
-// Licensed under the Apache License, Version 2.0 (the "License");
4
-// you may not use this file except in compliance with the License.
5
-// You may obtain a copy of the License at
6
-//
7
-//      http://www.apache.org/licenses/LICENSE-2.0
8
-//
9
-// Unless required by applicable law or agreed to in writing, software
10
-// distributed under the License is distributed on an "AS IS" BASIS,
11
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
-// See the License for the specific language governing permissions and
13
-// limitations under the License.
14
-
15
-// +build go1.8
16
-
17
-package http
18
-
19
-import (
20
-	"net/http"
21
-
22
-	"go.opencensus.io/exporter/stackdriver/propagation"
23
-	"go.opencensus.io/plugin/ochttp"
24
-)
25
-
26
-func addOCTransport(trans http.RoundTripper) http.RoundTripper {
27
-	return &ochttp.Transport{
28
-		Base:        trans,
29
-		Propagation: &propagation.HTTPFormat{},
30
-	}
31
-}
32 1
new file mode 100644
... ...
@@ -0,0 +1,96 @@
0
+// Copyright 2018 Google LLC
1
+//
2
+// Licensed under the Apache License, Version 2.0 (the "License");
3
+// you may not use this file except in compliance with the License.
4
+// You may obtain a copy of the License at
5
+//
6
+//      http://www.apache.org/licenses/LICENSE-2.0
7
+//
8
+// Unless required by applicable law or agreed to in writing, software
9
+// distributed under the License is distributed on an "AS IS" BASIS,
10
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+// See the License for the specific language governing permissions and
12
+// limitations under the License.
13
+
14
+// +build go1.8
15
+
16
+// Package propagation implements X-Cloud-Trace-Context header propagation used
17
+// by Google Cloud products.
18
+package propagation
19
+
20
+import (
21
+	"encoding/binary"
22
+	"encoding/hex"
23
+	"fmt"
24
+	"net/http"
25
+	"strconv"
26
+	"strings"
27
+
28
+	"go.opencensus.io/trace"
29
+	"go.opencensus.io/trace/propagation"
30
+)
31
+
32
+const (
33
+	httpHeaderMaxSize = 200
34
+	httpHeader        = `X-Cloud-Trace-Context`
35
+)
36
+
37
+var _ propagation.HTTPFormat = (*HTTPFormat)(nil)
38
+
39
+// HTTPFormat implements propagation.HTTPFormat to propagate
40
+// traces in HTTP headers for Google Cloud Platform and Stackdriver Trace.
41
+type HTTPFormat struct{}
42
+
43
+// SpanContextFromRequest extracts a Stackdriver Trace span context from incoming requests.
44
+func (f *HTTPFormat) SpanContextFromRequest(req *http.Request) (sc trace.SpanContext, ok bool) {
45
+	h := req.Header.Get(httpHeader)
46
+	// See https://cloud.google.com/trace/docs/faq for the header HTTPFormat.
47
+	// Return if the header is empty or missing, or if the header is unreasonably
48
+	// large, to avoid making unnecessary copies of a large string.
49
+	if h == "" || len(h) > httpHeaderMaxSize {
50
+		return trace.SpanContext{}, false
51
+	}
52
+
53
+	// Parse the trace id field.
54
+	slash := strings.Index(h, `/`)
55
+	if slash == -1 {
56
+		return trace.SpanContext{}, false
57
+	}
58
+	tid, h := h[:slash], h[slash+1:]
59
+
60
+	buf, err := hex.DecodeString(tid)
61
+	if err != nil {
62
+		return trace.SpanContext{}, false
63
+	}
64
+	copy(sc.TraceID[:], buf)
65
+
66
+	// Parse the span id field.
67
+	spanstr := h
68
+	semicolon := strings.Index(h, `;`)
69
+	if semicolon != -1 {
70
+		spanstr, h = h[:semicolon], h[semicolon+1:]
71
+	}
72
+	sid, err := strconv.ParseUint(spanstr, 10, 64)
73
+	if err != nil {
74
+		return trace.SpanContext{}, false
75
+	}
76
+	binary.BigEndian.PutUint64(sc.SpanID[:], sid)
77
+
78
+	// Parse the options field, options field is optional.
79
+	if !strings.HasPrefix(h, "o=") {
80
+		return sc, true
81
+	}
82
+	o, err := strconv.ParseUint(h[2:], 10, 64)
83
+	if err != nil {
84
+		return trace.SpanContext{}, false
85
+	}
86
+	sc.TraceOptions = trace.TraceOptions(o)
87
+	return sc, true
88
+}
89
+
90
+// SpanContextToRequest modifies the given request to include a Stackdriver Trace header.
91
+func (f *HTTPFormat) SpanContextToRequest(sc trace.SpanContext, req *http.Request) {
92
+	sid := binary.BigEndian.Uint64(sc.SpanID[:])
93
+	header := fmt.Sprintf("%s/%d;o=%d", hex.EncodeToString(sc.TraceID[:]), sid, int64(sc.TraceOptions))
94
+	req.Header.Set(httpHeader, header)
95
+}
0 96
deleted file mode 100644
... ...
@@ -1,21 +0,0 @@
1
-// Copyright 2018 Google Inc. All Rights Reserved.
2
-//
3
-// Licensed under the Apache License, Version 2.0 (the "License");
4
-// you may not use this file except in compliance with the License.
5
-// You may obtain a copy of the License at
6
-//
7
-//      http://www.apache.org/licenses/LICENSE-2.0
8
-//
9
-// Unless required by applicable law or agreed to in writing, software
10
-// distributed under the License is distributed on an "AS IS" BASIS,
11
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
-// See the License for the specific language governing permissions and
13
-// limitations under the License.
14
-
15
-// +build !go1.8
16
-
17
-package http
18
-
19
-import "net/http"
20
-
21
-func addOCTransport(trans http.RoundTripper) http.RoundTripper { return trans }
... ...
@@ -1,4 +1,4 @@
1
-// Copyright 2018 Google Inc. All Rights Reserved.
1
+// Copyright 2018 Google LLC
2 2
 //
3 3
 // Licensed under the Apache License, Version 2.0 (the "License");
4 4
 // you may not use this file except in compliance with the License.
... ...
@@ -17,7 +17,8 @@
17 17
 package transport
18 18
 
19 19
 import (
20
-	"golang.org/x/net/context"
20
+	"context"
21
+
21 22
 	"golang.org/x/oauth2/google"
22 23
 	"google.golang.org/api/internal"
23 24
 	"google.golang.org/api/option"
24 25
new file mode 100644
... ...
@@ -0,0 +1,772 @@
0
+// Code generated by protoc-gen-go. DO NOT EDIT.
1
+// source: grpc/lb/v1/load_balancer.proto
2
+
3
+package grpc_lb_v1
4
+
5
+import (
6
+	context "context"
7
+	fmt "fmt"
8
+	proto "github.com/golang/protobuf/proto"
9
+	duration "github.com/golang/protobuf/ptypes/duration"
10
+	timestamp "github.com/golang/protobuf/ptypes/timestamp"
11
+	grpc "google.golang.org/grpc"
12
+	codes "google.golang.org/grpc/codes"
13
+	status "google.golang.org/grpc/status"
14
+	math "math"
15
+)
16
+
17
+// Reference imports to suppress errors if they are not otherwise used.
18
+var _ = proto.Marshal
19
+var _ = fmt.Errorf
20
+var _ = math.Inf
21
+
22
+// This is a compile-time assertion to ensure that this generated file
23
+// is compatible with the proto package it is being compiled against.
24
+// A compilation error at this line likely means your copy of the
25
+// proto package needs to be updated.
26
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
27
+
28
+type LoadBalanceRequest struct {
29
+	// Types that are valid to be assigned to LoadBalanceRequestType:
30
+	//	*LoadBalanceRequest_InitialRequest
31
+	//	*LoadBalanceRequest_ClientStats
32
+	LoadBalanceRequestType isLoadBalanceRequest_LoadBalanceRequestType `protobuf_oneof:"load_balance_request_type"`
33
+	XXX_NoUnkeyedLiteral   struct{}                                    `json:"-"`
34
+	XXX_unrecognized       []byte                                      `json:"-"`
35
+	XXX_sizecache          int32                                       `json:"-"`
36
+}
37
+
38
+func (m *LoadBalanceRequest) Reset()         { *m = LoadBalanceRequest{} }
39
+func (m *LoadBalanceRequest) String() string { return proto.CompactTextString(m) }
40
+func (*LoadBalanceRequest) ProtoMessage()    {}
41
+func (*LoadBalanceRequest) Descriptor() ([]byte, []int) {
42
+	return fileDescriptor_7cd3f6d792743fdf, []int{0}
43
+}
44
+
45
+func (m *LoadBalanceRequest) XXX_Unmarshal(b []byte) error {
46
+	return xxx_messageInfo_LoadBalanceRequest.Unmarshal(m, b)
47
+}
48
+func (m *LoadBalanceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
49
+	return xxx_messageInfo_LoadBalanceRequest.Marshal(b, m, deterministic)
50
+}
51
+func (m *LoadBalanceRequest) XXX_Merge(src proto.Message) {
52
+	xxx_messageInfo_LoadBalanceRequest.Merge(m, src)
53
+}
54
+func (m *LoadBalanceRequest) XXX_Size() int {
55
+	return xxx_messageInfo_LoadBalanceRequest.Size(m)
56
+}
57
+func (m *LoadBalanceRequest) XXX_DiscardUnknown() {
58
+	xxx_messageInfo_LoadBalanceRequest.DiscardUnknown(m)
59
+}
60
+
61
+var xxx_messageInfo_LoadBalanceRequest proto.InternalMessageInfo
62
+
63
+type isLoadBalanceRequest_LoadBalanceRequestType interface {
64
+	isLoadBalanceRequest_LoadBalanceRequestType()
65
+}
66
+
67
+type LoadBalanceRequest_InitialRequest struct {
68
+	InitialRequest *InitialLoadBalanceRequest `protobuf:"bytes,1,opt,name=initial_request,json=initialRequest,proto3,oneof"`
69
+}
70
+
71
+type LoadBalanceRequest_ClientStats struct {
72
+	ClientStats *ClientStats `protobuf:"bytes,2,opt,name=client_stats,json=clientStats,proto3,oneof"`
73
+}
74
+
75
+func (*LoadBalanceRequest_InitialRequest) isLoadBalanceRequest_LoadBalanceRequestType() {}
76
+
77
+func (*LoadBalanceRequest_ClientStats) isLoadBalanceRequest_LoadBalanceRequestType() {}
78
+
79
+func (m *LoadBalanceRequest) GetLoadBalanceRequestType() isLoadBalanceRequest_LoadBalanceRequestType {
80
+	if m != nil {
81
+		return m.LoadBalanceRequestType
82
+	}
83
+	return nil
84
+}
85
+
86
+func (m *LoadBalanceRequest) GetInitialRequest() *InitialLoadBalanceRequest {
87
+	if x, ok := m.GetLoadBalanceRequestType().(*LoadBalanceRequest_InitialRequest); ok {
88
+		return x.InitialRequest
89
+	}
90
+	return nil
91
+}
92
+
93
+func (m *LoadBalanceRequest) GetClientStats() *ClientStats {
94
+	if x, ok := m.GetLoadBalanceRequestType().(*LoadBalanceRequest_ClientStats); ok {
95
+		return x.ClientStats
96
+	}
97
+	return nil
98
+}
99
+
100
+// XXX_OneofWrappers is for the internal use of the proto package.
101
+func (*LoadBalanceRequest) XXX_OneofWrappers() []interface{} {
102
+	return []interface{}{
103
+		(*LoadBalanceRequest_InitialRequest)(nil),
104
+		(*LoadBalanceRequest_ClientStats)(nil),
105
+	}
106
+}
107
+
108
+type InitialLoadBalanceRequest struct {
109
+	// The name of the load balanced service (e.g., service.googleapis.com). Its
110
+	// length should be less than 256 bytes.
111
+	// The name might include a port number. How to handle the port number is up
112
+	// to the balancer.
113
+	Name                 string   `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
114
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
115
+	XXX_unrecognized     []byte   `json:"-"`
116
+	XXX_sizecache        int32    `json:"-"`
117
+}
118
+
119
+func (m *InitialLoadBalanceRequest) Reset()         { *m = InitialLoadBalanceRequest{} }
120
+func (m *InitialLoadBalanceRequest) String() string { return proto.CompactTextString(m) }
121
+func (*InitialLoadBalanceRequest) ProtoMessage()    {}
122
+func (*InitialLoadBalanceRequest) Descriptor() ([]byte, []int) {
123
+	return fileDescriptor_7cd3f6d792743fdf, []int{1}
124
+}
125
+
126
+func (m *InitialLoadBalanceRequest) XXX_Unmarshal(b []byte) error {
127
+	return xxx_messageInfo_InitialLoadBalanceRequest.Unmarshal(m, b)
128
+}
129
+func (m *InitialLoadBalanceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
130
+	return xxx_messageInfo_InitialLoadBalanceRequest.Marshal(b, m, deterministic)
131
+}
132
+func (m *InitialLoadBalanceRequest) XXX_Merge(src proto.Message) {
133
+	xxx_messageInfo_InitialLoadBalanceRequest.Merge(m, src)
134
+}
135
+func (m *InitialLoadBalanceRequest) XXX_Size() int {
136
+	return xxx_messageInfo_InitialLoadBalanceRequest.Size(m)
137
+}
138
+func (m *InitialLoadBalanceRequest) XXX_DiscardUnknown() {
139
+	xxx_messageInfo_InitialLoadBalanceRequest.DiscardUnknown(m)
140
+}
141
+
142
+var xxx_messageInfo_InitialLoadBalanceRequest proto.InternalMessageInfo
143
+
144
+func (m *InitialLoadBalanceRequest) GetName() string {
145
+	if m != nil {
146
+		return m.Name
147
+	}
148
+	return ""
149
+}
150
+
151
+// Contains the number of calls finished for a particular load balance token.
152
+type ClientStatsPerToken struct {
153
+	// See Server.load_balance_token.
154
+	LoadBalanceToken string `protobuf:"bytes,1,opt,name=load_balance_token,json=loadBalanceToken,proto3" json:"load_balance_token,omitempty"`
155
+	// The total number of RPCs that finished associated with the token.
156
+	NumCalls             int64    `protobuf:"varint,2,opt,name=num_calls,json=numCalls,proto3" json:"num_calls,omitempty"`
157
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
158
+	XXX_unrecognized     []byte   `json:"-"`
159
+	XXX_sizecache        int32    `json:"-"`
160
+}
161
+
162
+func (m *ClientStatsPerToken) Reset()         { *m = ClientStatsPerToken{} }
163
+func (m *ClientStatsPerToken) String() string { return proto.CompactTextString(m) }
164
+func (*ClientStatsPerToken) ProtoMessage()    {}
165
+func (*ClientStatsPerToken) Descriptor() ([]byte, []int) {
166
+	return fileDescriptor_7cd3f6d792743fdf, []int{2}
167
+}
168
+
169
+func (m *ClientStatsPerToken) XXX_Unmarshal(b []byte) error {
170
+	return xxx_messageInfo_ClientStatsPerToken.Unmarshal(m, b)
171
+}
172
+func (m *ClientStatsPerToken) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
173
+	return xxx_messageInfo_ClientStatsPerToken.Marshal(b, m, deterministic)
174
+}
175
+func (m *ClientStatsPerToken) XXX_Merge(src proto.Message) {
176
+	xxx_messageInfo_ClientStatsPerToken.Merge(m, src)
177
+}
178
+func (m *ClientStatsPerToken) XXX_Size() int {
179
+	return xxx_messageInfo_ClientStatsPerToken.Size(m)
180
+}
181
+func (m *ClientStatsPerToken) XXX_DiscardUnknown() {
182
+	xxx_messageInfo_ClientStatsPerToken.DiscardUnknown(m)
183
+}
184
+
185
+var xxx_messageInfo_ClientStatsPerToken proto.InternalMessageInfo
186
+
187
+func (m *ClientStatsPerToken) GetLoadBalanceToken() string {
188
+	if m != nil {
189
+		return m.LoadBalanceToken
190
+	}
191
+	return ""
192
+}
193
+
194
+func (m *ClientStatsPerToken) GetNumCalls() int64 {
195
+	if m != nil {
196
+		return m.NumCalls
197
+	}
198
+	return 0
199
+}
200
+
201
+// Contains client level statistics that are useful to load balancing. Each
202
+// count except the timestamp should be reset to zero after reporting the stats.
203
+type ClientStats struct {
204
+	// The timestamp of generating the report.
205
+	Timestamp *timestamp.Timestamp `protobuf:"bytes,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
206
+	// The total number of RPCs that started.
207
+	NumCallsStarted int64 `protobuf:"varint,2,opt,name=num_calls_started,json=numCallsStarted,proto3" json:"num_calls_started,omitempty"`
208
+	// The total number of RPCs that finished.
209
+	NumCallsFinished int64 `protobuf:"varint,3,opt,name=num_calls_finished,json=numCallsFinished,proto3" json:"num_calls_finished,omitempty"`
210
+	// The total number of RPCs that failed to reach a server except dropped RPCs.
211
+	NumCallsFinishedWithClientFailedToSend int64 `protobuf:"varint,6,opt,name=num_calls_finished_with_client_failed_to_send,json=numCallsFinishedWithClientFailedToSend,proto3" json:"num_calls_finished_with_client_failed_to_send,omitempty"`
212
+	// The total number of RPCs that finished and are known to have been received
213
+	// by a server.
214
+	NumCallsFinishedKnownReceived int64 `protobuf:"varint,7,opt,name=num_calls_finished_known_received,json=numCallsFinishedKnownReceived,proto3" json:"num_calls_finished_known_received,omitempty"`
215
+	// The list of dropped calls.
216
+	CallsFinishedWithDrop []*ClientStatsPerToken `protobuf:"bytes,8,rep,name=calls_finished_with_drop,json=callsFinishedWithDrop,proto3" json:"calls_finished_with_drop,omitempty"`
217
+	XXX_NoUnkeyedLiteral  struct{}               `json:"-"`
218
+	XXX_unrecognized      []byte                 `json:"-"`
219
+	XXX_sizecache         int32                  `json:"-"`
220
+}
221
+
222
+func (m *ClientStats) Reset()         { *m = ClientStats{} }
223
+func (m *ClientStats) String() string { return proto.CompactTextString(m) }
224
+func (*ClientStats) ProtoMessage()    {}
225
+func (*ClientStats) Descriptor() ([]byte, []int) {
226
+	return fileDescriptor_7cd3f6d792743fdf, []int{3}
227
+}
228
+
229
+func (m *ClientStats) XXX_Unmarshal(b []byte) error {
230
+	return xxx_messageInfo_ClientStats.Unmarshal(m, b)
231
+}
232
+func (m *ClientStats) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
233
+	return xxx_messageInfo_ClientStats.Marshal(b, m, deterministic)
234
+}
235
+func (m *ClientStats) XXX_Merge(src proto.Message) {
236
+	xxx_messageInfo_ClientStats.Merge(m, src)
237
+}
238
+func (m *ClientStats) XXX_Size() int {
239
+	return xxx_messageInfo_ClientStats.Size(m)
240
+}
241
+func (m *ClientStats) XXX_DiscardUnknown() {
242
+	xxx_messageInfo_ClientStats.DiscardUnknown(m)
243
+}
244
+
245
+var xxx_messageInfo_ClientStats proto.InternalMessageInfo
246
+
247
+func (m *ClientStats) GetTimestamp() *timestamp.Timestamp {
248
+	if m != nil {
249
+		return m.Timestamp
250
+	}
251
+	return nil
252
+}
253
+
254
+func (m *ClientStats) GetNumCallsStarted() int64 {
255
+	if m != nil {
256
+		return m.NumCallsStarted
257
+	}
258
+	return 0
259
+}
260
+
261
+func (m *ClientStats) GetNumCallsFinished() int64 {
262
+	if m != nil {
263
+		return m.NumCallsFinished
264
+	}
265
+	return 0
266
+}
267
+
268
+func (m *ClientStats) GetNumCallsFinishedWithClientFailedToSend() int64 {
269
+	if m != nil {
270
+		return m.NumCallsFinishedWithClientFailedToSend
271
+	}
272
+	return 0
273
+}
274
+
275
+func (m *ClientStats) GetNumCallsFinishedKnownReceived() int64 {
276
+	if m != nil {
277
+		return m.NumCallsFinishedKnownReceived
278
+	}
279
+	return 0
280
+}
281
+
282
+func (m *ClientStats) GetCallsFinishedWithDrop() []*ClientStatsPerToken {
283
+	if m != nil {
284
+		return m.CallsFinishedWithDrop
285
+	}
286
+	return nil
287
+}
288
+
289
+type LoadBalanceResponse struct {
290
+	// Types that are valid to be assigned to LoadBalanceResponseType:
291
+	//	*LoadBalanceResponse_InitialResponse
292
+	//	*LoadBalanceResponse_ServerList
293
+	//	*LoadBalanceResponse_FallbackResponse
294
+	LoadBalanceResponseType isLoadBalanceResponse_LoadBalanceResponseType `protobuf_oneof:"load_balance_response_type"`
295
+	XXX_NoUnkeyedLiteral    struct{}                                      `json:"-"`
296
+	XXX_unrecognized        []byte                                        `json:"-"`
297
+	XXX_sizecache           int32                                         `json:"-"`
298
+}
299
+
300
+func (m *LoadBalanceResponse) Reset()         { *m = LoadBalanceResponse{} }
301
+func (m *LoadBalanceResponse) String() string { return proto.CompactTextString(m) }
302
+func (*LoadBalanceResponse) ProtoMessage()    {}
303
+func (*LoadBalanceResponse) Descriptor() ([]byte, []int) {
304
+	return fileDescriptor_7cd3f6d792743fdf, []int{4}
305
+}
306
+
307
+func (m *LoadBalanceResponse) XXX_Unmarshal(b []byte) error {
308
+	return xxx_messageInfo_LoadBalanceResponse.Unmarshal(m, b)
309
+}
310
+func (m *LoadBalanceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
311
+	return xxx_messageInfo_LoadBalanceResponse.Marshal(b, m, deterministic)
312
+}
313
+func (m *LoadBalanceResponse) XXX_Merge(src proto.Message) {
314
+	xxx_messageInfo_LoadBalanceResponse.Merge(m, src)
315
+}
316
+func (m *LoadBalanceResponse) XXX_Size() int {
317
+	return xxx_messageInfo_LoadBalanceResponse.Size(m)
318
+}
319
+func (m *LoadBalanceResponse) XXX_DiscardUnknown() {
320
+	xxx_messageInfo_LoadBalanceResponse.DiscardUnknown(m)
321
+}
322
+
323
+var xxx_messageInfo_LoadBalanceResponse proto.InternalMessageInfo
324
+
325
+type isLoadBalanceResponse_LoadBalanceResponseType interface {
326
+	isLoadBalanceResponse_LoadBalanceResponseType()
327
+}
328
+
329
+type LoadBalanceResponse_InitialResponse struct {
330
+	InitialResponse *InitialLoadBalanceResponse `protobuf:"bytes,1,opt,name=initial_response,json=initialResponse,proto3,oneof"`
331
+}
332
+
333
+type LoadBalanceResponse_ServerList struct {
334
+	ServerList *ServerList `protobuf:"bytes,2,opt,name=server_list,json=serverList,proto3,oneof"`
335
+}
336
+
337
+type LoadBalanceResponse_FallbackResponse struct {
338
+	FallbackResponse *FallbackResponse `protobuf:"bytes,3,opt,name=fallback_response,json=fallbackResponse,proto3,oneof"`
339
+}
340
+
341
+func (*LoadBalanceResponse_InitialResponse) isLoadBalanceResponse_LoadBalanceResponseType() {}
342
+
343
+func (*LoadBalanceResponse_ServerList) isLoadBalanceResponse_LoadBalanceResponseType() {}
344
+
345
+func (*LoadBalanceResponse_FallbackResponse) isLoadBalanceResponse_LoadBalanceResponseType() {}
346
+
347
+func (m *LoadBalanceResponse) GetLoadBalanceResponseType() isLoadBalanceResponse_LoadBalanceResponseType {
348
+	if m != nil {
349
+		return m.LoadBalanceResponseType
350
+	}
351
+	return nil
352
+}
353
+
354
+func (m *LoadBalanceResponse) GetInitialResponse() *InitialLoadBalanceResponse {
355
+	if x, ok := m.GetLoadBalanceResponseType().(*LoadBalanceResponse_InitialResponse); ok {
356
+		return x.InitialResponse
357
+	}
358
+	return nil
359
+}
360
+
361
+func (m *LoadBalanceResponse) GetServerList() *ServerList {
362
+	if x, ok := m.GetLoadBalanceResponseType().(*LoadBalanceResponse_ServerList); ok {
363
+		return x.ServerList
364
+	}
365
+	return nil
366
+}
367
+
368
+func (m *LoadBalanceResponse) GetFallbackResponse() *FallbackResponse {
369
+	if x, ok := m.GetLoadBalanceResponseType().(*LoadBalanceResponse_FallbackResponse); ok {
370
+		return x.FallbackResponse
371
+	}
372
+	return nil
373
+}
374
+
375
+// XXX_OneofWrappers is for the internal use of the proto package.
376
+func (*LoadBalanceResponse) XXX_OneofWrappers() []interface{} {
377
+	return []interface{}{
378
+		(*LoadBalanceResponse_InitialResponse)(nil),
379
+		(*LoadBalanceResponse_ServerList)(nil),
380
+		(*LoadBalanceResponse_FallbackResponse)(nil),
381
+	}
382
+}
383
+
384
+type FallbackResponse struct {
385
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
386
+	XXX_unrecognized     []byte   `json:"-"`
387
+	XXX_sizecache        int32    `json:"-"`
388
+}
389
+
390
+func (m *FallbackResponse) Reset()         { *m = FallbackResponse{} }
391
+func (m *FallbackResponse) String() string { return proto.CompactTextString(m) }
392
+func (*FallbackResponse) ProtoMessage()    {}
393
+func (*FallbackResponse) Descriptor() ([]byte, []int) {
394
+	return fileDescriptor_7cd3f6d792743fdf, []int{5}
395
+}
396
+
397
+func (m *FallbackResponse) XXX_Unmarshal(b []byte) error {
398
+	return xxx_messageInfo_FallbackResponse.Unmarshal(m, b)
399
+}
400
+func (m *FallbackResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
401
+	return xxx_messageInfo_FallbackResponse.Marshal(b, m, deterministic)
402
+}
403
+func (m *FallbackResponse) XXX_Merge(src proto.Message) {
404
+	xxx_messageInfo_FallbackResponse.Merge(m, src)
405
+}
406
+func (m *FallbackResponse) XXX_Size() int {
407
+	return xxx_messageInfo_FallbackResponse.Size(m)
408
+}
409
+func (m *FallbackResponse) XXX_DiscardUnknown() {
410
+	xxx_messageInfo_FallbackResponse.DiscardUnknown(m)
411
+}
412
+
413
+var xxx_messageInfo_FallbackResponse proto.InternalMessageInfo
414
+
415
+type InitialLoadBalanceResponse struct {
416
+	// This is an application layer redirect that indicates the client should use
417
+	// the specified server for load balancing. When this field is non-empty in
418
+	// the response, the client should open a separate connection to the
419
+	// load_balancer_delegate and call the BalanceLoad method. Its length should
420
+	// be less than 64 bytes.
421
+	LoadBalancerDelegate string `protobuf:"bytes,1,opt,name=load_balancer_delegate,json=loadBalancerDelegate,proto3" json:"load_balancer_delegate,omitempty"`
422
+	// This interval defines how often the client should send the client stats
423
+	// to the load balancer. Stats should only be reported when the duration is
424
+	// positive.
425
+	ClientStatsReportInterval *duration.Duration `protobuf:"bytes,2,opt,name=client_stats_report_interval,json=clientStatsReportInterval,proto3" json:"client_stats_report_interval,omitempty"`
426
+	XXX_NoUnkeyedLiteral      struct{}           `json:"-"`
427
+	XXX_unrecognized          []byte             `json:"-"`
428
+	XXX_sizecache             int32              `json:"-"`
429
+}
430
+
431
+func (m *InitialLoadBalanceResponse) Reset()         { *m = InitialLoadBalanceResponse{} }
432
+func (m *InitialLoadBalanceResponse) String() string { return proto.CompactTextString(m) }
433
+func (*InitialLoadBalanceResponse) ProtoMessage()    {}
434
+func (*InitialLoadBalanceResponse) Descriptor() ([]byte, []int) {
435
+	return fileDescriptor_7cd3f6d792743fdf, []int{6}
436
+}
437
+
438
+func (m *InitialLoadBalanceResponse) XXX_Unmarshal(b []byte) error {
439
+	return xxx_messageInfo_InitialLoadBalanceResponse.Unmarshal(m, b)
440
+}
441
+func (m *InitialLoadBalanceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
442
+	return xxx_messageInfo_InitialLoadBalanceResponse.Marshal(b, m, deterministic)
443
+}
444
+func (m *InitialLoadBalanceResponse) XXX_Merge(src proto.Message) {
445
+	xxx_messageInfo_InitialLoadBalanceResponse.Merge(m, src)
446
+}
447
+func (m *InitialLoadBalanceResponse) XXX_Size() int {
448
+	return xxx_messageInfo_InitialLoadBalanceResponse.Size(m)
449
+}
450
+func (m *InitialLoadBalanceResponse) XXX_DiscardUnknown() {
451
+	xxx_messageInfo_InitialLoadBalanceResponse.DiscardUnknown(m)
452
+}
453
+
454
+var xxx_messageInfo_InitialLoadBalanceResponse proto.InternalMessageInfo
455
+
456
+func (m *InitialLoadBalanceResponse) GetLoadBalancerDelegate() string {
457
+	if m != nil {
458
+		return m.LoadBalancerDelegate
459
+	}
460
+	return ""
461
+}
462
+
463
+func (m *InitialLoadBalanceResponse) GetClientStatsReportInterval() *duration.Duration {
464
+	if m != nil {
465
+		return m.ClientStatsReportInterval
466
+	}
467
+	return nil
468
+}
469
+
470
+type ServerList struct {
471
+	// Contains a list of servers selected by the load balancer. The list will
472
+	// be updated when server resolutions change or as needed to balance load
473
+	// across more servers. The client should consume the server list in order
474
+	// unless instructed otherwise via the client_config.
475
+	Servers              []*Server `protobuf:"bytes,1,rep,name=servers,proto3" json:"servers,omitempty"`
476
+	XXX_NoUnkeyedLiteral struct{}  `json:"-"`
477
+	XXX_unrecognized     []byte    `json:"-"`
478
+	XXX_sizecache        int32     `json:"-"`
479
+}
480
+
481
+func (m *ServerList) Reset()         { *m = ServerList{} }
482
+func (m *ServerList) String() string { return proto.CompactTextString(m) }
483
+func (*ServerList) ProtoMessage()    {}
484
+func (*ServerList) Descriptor() ([]byte, []int) {
485
+	return fileDescriptor_7cd3f6d792743fdf, []int{7}
486
+}
487
+
488
+func (m *ServerList) XXX_Unmarshal(b []byte) error {
489
+	return xxx_messageInfo_ServerList.Unmarshal(m, b)
490
+}
491
+func (m *ServerList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
492
+	return xxx_messageInfo_ServerList.Marshal(b, m, deterministic)
493
+}
494
+func (m *ServerList) XXX_Merge(src proto.Message) {
495
+	xxx_messageInfo_ServerList.Merge(m, src)
496
+}
497
+func (m *ServerList) XXX_Size() int {
498
+	return xxx_messageInfo_ServerList.Size(m)
499
+}
500
+func (m *ServerList) XXX_DiscardUnknown() {
501
+	xxx_messageInfo_ServerList.DiscardUnknown(m)
502
+}
503
+
504
+var xxx_messageInfo_ServerList proto.InternalMessageInfo
505
+
506
+func (m *ServerList) GetServers() []*Server {
507
+	if m != nil {
508
+		return m.Servers
509
+	}
510
+	return nil
511
+}
512
+
513
+// Contains server information. When the drop field is not true, use the other
514
+// fields.
515
+type Server struct {
516
+	// A resolved address for the server, serialized in network-byte-order. It may
517
+	// either be an IPv4 or IPv6 address.
518
+	IpAddress []byte `protobuf:"bytes,1,opt,name=ip_address,json=ipAddress,proto3" json:"ip_address,omitempty"`
519
+	// A resolved port number for the server.
520
+	Port int32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"`
521
+	// An opaque but printable token for load reporting. The client must include
522
+	// the token of the picked server into the initial metadata when it starts a
523
+	// call to that server. The token is used by the server to verify the request
524
+	// and to allow the server to report load to the gRPC LB system. The token is
525
+	// also used in client stats for reporting dropped calls.
526
+	//
527
+	// Its length can be variable but must be less than 50 bytes.
528
+	LoadBalanceToken string `protobuf:"bytes,3,opt,name=load_balance_token,json=loadBalanceToken,proto3" json:"load_balance_token,omitempty"`
529
+	// Indicates whether this particular request should be dropped by the client.
530
+	// If the request is dropped, there will be a corresponding entry in
531
+	// ClientStats.calls_finished_with_drop.
532
+	Drop                 bool     `protobuf:"varint,4,opt,name=drop,proto3" json:"drop,omitempty"`
533
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
534
+	XXX_unrecognized     []byte   `json:"-"`
535
+	XXX_sizecache        int32    `json:"-"`
536
+}
537
+
538
+func (m *Server) Reset()         { *m = Server{} }
539
+func (m *Server) String() string { return proto.CompactTextString(m) }
540
+func (*Server) ProtoMessage()    {}
541
+func (*Server) Descriptor() ([]byte, []int) {
542
+	return fileDescriptor_7cd3f6d792743fdf, []int{8}
543
+}
544
+
545
+func (m *Server) XXX_Unmarshal(b []byte) error {
546
+	return xxx_messageInfo_Server.Unmarshal(m, b)
547
+}
548
+func (m *Server) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
549
+	return xxx_messageInfo_Server.Marshal(b, m, deterministic)
550
+}
551
+func (m *Server) XXX_Merge(src proto.Message) {
552
+	xxx_messageInfo_Server.Merge(m, src)
553
+}
554
+func (m *Server) XXX_Size() int {
555
+	return xxx_messageInfo_Server.Size(m)
556
+}
557
+func (m *Server) XXX_DiscardUnknown() {
558
+	xxx_messageInfo_Server.DiscardUnknown(m)
559
+}
560
+
561
+var xxx_messageInfo_Server proto.InternalMessageInfo
562
+
563
+func (m *Server) GetIpAddress() []byte {
564
+	if m != nil {
565
+		return m.IpAddress
566
+	}
567
+	return nil
568
+}
569
+
570
+func (m *Server) GetPort() int32 {
571
+	if m != nil {
572
+		return m.Port
573
+	}
574
+	return 0
575
+}
576
+
577
+func (m *Server) GetLoadBalanceToken() string {
578
+	if m != nil {
579
+		return m.LoadBalanceToken
580
+	}
581
+	return ""
582
+}
583
+
584
+func (m *Server) GetDrop() bool {
585
+	if m != nil {
586
+		return m.Drop
587
+	}
588
+	return false
589
+}
590
+
591
+func init() {
592
+	proto.RegisterType((*LoadBalanceRequest)(nil), "grpc.lb.v1.LoadBalanceRequest")
593
+	proto.RegisterType((*InitialLoadBalanceRequest)(nil), "grpc.lb.v1.InitialLoadBalanceRequest")
594
+	proto.RegisterType((*ClientStatsPerToken)(nil), "grpc.lb.v1.ClientStatsPerToken")
595
+	proto.RegisterType((*ClientStats)(nil), "grpc.lb.v1.ClientStats")
596
+	proto.RegisterType((*LoadBalanceResponse)(nil), "grpc.lb.v1.LoadBalanceResponse")
597
+	proto.RegisterType((*FallbackResponse)(nil), "grpc.lb.v1.FallbackResponse")
598
+	proto.RegisterType((*InitialLoadBalanceResponse)(nil), "grpc.lb.v1.InitialLoadBalanceResponse")
599
+	proto.RegisterType((*ServerList)(nil), "grpc.lb.v1.ServerList")
600
+	proto.RegisterType((*Server)(nil), "grpc.lb.v1.Server")
601
+}
602
+
603
+func init() { proto.RegisterFile("grpc/lb/v1/load_balancer.proto", fileDescriptor_7cd3f6d792743fdf) }
604
+
605
+var fileDescriptor_7cd3f6d792743fdf = []byte{
606
+	// 785 bytes of a gzipped FileDescriptorProto
607
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x55, 0xdd, 0x6e, 0xdb, 0x36,
608
+	0x14, 0x8e, 0x6a, 0x27, 0x75, 0x8e, 0xb3, 0xc5, 0x61, 0xb7, 0x4e, 0x71, 0xd3, 0x24, 0x13, 0xb0,
609
+	0x22, 0x18, 0x3a, 0x79, 0xc9, 0x76, 0xb1, 0x01, 0xbb, 0xd8, 0xdc, 0x20, 0x48, 0xd3, 0x5e, 0x04,
610
+	0x74, 0x80, 0x0e, 0x05, 0x06, 0x8e, 0x92, 0x68, 0x87, 0x08, 0x4d, 0x6a, 0x14, 0xed, 0x62, 0xd7,
611
+	0x7b, 0x81, 0x3d, 0xc9, 0xb0, 0x57, 0xd8, 0x9b, 0x0d, 0x22, 0x29, 0x4b, 0xb1, 0x63, 0xf4, 0x4a,
612
+	0xe4, 0x39, 0x1f, 0xbf, 0xf3, 0x7f, 0x04, 0x87, 0x13, 0x9d, 0xa7, 0x03, 0x91, 0x0c, 0xe6, 0xa7,
613
+	0x03, 0xa1, 0x68, 0x46, 0x12, 0x2a, 0xa8, 0x4c, 0x99, 0x8e, 0x73, 0xad, 0x8c, 0x42, 0x50, 0xea,
614
+	0x63, 0x91, 0xc4, 0xf3, 0xd3, 0xfe, 0xe1, 0x44, 0xa9, 0x89, 0x60, 0x03, 0xab, 0x49, 0x66, 0xe3,
615
+	0x41, 0x36, 0xd3, 0xd4, 0x70, 0x25, 0x1d, 0xb6, 0x7f, 0xb4, 0xac, 0x37, 0x7c, 0xca, 0x0a, 0x43,
616
+	0xa7, 0xb9, 0x03, 0x44, 0xff, 0x05, 0x80, 0xde, 0x2a, 0x9a, 0x0d, 0x9d, 0x0d, 0xcc, 0xfe, 0x98,
617
+	0xb1, 0xc2, 0xa0, 0x6b, 0xd8, 0xe5, 0x92, 0x1b, 0x4e, 0x05, 0xd1, 0x4e, 0x14, 0x06, 0xc7, 0xc1,
618
+	0x49, 0xf7, 0xec, 0xab, 0xb8, 0xb6, 0x1e, 0xbf, 0x76, 0x90, 0xd5, 0xf7, 0x97, 0x1b, 0xf8, 0x53,
619
+	0xff, 0xbe, 0x62, 0xfc, 0x09, 0x76, 0x52, 0xc1, 0x99, 0x34, 0xa4, 0x30, 0xd4, 0x14, 0xe1, 0x23,
620
+	0x4b, 0xf7, 0x45, 0x93, 0xee, 0x95, 0xd5, 0x8f, 0x4a, 0xf5, 0xe5, 0x06, 0xee, 0xa6, 0xf5, 0x75,
621
+	0xf8, 0x0c, 0xf6, 0x9b, 0xa9, 0xa8, 0x9c, 0x22, 0xe6, 0xcf, 0x9c, 0x45, 0x03, 0xd8, 0x5f, 0xeb,
622
+	0x09, 0x42, 0xd0, 0x96, 0x74, 0xca, 0xac, 0xfb, 0xdb, 0xd8, 0x9e, 0xa3, 0xdf, 0xe1, 0x49, 0xc3,
623
+	0xd6, 0x35, 0xd3, 0x37, 0xea, 0x8e, 0x49, 0xf4, 0x12, 0xd0, 0x3d, 0x23, 0xa6, 0x94, 0xfa, 0x87,
624
+	0x3d, 0x51, 0x53, 0x3b, 0xf4, 0x33, 0xd8, 0x96, 0xb3, 0x29, 0x49, 0xa9, 0x10, 0x2e, 0x9a, 0x16,
625
+	0xee, 0xc8, 0xd9, 0xf4, 0x55, 0x79, 0x8f, 0xfe, 0x6d, 0x41, 0xb7, 0x61, 0x02, 0xfd, 0x00, 0xdb,
626
+	0x8b, 0xcc, 0xfb, 0x4c, 0xf6, 0x63, 0x57, 0x9b, 0xb8, 0xaa, 0x4d, 0x7c, 0x53, 0x21, 0x70, 0x0d,
627
+	0x46, 0x5f, 0xc3, 0xde, 0xc2, 0x4c, 0x99, 0x3a, 0x6d, 0x58, 0xe6, 0xcd, 0xed, 0x56, 0xe6, 0x46,
628
+	0x4e, 0x5c, 0x06, 0x50, 0x63, 0xc7, 0x5c, 0xf2, 0xe2, 0x96, 0x65, 0x61, 0xcb, 0x82, 0x7b, 0x15,
629
+	0xf8, 0xc2, 0xcb, 0xd1, 0x6f, 0xf0, 0xcd, 0x2a, 0x9a, 0x7c, 0xe0, 0xe6, 0x96, 0xf8, 0x4a, 0x8d,
630
+	0x29, 0x17, 0x2c, 0x23, 0x46, 0x91, 0x82, 0xc9, 0x2c, 0xdc, 0xb2, 0x44, 0x2f, 0x96, 0x89, 0xde,
631
+	0x71, 0x73, 0xeb, 0x62, 0xbd, 0xb0, 0xf8, 0x1b, 0x35, 0x62, 0x32, 0x43, 0x97, 0xf0, 0xe5, 0x03,
632
+	0xf4, 0x77, 0x52, 0x7d, 0x90, 0x44, 0xb3, 0x94, 0xf1, 0x39, 0xcb, 0xc2, 0xc7, 0x96, 0xf2, 0xf9,
633
+	0x32, 0xe5, 0x9b, 0x12, 0x85, 0x3d, 0x08, 0xfd, 0x0a, 0xe1, 0x43, 0x4e, 0x66, 0x5a, 0xe5, 0x61,
634
+	0xe7, 0xb8, 0x75, 0xd2, 0x3d, 0x3b, 0x5a, 0xd3, 0x46, 0x55, 0x69, 0xf1, 0xe7, 0xe9, 0xb2, 0xc7,
635
+	0xe7, 0x5a, 0xe5, 0x57, 0xed, 0x4e, 0xbb, 0xb7, 0x79, 0xd5, 0xee, 0x6c, 0xf6, 0xb6, 0xa2, 0xbf,
636
+	0x1f, 0xc1, 0x93, 0x7b, 0xfd, 0x53, 0xe4, 0x4a, 0x16, 0x0c, 0x8d, 0xa0, 0x57, 0x8f, 0x82, 0x93,
637
+	0xf9, 0x0a, 0xbe, 0xf8, 0xd8, 0x2c, 0x38, 0xf4, 0xe5, 0x06, 0xde, 0x5d, 0x0c, 0x83, 0x27, 0xfd,
638
+	0x11, 0xba, 0x05, 0xd3, 0x73, 0xa6, 0x89, 0xe0, 0x85, 0xf1, 0xc3, 0xf0, 0xb4, 0xc9, 0x37, 0xb2,
639
+	0xea, 0xb7, 0xdc, 0x0e, 0x13, 0x14, 0x8b, 0x1b, 0x7a, 0x03, 0x7b, 0x63, 0x2a, 0x44, 0x42, 0xd3,
640
+	0xbb, 0xda, 0xa1, 0x96, 0x25, 0x38, 0x68, 0x12, 0x5c, 0x78, 0x50, 0xc3, 0x8d, 0xde, 0x78, 0x49,
641
+	0x36, 0x3c, 0x80, 0xfe, 0xd2, 0x5c, 0x39, 0x85, 0x1b, 0x2c, 0x04, 0xbd, 0x65, 0x96, 0xe8, 0x9f,
642
+	0x00, 0xfa, 0xeb, 0x63, 0x45, 0xdf, 0xc3, 0xd3, 0x7b, 0x3b, 0x8b, 0x64, 0x4c, 0xb0, 0x09, 0x35,
643
+	0xd5, 0x00, 0x7e, 0xd6, 0x98, 0x23, 0x7d, 0xee, 0x75, 0xe8, 0x3d, 0x1c, 0x34, 0x97, 0x03, 0xd1,
644
+	0x2c, 0x57, 0xda, 0x10, 0x2e, 0x0d, 0xd3, 0x73, 0x2a, 0x7c, 0x7e, 0xf6, 0x57, 0x26, 0xe6, 0xdc,
645
+	0x6f, 0x3b, 0xbc, 0xdf, 0x58, 0x16, 0xd8, 0x3e, 0x7e, 0xed, 0xdf, 0x46, 0x3f, 0x03, 0xd4, 0xb9,
646
+	0x44, 0x2f, 0xe1, 0xb1, 0xcb, 0x65, 0x11, 0x06, 0xb6, 0x75, 0xd0, 0x6a, 0xd2, 0x71, 0x05, 0xb9,
647
+	0x6a, 0x77, 0x5a, 0xbd, 0x76, 0xf4, 0x57, 0x00, 0x5b, 0x4e, 0x83, 0x9e, 0x03, 0xf0, 0x9c, 0xd0,
648
+	0x2c, 0xd3, 0xac, 0x28, 0x6c, 0x48, 0x3b, 0x78, 0x9b, 0xe7, 0xbf, 0x38, 0x41, 0xb9, 0x6c, 0x4a,
649
+	0xdb, 0xd6, 0xdf, 0x4d, 0x6c, 0xcf, 0x6b, 0xb6, 0x4a, 0x6b, 0xcd, 0x56, 0x41, 0xd0, 0xb6, 0x7d,
650
+	0xdd, 0x3e, 0x0e, 0x4e, 0x3a, 0xd8, 0x9e, 0x5d, 0x7f, 0x9e, 0x25, 0xb0, 0xd3, 0x48, 0xb8, 0x46,
651
+	0x18, 0xba, 0xfe, 0x5c, 0x8a, 0xd1, 0x61, 0x33, 0x8e, 0xd5, 0x3d, 0xd8, 0x3f, 0x5a, 0xab, 0x77,
652
+	0x95, 0x3b, 0x09, 0xbe, 0x0d, 0x86, 0xef, 0xe0, 0x13, 0xae, 0x1a, 0xc0, 0xe1, 0x5e, 0xd3, 0xe4,
653
+	0x75, 0x99, 0xf6, 0xeb, 0xe0, 0xfd, 0xa9, 0x2f, 0xc3, 0x44, 0x09, 0x2a, 0x27, 0xb1, 0xd2, 0x93,
654
+	0x81, 0xfd, 0x65, 0x55, 0x35, 0xb7, 0x37, 0x91, 0xd8, 0x0f, 0x11, 0x09, 0x99, 0x9f, 0x26, 0x5b,
655
+	0xb6, 0x64, 0xdf, 0xfd, 0x1f, 0x00, 0x00, 0xff, 0xff, 0x09, 0x7b, 0x39, 0x1e, 0xdc, 0x06, 0x00,
656
+	0x00,
657
+}
658
+
659
+// Reference imports to suppress errors if they are not otherwise used.
660
+var _ context.Context
661
+var _ grpc.ClientConn
662
+
663
+// This is a compile-time assertion to ensure that this generated file
664
+// is compatible with the grpc package it is being compiled against.
665
+const _ = grpc.SupportPackageIsVersion4
666
+
667
+// LoadBalancerClient is the client API for LoadBalancer service.
668
+//
669
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
670
+type LoadBalancerClient interface {
671
+	// Bidirectional rpc to get a list of servers.
672
+	BalanceLoad(ctx context.Context, opts ...grpc.CallOption) (LoadBalancer_BalanceLoadClient, error)
673
+}
674
+
675
+type loadBalancerClient struct {
676
+	cc *grpc.ClientConn
677
+}
678
+
679
+func NewLoadBalancerClient(cc *grpc.ClientConn) LoadBalancerClient {
680
+	return &loadBalancerClient{cc}
681
+}
682
+
683
+func (c *loadBalancerClient) BalanceLoad(ctx context.Context, opts ...grpc.CallOption) (LoadBalancer_BalanceLoadClient, error) {
684
+	stream, err := c.cc.NewStream(ctx, &_LoadBalancer_serviceDesc.Streams[0], "/grpc.lb.v1.LoadBalancer/BalanceLoad", opts...)
685
+	if err != nil {
686
+		return nil, err
687
+	}
688
+	x := &loadBalancerBalanceLoadClient{stream}
689
+	return x, nil
690
+}
691
+
692
+type LoadBalancer_BalanceLoadClient interface {
693
+	Send(*LoadBalanceRequest) error
694
+	Recv() (*LoadBalanceResponse, error)
695
+	grpc.ClientStream
696
+}
697
+
698
+type loadBalancerBalanceLoadClient struct {
699
+	grpc.ClientStream
700
+}
701
+
702
+func (x *loadBalancerBalanceLoadClient) Send(m *LoadBalanceRequest) error {
703
+	return x.ClientStream.SendMsg(m)
704
+}
705
+
706
+func (x *loadBalancerBalanceLoadClient) Recv() (*LoadBalanceResponse, error) {
707
+	m := new(LoadBalanceResponse)
708
+	if err := x.ClientStream.RecvMsg(m); err != nil {
709
+		return nil, err
710
+	}
711
+	return m, nil
712
+}
713
+
714
+// LoadBalancerServer is the server API for LoadBalancer service.
715
+type LoadBalancerServer interface {
716
+	// Bidirectional rpc to get a list of servers.
717
+	BalanceLoad(LoadBalancer_BalanceLoadServer) error
718
+}
719
+
720
+// UnimplementedLoadBalancerServer can be embedded to have forward compatible implementations.
721
+type UnimplementedLoadBalancerServer struct {
722
+}
723
+
724
+func (*UnimplementedLoadBalancerServer) BalanceLoad(srv LoadBalancer_BalanceLoadServer) error {
725
+	return status.Errorf(codes.Unimplemented, "method BalanceLoad not implemented")
726
+}
727
+
728
+func RegisterLoadBalancerServer(s *grpc.Server, srv LoadBalancerServer) {
729
+	s.RegisterService(&_LoadBalancer_serviceDesc, srv)
730
+}
731
+
732
+func _LoadBalancer_BalanceLoad_Handler(srv interface{}, stream grpc.ServerStream) error {
733
+	return srv.(LoadBalancerServer).BalanceLoad(&loadBalancerBalanceLoadServer{stream})
734
+}
735
+
736
+type LoadBalancer_BalanceLoadServer interface {
737
+	Send(*LoadBalanceResponse) error
738
+	Recv() (*LoadBalanceRequest, error)
739
+	grpc.ServerStream
740
+}
741
+
742
+type loadBalancerBalanceLoadServer struct {
743
+	grpc.ServerStream
744
+}
745
+
746
+func (x *loadBalancerBalanceLoadServer) Send(m *LoadBalanceResponse) error {
747
+	return x.ServerStream.SendMsg(m)
748
+}
749
+
750
+func (x *loadBalancerBalanceLoadServer) Recv() (*LoadBalanceRequest, error) {
751
+	m := new(LoadBalanceRequest)
752
+	if err := x.ServerStream.RecvMsg(m); err != nil {
753
+		return nil, err
754
+	}
755
+	return m, nil
756
+}
757
+
758
+var _LoadBalancer_serviceDesc = grpc.ServiceDesc{
759
+	ServiceName: "grpc.lb.v1.LoadBalancer",
760
+	HandlerType: (*LoadBalancerServer)(nil),
761
+	Methods:     []grpc.MethodDesc{},
762
+	Streams: []grpc.StreamDesc{
763
+		{
764
+			StreamName:    "BalanceLoad",
765
+			Handler:       _LoadBalancer_BalanceLoad_Handler,
766
+			ServerStreams: true,
767
+			ClientStreams: true,
768
+		},
769
+	},
770
+	Metadata: "grpc/lb/v1/load_balancer.proto",
771
+}
0 772
new file mode 100644
... ...
@@ -0,0 +1,488 @@
0
+/*
1
+ *
2
+ * Copyright 2016 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+//go:generate ./regenerate.sh
19
+
20
+// Package grpclb defines a grpclb balancer.
21
+//
22
+// To install grpclb balancer, import this package as:
23
+//    import _ "google.golang.org/grpc/balancer/grpclb"
24
+package grpclb
25
+
26
+import (
27
+	"context"
28
+	"errors"
29
+	"sync"
30
+	"time"
31
+
32
+	durationpb "github.com/golang/protobuf/ptypes/duration"
33
+	"google.golang.org/grpc"
34
+	"google.golang.org/grpc/balancer"
35
+	lbpb "google.golang.org/grpc/balancer/grpclb/grpc_lb_v1"
36
+	"google.golang.org/grpc/connectivity"
37
+	"google.golang.org/grpc/credentials"
38
+	"google.golang.org/grpc/grpclog"
39
+	"google.golang.org/grpc/internal"
40
+	"google.golang.org/grpc/internal/backoff"
41
+	"google.golang.org/grpc/internal/resolver/dns"
42
+	"google.golang.org/grpc/resolver"
43
+)
44
+
45
+const (
46
+	lbTokenKey             = "lb-token"
47
+	defaultFallbackTimeout = 10 * time.Second
48
+	grpclbName             = "grpclb"
49
+)
50
+
51
+var errServerTerminatedConnection = errors.New("grpclb: failed to recv server list: server terminated connection")
52
+
53
+func convertDuration(d *durationpb.Duration) time.Duration {
54
+	if d == nil {
55
+		return 0
56
+	}
57
+	return time.Duration(d.Seconds)*time.Second + time.Duration(d.Nanos)*time.Nanosecond
58
+}
59
+
60
+// Client API for LoadBalancer service.
61
+// Mostly copied from generated pb.go file.
62
+// To avoid circular dependency.
63
+type loadBalancerClient struct {
64
+	cc *grpc.ClientConn
65
+}
66
+
67
+func (c *loadBalancerClient) BalanceLoad(ctx context.Context, opts ...grpc.CallOption) (*balanceLoadClientStream, error) {
68
+	desc := &grpc.StreamDesc{
69
+		StreamName:    "BalanceLoad",
70
+		ServerStreams: true,
71
+		ClientStreams: true,
72
+	}
73
+	stream, err := c.cc.NewStream(ctx, desc, "/grpc.lb.v1.LoadBalancer/BalanceLoad", opts...)
74
+	if err != nil {
75
+		return nil, err
76
+	}
77
+	x := &balanceLoadClientStream{stream}
78
+	return x, nil
79
+}
80
+
81
+type balanceLoadClientStream struct {
82
+	grpc.ClientStream
83
+}
84
+
85
+func (x *balanceLoadClientStream) Send(m *lbpb.LoadBalanceRequest) error {
86
+	return x.ClientStream.SendMsg(m)
87
+}
88
+
89
+func (x *balanceLoadClientStream) Recv() (*lbpb.LoadBalanceResponse, error) {
90
+	m := new(lbpb.LoadBalanceResponse)
91
+	if err := x.ClientStream.RecvMsg(m); err != nil {
92
+		return nil, err
93
+	}
94
+	return m, nil
95
+}
96
+
97
+func init() {
98
+	balancer.Register(newLBBuilder())
99
+	dns.EnableSRVLookups = true
100
+}
101
+
102
+// newLBBuilder creates a builder for grpclb.
103
+func newLBBuilder() balancer.Builder {
104
+	return newLBBuilderWithFallbackTimeout(defaultFallbackTimeout)
105
+}
106
+
107
+// newLBBuilderWithFallbackTimeout creates a grpclb builder with the given
108
+// fallbackTimeout. If no response is received from the remote balancer within
109
+// fallbackTimeout, the backend addresses from the resolved address list will be
110
+// used.
111
+//
112
+// Only call this function when a non-default fallback timeout is needed.
113
+func newLBBuilderWithFallbackTimeout(fallbackTimeout time.Duration) balancer.Builder {
114
+	return &lbBuilder{
115
+		fallbackTimeout: fallbackTimeout,
116
+	}
117
+}
118
+
119
+type lbBuilder struct {
120
+	fallbackTimeout time.Duration
121
+}
122
+
123
+func (b *lbBuilder) Name() string {
124
+	return grpclbName
125
+}
126
+
127
+func (b *lbBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer {
128
+	// This generates a manual resolver builder with a fixed scheme. This
129
+	// scheme will be used to dial to remote LB, so we can send filtered
130
+	// address updates to remote LB ClientConn using this manual resolver.
131
+	r := &lbManualResolver{scheme: "grpclb-internal", ccb: cc}
132
+
133
+	lb := &lbBalancer{
134
+		cc:              newLBCacheClientConn(cc),
135
+		target:          opt.Target.Endpoint,
136
+		opt:             opt,
137
+		fallbackTimeout: b.fallbackTimeout,
138
+		doneCh:          make(chan struct{}),
139
+
140
+		manualResolver: r,
141
+		subConns:       make(map[resolver.Address]balancer.SubConn),
142
+		scStates:       make(map[balancer.SubConn]connectivity.State),
143
+		picker:         &errPicker{err: balancer.ErrNoSubConnAvailable},
144
+		clientStats:    newRPCStats(),
145
+		backoff:        backoff.DefaultExponential, // TODO: make backoff configurable.
146
+	}
147
+
148
+	var err error
149
+	if opt.CredsBundle != nil {
150
+		lb.grpclbClientConnCreds, err = opt.CredsBundle.NewWithMode(internal.CredsBundleModeBalancer)
151
+		if err != nil {
152
+			grpclog.Warningf("lbBalancer: client connection creds NewWithMode failed: %v", err)
153
+		}
154
+		lb.grpclbBackendCreds, err = opt.CredsBundle.NewWithMode(internal.CredsBundleModeBackendFromBalancer)
155
+		if err != nil {
156
+			grpclog.Warningf("lbBalancer: backend creds NewWithMode failed: %v", err)
157
+		}
158
+	}
159
+
160
+	return lb
161
+}
162
+
163
+var _ balancer.V2Balancer = (*lbBalancer)(nil) // Assert that we implement V2Balancer
164
+
165
+type lbBalancer struct {
166
+	cc     *lbCacheClientConn
167
+	target string
168
+	opt    balancer.BuildOptions
169
+
170
+	usePickFirst bool
171
+
172
+	// grpclbClientConnCreds is the creds bundle to be used to connect to grpclb
173
+	// servers. If it's nil, use the TransportCredentials from BuildOptions
174
+	// instead.
175
+	grpclbClientConnCreds credentials.Bundle
176
+	// grpclbBackendCreds is the creds bundle to be used for addresses that are
177
+	// returned by grpclb server. If it's nil, don't set anything when creating
178
+	// SubConns.
179
+	grpclbBackendCreds credentials.Bundle
180
+
181
+	fallbackTimeout time.Duration
182
+	doneCh          chan struct{}
183
+
184
+	// manualResolver is used in the remote LB ClientConn inside grpclb. When
185
+	// resolved address updates are received by grpclb, filtered updates will be
186
+	// send to remote LB ClientConn through this resolver.
187
+	manualResolver *lbManualResolver
188
+	// The ClientConn to talk to the remote balancer.
189
+	ccRemoteLB *remoteBalancerCCWrapper
190
+	// backoff for calling remote balancer.
191
+	backoff backoff.Strategy
192
+
193
+	// Support client side load reporting. Each picker gets a reference to this,
194
+	// and will update its content.
195
+	clientStats *rpcStats
196
+
197
+	mu sync.Mutex // guards everything following.
198
+	// The full server list including drops, used to check if the newly received
199
+	// serverList contains anything new. Each generate picker will also have
200
+	// reference to this list to do the first layer pick.
201
+	fullServerList []*lbpb.Server
202
+	// Backend addresses. It's kept so the addresses are available when
203
+	// switching between round_robin and pickfirst.
204
+	backendAddrs []resolver.Address
205
+	// All backends addresses, with metadata set to nil. This list contains all
206
+	// backend addresses in the same order and with the same duplicates as in
207
+	// serverlist. When generating picker, a SubConn slice with the same order
208
+	// but with only READY SCs will be gerenated.
209
+	backendAddrsWithoutMetadata []resolver.Address
210
+	// Roundrobin functionalities.
211
+	state    connectivity.State
212
+	subConns map[resolver.Address]balancer.SubConn   // Used to new/remove SubConn.
213
+	scStates map[balancer.SubConn]connectivity.State // Used to filter READY SubConns.
214
+	picker   balancer.V2Picker
215
+	// Support fallback to resolved backend addresses if there's no response
216
+	// from remote balancer within fallbackTimeout.
217
+	remoteBalancerConnected bool
218
+	serverListReceived      bool
219
+	inFallback              bool
220
+	// resolvedBackendAddrs is resolvedAddrs minus remote balancers. It's set
221
+	// when resolved address updates are received, and read in the goroutine
222
+	// handling fallback.
223
+	resolvedBackendAddrs []resolver.Address
224
+}
225
+
226
+// regeneratePicker takes a snapshot of the balancer, and generates a picker from
227
+// it. The picker
228
+//  - always returns ErrTransientFailure if the balancer is in TransientFailure,
229
+//  - does two layer roundrobin pick otherwise.
230
+// Caller must hold lb.mu.
231
+func (lb *lbBalancer) regeneratePicker(resetDrop bool) {
232
+	if lb.state == connectivity.TransientFailure {
233
+		lb.picker = &errPicker{err: balancer.ErrTransientFailure}
234
+		return
235
+	}
236
+
237
+	if lb.state == connectivity.Connecting {
238
+		lb.picker = &errPicker{err: balancer.ErrNoSubConnAvailable}
239
+		return
240
+	}
241
+
242
+	var readySCs []balancer.SubConn
243
+	if lb.usePickFirst {
244
+		for _, sc := range lb.subConns {
245
+			readySCs = append(readySCs, sc)
246
+			break
247
+		}
248
+	} else {
249
+		for _, a := range lb.backendAddrsWithoutMetadata {
250
+			if sc, ok := lb.subConns[a]; ok {
251
+				if st, ok := lb.scStates[sc]; ok && st == connectivity.Ready {
252
+					readySCs = append(readySCs, sc)
253
+				}
254
+			}
255
+		}
256
+	}
257
+
258
+	if len(readySCs) <= 0 {
259
+		// If there's no ready SubConns, always re-pick. This is to avoid drops
260
+		// unless at least one SubConn is ready. Otherwise we may drop more
261
+		// often than want because of drops + re-picks(which become re-drops).
262
+		//
263
+		// This doesn't seem to be necessary after the connecting check above.
264
+		// Kept for safety.
265
+		lb.picker = &errPicker{err: balancer.ErrNoSubConnAvailable}
266
+		return
267
+	}
268
+	if lb.inFallback {
269
+		lb.picker = newRRPicker(readySCs)
270
+		return
271
+	}
272
+	if resetDrop {
273
+		lb.picker = newLBPicker(lb.fullServerList, readySCs, lb.clientStats)
274
+		return
275
+	}
276
+	prevLBPicker, ok := lb.picker.(*lbPicker)
277
+	if !ok {
278
+		lb.picker = newLBPicker(lb.fullServerList, readySCs, lb.clientStats)
279
+		return
280
+	}
281
+	prevLBPicker.updateReadySCs(readySCs)
282
+}
283
+
284
+// aggregateSubConnStats calculate the aggregated state of SubConns in
285
+// lb.SubConns. These SubConns are subconns in use (when switching between
286
+// fallback and grpclb). lb.scState contains states for all SubConns, including
287
+// those in cache (SubConns are cached for 10 seconds after remove).
288
+//
289
+// The aggregated state is:
290
+//  - If at least one SubConn in Ready, the aggregated state is Ready;
291
+//  - Else if at least one SubConn in Connecting, the aggregated state is Connecting;
292
+//  - Else the aggregated state is TransientFailure.
293
+func (lb *lbBalancer) aggregateSubConnStates() connectivity.State {
294
+	var numConnecting uint64
295
+
296
+	for _, sc := range lb.subConns {
297
+		if state, ok := lb.scStates[sc]; ok {
298
+			switch state {
299
+			case connectivity.Ready:
300
+				return connectivity.Ready
301
+			case connectivity.Connecting:
302
+				numConnecting++
303
+			}
304
+		}
305
+	}
306
+	if numConnecting > 0 {
307
+		return connectivity.Connecting
308
+	}
309
+	return connectivity.TransientFailure
310
+}
311
+
312
+func (lb *lbBalancer) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
313
+	panic("not used")
314
+}
315
+
316
+func (lb *lbBalancer) UpdateSubConnState(sc balancer.SubConn, scs balancer.SubConnState) {
317
+	s := scs.ConnectivityState
318
+	if grpclog.V(2) {
319
+		grpclog.Infof("lbBalancer: handle SubConn state change: %p, %v", sc, s)
320
+	}
321
+	lb.mu.Lock()
322
+	defer lb.mu.Unlock()
323
+
324
+	oldS, ok := lb.scStates[sc]
325
+	if !ok {
326
+		if grpclog.V(2) {
327
+			grpclog.Infof("lbBalancer: got state changes for an unknown SubConn: %p, %v", sc, s)
328
+		}
329
+		return
330
+	}
331
+	lb.scStates[sc] = s
332
+	switch s {
333
+	case connectivity.Idle:
334
+		sc.Connect()
335
+	case connectivity.Shutdown:
336
+		// When an address was removed by resolver, b called RemoveSubConn but
337
+		// kept the sc's state in scStates. Remove state for this sc here.
338
+		delete(lb.scStates, sc)
339
+	}
340
+	// Force regenerate picker if
341
+	//  - this sc became ready from not-ready
342
+	//  - this sc became not-ready from ready
343
+	lb.updateStateAndPicker((oldS == connectivity.Ready) != (s == connectivity.Ready), false)
344
+
345
+	// Enter fallback when the aggregated state is not Ready and the connection
346
+	// to remote balancer is lost.
347
+	if lb.state != connectivity.Ready {
348
+		if !lb.inFallback && !lb.remoteBalancerConnected {
349
+			// Enter fallback.
350
+			lb.refreshSubConns(lb.resolvedBackendAddrs, true, lb.usePickFirst)
351
+		}
352
+	}
353
+}
354
+
355
+// updateStateAndPicker re-calculate the aggregated state, and regenerate picker
356
+// if overall state is changed.
357
+//
358
+// If forceRegeneratePicker is true, picker will be regenerated.
359
+func (lb *lbBalancer) updateStateAndPicker(forceRegeneratePicker bool, resetDrop bool) {
360
+	oldAggrState := lb.state
361
+	lb.state = lb.aggregateSubConnStates()
362
+	// Regenerate picker when one of the following happens:
363
+	//  - caller wants to regenerate
364
+	//  - the aggregated state changed
365
+	if forceRegeneratePicker || (lb.state != oldAggrState) {
366
+		lb.regeneratePicker(resetDrop)
367
+	}
368
+
369
+	lb.cc.UpdateState(balancer.State{ConnectivityState: lb.state, Picker: lb.picker})
370
+}
371
+
372
+// fallbackToBackendsAfter blocks for fallbackTimeout and falls back to use
373
+// resolved backends (backends received from resolver, not from remote balancer)
374
+// if no connection to remote balancers was successful.
375
+func (lb *lbBalancer) fallbackToBackendsAfter(fallbackTimeout time.Duration) {
376
+	timer := time.NewTimer(fallbackTimeout)
377
+	defer timer.Stop()
378
+	select {
379
+	case <-timer.C:
380
+	case <-lb.doneCh:
381
+		return
382
+	}
383
+	lb.mu.Lock()
384
+	if lb.inFallback || lb.serverListReceived {
385
+		lb.mu.Unlock()
386
+		return
387
+	}
388
+	// Enter fallback.
389
+	lb.refreshSubConns(lb.resolvedBackendAddrs, true, lb.usePickFirst)
390
+	lb.mu.Unlock()
391
+}
392
+
393
+// HandleResolvedAddrs sends the updated remoteLB addresses to remoteLB
394
+// clientConn. The remoteLB clientConn will handle creating/removing remoteLB
395
+// connections.
396
+func (lb *lbBalancer) HandleResolvedAddrs(addrs []resolver.Address, err error) {
397
+	panic("not used")
398
+}
399
+
400
+func (lb *lbBalancer) handleServiceConfig(gc *grpclbServiceConfig) {
401
+	lb.mu.Lock()
402
+	defer lb.mu.Unlock()
403
+
404
+	newUsePickFirst := childIsPickFirst(gc)
405
+	if lb.usePickFirst == newUsePickFirst {
406
+		return
407
+	}
408
+	if grpclog.V(2) {
409
+		grpclog.Infof("lbBalancer: switching mode, new usePickFirst: %+v", newUsePickFirst)
410
+	}
411
+	lb.refreshSubConns(lb.backendAddrs, lb.inFallback, newUsePickFirst)
412
+}
413
+
414
+func (lb *lbBalancer) ResolverError(error) {
415
+	// Ignore resolver errors.  GRPCLB is not selected unless the resolver
416
+	// works at least once.
417
+}
418
+
419
+func (lb *lbBalancer) UpdateClientConnState(ccs balancer.ClientConnState) error {
420
+	if grpclog.V(2) {
421
+		grpclog.Infof("lbBalancer: UpdateClientConnState: %+v", ccs)
422
+	}
423
+	gc, _ := ccs.BalancerConfig.(*grpclbServiceConfig)
424
+	lb.handleServiceConfig(gc)
425
+
426
+	addrs := ccs.ResolverState.Addresses
427
+	if len(addrs) == 0 {
428
+		// There should be at least one address, either grpclb server or
429
+		// fallback. Empty address is not valid.
430
+		return balancer.ErrBadResolverState
431
+	}
432
+
433
+	var remoteBalancerAddrs, backendAddrs []resolver.Address
434
+	for _, a := range addrs {
435
+		if a.Type == resolver.GRPCLB {
436
+			a.Type = resolver.Backend
437
+			remoteBalancerAddrs = append(remoteBalancerAddrs, a)
438
+		} else {
439
+			backendAddrs = append(backendAddrs, a)
440
+		}
441
+	}
442
+
443
+	if len(remoteBalancerAddrs) == 0 {
444
+		if lb.ccRemoteLB != nil {
445
+			lb.ccRemoteLB.close()
446
+			lb.ccRemoteLB = nil
447
+		}
448
+	} else if lb.ccRemoteLB == nil {
449
+		// First time receiving resolved addresses, create a cc to remote
450
+		// balancers.
451
+		lb.newRemoteBalancerCCWrapper()
452
+		// Start the fallback goroutine.
453
+		go lb.fallbackToBackendsAfter(lb.fallbackTimeout)
454
+	}
455
+
456
+	if lb.ccRemoteLB != nil {
457
+		// cc to remote balancers uses lb.manualResolver. Send the updated remote
458
+		// balancer addresses to it through manualResolver.
459
+		lb.manualResolver.UpdateState(resolver.State{Addresses: remoteBalancerAddrs})
460
+	}
461
+
462
+	lb.mu.Lock()
463
+	lb.resolvedBackendAddrs = backendAddrs
464
+	if len(remoteBalancerAddrs) == 0 || lb.inFallback {
465
+		// If there's no remote balancer address in ClientConn update, grpclb
466
+		// enters fallback mode immediately.
467
+		//
468
+		// If a new update is received while grpclb is in fallback, update the
469
+		// list of backends being used to the new fallback backends.
470
+		lb.refreshSubConns(lb.resolvedBackendAddrs, true, lb.usePickFirst)
471
+	}
472
+	lb.mu.Unlock()
473
+	return nil
474
+}
475
+
476
+func (lb *lbBalancer) Close() {
477
+	select {
478
+	case <-lb.doneCh:
479
+		return
480
+	default:
481
+	}
482
+	close(lb.doneCh)
483
+	if lb.ccRemoteLB != nil {
484
+		lb.ccRemoteLB.close()
485
+	}
486
+	lb.cc.close()
487
+}
0 488
new file mode 100644
... ...
@@ -0,0 +1,66 @@
0
+/*
1
+ *
2
+ * Copyright 2019 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+package grpclb
19
+
20
+import (
21
+	"encoding/json"
22
+
23
+	"google.golang.org/grpc"
24
+	"google.golang.org/grpc/balancer/roundrobin"
25
+	"google.golang.org/grpc/serviceconfig"
26
+)
27
+
28
+const (
29
+	roundRobinName = roundrobin.Name
30
+	pickFirstName  = grpc.PickFirstBalancerName
31
+)
32
+
33
+type grpclbServiceConfig struct {
34
+	serviceconfig.LoadBalancingConfig
35
+	ChildPolicy *[]map[string]json.RawMessage
36
+}
37
+
38
+func (b *lbBuilder) ParseConfig(lbConfig json.RawMessage) (serviceconfig.LoadBalancingConfig, error) {
39
+	ret := &grpclbServiceConfig{}
40
+	if err := json.Unmarshal(lbConfig, ret); err != nil {
41
+		return nil, err
42
+	}
43
+	return ret, nil
44
+}
45
+
46
+func childIsPickFirst(sc *grpclbServiceConfig) bool {
47
+	if sc == nil {
48
+		return false
49
+	}
50
+	childConfigs := sc.ChildPolicy
51
+	if childConfigs == nil {
52
+		return false
53
+	}
54
+	for _, childC := range *childConfigs {
55
+		// If round_robin exists before pick_first, return false
56
+		if _, ok := childC[roundRobinName]; ok {
57
+			return false
58
+		}
59
+		// If pick_first is before round_robin, return true
60
+		if _, ok := childC[pickFirstName]; ok {
61
+			return true
62
+		}
63
+	}
64
+	return false
65
+}
0 66
new file mode 100644
... ...
@@ -0,0 +1,202 @@
0
+/*
1
+ *
2
+ * Copyright 2017 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+package grpclb
19
+
20
+import (
21
+	"sync"
22
+	"sync/atomic"
23
+
24
+	"google.golang.org/grpc/balancer"
25
+	lbpb "google.golang.org/grpc/balancer/grpclb/grpc_lb_v1"
26
+	"google.golang.org/grpc/codes"
27
+	"google.golang.org/grpc/internal/grpcrand"
28
+	"google.golang.org/grpc/status"
29
+)
30
+
31
+// rpcStats is same as lbpb.ClientStats, except that numCallsDropped is a map
32
+// instead of a slice.
33
+type rpcStats struct {
34
+	// Only access the following fields atomically.
35
+	numCallsStarted                        int64
36
+	numCallsFinished                       int64
37
+	numCallsFinishedWithClientFailedToSend int64
38
+	numCallsFinishedKnownReceived          int64
39
+
40
+	mu sync.Mutex
41
+	// map load_balance_token -> num_calls_dropped
42
+	numCallsDropped map[string]int64
43
+}
44
+
45
+func newRPCStats() *rpcStats {
46
+	return &rpcStats{
47
+		numCallsDropped: make(map[string]int64),
48
+	}
49
+}
50
+
51
+func isZeroStats(stats *lbpb.ClientStats) bool {
52
+	return len(stats.CallsFinishedWithDrop) == 0 &&
53
+		stats.NumCallsStarted == 0 &&
54
+		stats.NumCallsFinished == 0 &&
55
+		stats.NumCallsFinishedWithClientFailedToSend == 0 &&
56
+		stats.NumCallsFinishedKnownReceived == 0
57
+}
58
+
59
+// toClientStats converts rpcStats to lbpb.ClientStats, and clears rpcStats.
60
+func (s *rpcStats) toClientStats() *lbpb.ClientStats {
61
+	stats := &lbpb.ClientStats{
62
+		NumCallsStarted:                        atomic.SwapInt64(&s.numCallsStarted, 0),
63
+		NumCallsFinished:                       atomic.SwapInt64(&s.numCallsFinished, 0),
64
+		NumCallsFinishedWithClientFailedToSend: atomic.SwapInt64(&s.numCallsFinishedWithClientFailedToSend, 0),
65
+		NumCallsFinishedKnownReceived:          atomic.SwapInt64(&s.numCallsFinishedKnownReceived, 0),
66
+	}
67
+	s.mu.Lock()
68
+	dropped := s.numCallsDropped
69
+	s.numCallsDropped = make(map[string]int64)
70
+	s.mu.Unlock()
71
+	for token, count := range dropped {
72
+		stats.CallsFinishedWithDrop = append(stats.CallsFinishedWithDrop, &lbpb.ClientStatsPerToken{
73
+			LoadBalanceToken: token,
74
+			NumCalls:         count,
75
+		})
76
+	}
77
+	return stats
78
+}
79
+
80
+func (s *rpcStats) drop(token string) {
81
+	atomic.AddInt64(&s.numCallsStarted, 1)
82
+	s.mu.Lock()
83
+	s.numCallsDropped[token]++
84
+	s.mu.Unlock()
85
+	atomic.AddInt64(&s.numCallsFinished, 1)
86
+}
87
+
88
+func (s *rpcStats) failedToSend() {
89
+	atomic.AddInt64(&s.numCallsStarted, 1)
90
+	atomic.AddInt64(&s.numCallsFinishedWithClientFailedToSend, 1)
91
+	atomic.AddInt64(&s.numCallsFinished, 1)
92
+}
93
+
94
+func (s *rpcStats) knownReceived() {
95
+	atomic.AddInt64(&s.numCallsStarted, 1)
96
+	atomic.AddInt64(&s.numCallsFinishedKnownReceived, 1)
97
+	atomic.AddInt64(&s.numCallsFinished, 1)
98
+}
99
+
100
+type errPicker struct {
101
+	// Pick always returns this err.
102
+	err error
103
+}
104
+
105
+func (p *errPicker) Pick(balancer.PickInfo) (balancer.PickResult, error) {
106
+	return balancer.PickResult{}, p.err
107
+}
108
+
109
+// rrPicker does roundrobin on subConns. It's typically used when there's no
110
+// response from remote balancer, and grpclb falls back to the resolved
111
+// backends.
112
+//
113
+// It guaranteed that len(subConns) > 0.
114
+type rrPicker struct {
115
+	mu           sync.Mutex
116
+	subConns     []balancer.SubConn // The subConns that were READY when taking the snapshot.
117
+	subConnsNext int
118
+}
119
+
120
+func newRRPicker(readySCs []balancer.SubConn) *rrPicker {
121
+	return &rrPicker{
122
+		subConns:     readySCs,
123
+		subConnsNext: grpcrand.Intn(len(readySCs)),
124
+	}
125
+}
126
+
127
+func (p *rrPicker) Pick(balancer.PickInfo) (balancer.PickResult, error) {
128
+	p.mu.Lock()
129
+	defer p.mu.Unlock()
130
+	sc := p.subConns[p.subConnsNext]
131
+	p.subConnsNext = (p.subConnsNext + 1) % len(p.subConns)
132
+	return balancer.PickResult{SubConn: sc}, nil
133
+}
134
+
135
+// lbPicker does two layers of picks:
136
+//
137
+// First layer: roundrobin on all servers in serverList, including drops and backends.
138
+// - If it picks a drop, the RPC will fail as being dropped.
139
+// - If it picks a backend, do a second layer pick to pick the real backend.
140
+//
141
+// Second layer: roundrobin on all READY backends.
142
+//
143
+// It's guaranteed that len(serverList) > 0.
144
+type lbPicker struct {
145
+	mu             sync.Mutex
146
+	serverList     []*lbpb.Server
147
+	serverListNext int
148
+	subConns       []balancer.SubConn // The subConns that were READY when taking the snapshot.
149
+	subConnsNext   int
150
+
151
+	stats *rpcStats
152
+}
153
+
154
+func newLBPicker(serverList []*lbpb.Server, readySCs []balancer.SubConn, stats *rpcStats) *lbPicker {
155
+	return &lbPicker{
156
+		serverList:   serverList,
157
+		subConns:     readySCs,
158
+		subConnsNext: grpcrand.Intn(len(readySCs)),
159
+		stats:        stats,
160
+	}
161
+}
162
+
163
+func (p *lbPicker) Pick(balancer.PickInfo) (balancer.PickResult, error) {
164
+	p.mu.Lock()
165
+	defer p.mu.Unlock()
166
+
167
+	// Layer one roundrobin on serverList.
168
+	s := p.serverList[p.serverListNext]
169
+	p.serverListNext = (p.serverListNext + 1) % len(p.serverList)
170
+
171
+	// If it's a drop, return an error and fail the RPC.
172
+	if s.Drop {
173
+		p.stats.drop(s.LoadBalanceToken)
174
+		return balancer.PickResult{}, status.Errorf(codes.Unavailable, "request dropped by grpclb")
175
+	}
176
+
177
+	// If not a drop but there's no ready subConns.
178
+	if len(p.subConns) <= 0 {
179
+		return balancer.PickResult{}, balancer.ErrNoSubConnAvailable
180
+	}
181
+
182
+	// Return the next ready subConn in the list, also collect rpc stats.
183
+	sc := p.subConns[p.subConnsNext]
184
+	p.subConnsNext = (p.subConnsNext + 1) % len(p.subConns)
185
+	done := func(info balancer.DoneInfo) {
186
+		if !info.BytesSent {
187
+			p.stats.failedToSend()
188
+		} else if info.BytesReceived {
189
+			p.stats.knownReceived()
190
+		}
191
+	}
192
+	return balancer.PickResult{SubConn: sc, Done: done}, nil
193
+}
194
+
195
+func (p *lbPicker) updateReadySCs(readySCs []balancer.SubConn) {
196
+	p.mu.Lock()
197
+	defer p.mu.Unlock()
198
+
199
+	p.subConns = readySCs
200
+	p.subConnsNext = p.subConnsNext % len(readySCs)
201
+}
0 202
new file mode 100644
... ...
@@ -0,0 +1,407 @@
0
+/*
1
+ *
2
+ * Copyright 2017 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+package grpclb
19
+
20
+import (
21
+	"context"
22
+	"fmt"
23
+	"io"
24
+	"net"
25
+	"sync"
26
+	"time"
27
+
28
+	"github.com/golang/protobuf/proto"
29
+	timestamppb "github.com/golang/protobuf/ptypes/timestamp"
30
+	"github.com/google/go-cmp/cmp"
31
+	"google.golang.org/grpc"
32
+	"google.golang.org/grpc/balancer"
33
+	lbpb "google.golang.org/grpc/balancer/grpclb/grpc_lb_v1"
34
+	"google.golang.org/grpc/connectivity"
35
+	"google.golang.org/grpc/grpclog"
36
+	"google.golang.org/grpc/internal/backoff"
37
+	"google.golang.org/grpc/internal/channelz"
38
+	"google.golang.org/grpc/keepalive"
39
+	"google.golang.org/grpc/metadata"
40
+	"google.golang.org/grpc/resolver"
41
+)
42
+
43
+// processServerList updates balaner's internal state, create/remove SubConns
44
+// and regenerates picker using the received serverList.
45
+func (lb *lbBalancer) processServerList(l *lbpb.ServerList) {
46
+	if grpclog.V(2) {
47
+		grpclog.Infof("lbBalancer: processing server list: %+v", l)
48
+	}
49
+	lb.mu.Lock()
50
+	defer lb.mu.Unlock()
51
+
52
+	// Set serverListReceived to true so fallback will not take effect if it has
53
+	// not hit timeout.
54
+	lb.serverListReceived = true
55
+
56
+	// If the new server list == old server list, do nothing.
57
+	if cmp.Equal(lb.fullServerList, l.Servers, cmp.Comparer(proto.Equal)) {
58
+		if grpclog.V(2) {
59
+			grpclog.Infof("lbBalancer: new serverlist same as the previous one, ignoring")
60
+		}
61
+		return
62
+	}
63
+	lb.fullServerList = l.Servers
64
+
65
+	var backendAddrs []resolver.Address
66
+	for i, s := range l.Servers {
67
+		if s.Drop {
68
+			continue
69
+		}
70
+
71
+		md := metadata.Pairs(lbTokenKey, s.LoadBalanceToken)
72
+		ip := net.IP(s.IpAddress)
73
+		ipStr := ip.String()
74
+		if ip.To4() == nil {
75
+			// Add square brackets to ipv6 addresses, otherwise net.Dial() and
76
+			// net.SplitHostPort() will return too many colons error.
77
+			ipStr = fmt.Sprintf("[%s]", ipStr)
78
+		}
79
+		addr := resolver.Address{
80
+			Addr:     fmt.Sprintf("%s:%d", ipStr, s.Port),
81
+			Metadata: &md,
82
+		}
83
+		if grpclog.V(2) {
84
+			grpclog.Infof("lbBalancer: server list entry[%d]: ipStr:|%s|, port:|%d|, load balancer token:|%v|",
85
+				i, ipStr, s.Port, s.LoadBalanceToken)
86
+		}
87
+		backendAddrs = append(backendAddrs, addr)
88
+	}
89
+
90
+	// Call refreshSubConns to create/remove SubConns.  If we are in fallback,
91
+	// this is also exiting fallback.
92
+	lb.refreshSubConns(backendAddrs, false, lb.usePickFirst)
93
+}
94
+
95
+// refreshSubConns creates/removes SubConns with backendAddrs, and refreshes
96
+// balancer state and picker.
97
+//
98
+// Caller must hold lb.mu.
99
+func (lb *lbBalancer) refreshSubConns(backendAddrs []resolver.Address, fallback bool, pickFirst bool) {
100
+	opts := balancer.NewSubConnOptions{}
101
+	if !fallback {
102
+		opts.CredsBundle = lb.grpclbBackendCreds
103
+	}
104
+
105
+	lb.backendAddrs = backendAddrs
106
+	lb.backendAddrsWithoutMetadata = nil
107
+
108
+	fallbackModeChanged := lb.inFallback != fallback
109
+	lb.inFallback = fallback
110
+	if fallbackModeChanged && lb.inFallback {
111
+		// Clear previous received list when entering fallback, so if the server
112
+		// comes back and sends the same list again, the new addresses will be
113
+		// used.
114
+		lb.fullServerList = nil
115
+	}
116
+
117
+	balancingPolicyChanged := lb.usePickFirst != pickFirst
118
+	oldUsePickFirst := lb.usePickFirst
119
+	lb.usePickFirst = pickFirst
120
+
121
+	if fallbackModeChanged || balancingPolicyChanged {
122
+		// Remove all SubConns when switching balancing policy or switching
123
+		// fallback mode.
124
+		//
125
+		// For fallback mode switching with pickfirst, we want to recreate the
126
+		// SubConn because the creds could be different.
127
+		for a, sc := range lb.subConns {
128
+			if oldUsePickFirst {
129
+				// If old SubConn were created for pickfirst, bypass cache and
130
+				// remove directly.
131
+				lb.cc.cc.RemoveSubConn(sc)
132
+			} else {
133
+				lb.cc.RemoveSubConn(sc)
134
+			}
135
+			delete(lb.subConns, a)
136
+		}
137
+	}
138
+
139
+	if lb.usePickFirst {
140
+		var sc balancer.SubConn
141
+		for _, sc = range lb.subConns {
142
+			break
143
+		}
144
+		if sc != nil {
145
+			sc.UpdateAddresses(backendAddrs)
146
+			sc.Connect()
147
+			return
148
+		}
149
+		// This bypasses the cc wrapper with SubConn cache.
150
+		sc, err := lb.cc.cc.NewSubConn(backendAddrs, opts)
151
+		if err != nil {
152
+			grpclog.Warningf("grpclb: failed to create new SubConn: %v", err)
153
+			return
154
+		}
155
+		sc.Connect()
156
+		lb.subConns[backendAddrs[0]] = sc
157
+		lb.scStates[sc] = connectivity.Idle
158
+		return
159
+	}
160
+
161
+	// addrsSet is the set converted from backendAddrsWithoutMetadata, it's used to quick
162
+	// lookup for an address.
163
+	addrsSet := make(map[resolver.Address]struct{})
164
+	// Create new SubConns.
165
+	for _, addr := range backendAddrs {
166
+		addrWithoutMD := addr
167
+		addrWithoutMD.Metadata = nil
168
+		addrsSet[addrWithoutMD] = struct{}{}
169
+		lb.backendAddrsWithoutMetadata = append(lb.backendAddrsWithoutMetadata, addrWithoutMD)
170
+
171
+		if _, ok := lb.subConns[addrWithoutMD]; !ok {
172
+			// Use addrWithMD to create the SubConn.
173
+			sc, err := lb.cc.NewSubConn([]resolver.Address{addr}, opts)
174
+			if err != nil {
175
+				grpclog.Warningf("grpclb: failed to create new SubConn: %v", err)
176
+				continue
177
+			}
178
+			lb.subConns[addrWithoutMD] = sc // Use the addr without MD as key for the map.
179
+			if _, ok := lb.scStates[sc]; !ok {
180
+				// Only set state of new sc to IDLE. The state could already be
181
+				// READY for cached SubConns.
182
+				lb.scStates[sc] = connectivity.Idle
183
+			}
184
+			sc.Connect()
185
+		}
186
+	}
187
+
188
+	for a, sc := range lb.subConns {
189
+		// a was removed by resolver.
190
+		if _, ok := addrsSet[a]; !ok {
191
+			lb.cc.RemoveSubConn(sc)
192
+			delete(lb.subConns, a)
193
+			// Keep the state of this sc in b.scStates until sc's state becomes Shutdown.
194
+			// The entry will be deleted in HandleSubConnStateChange.
195
+		}
196
+	}
197
+
198
+	// Regenerate and update picker after refreshing subconns because with
199
+	// cache, even if SubConn was newed/removed, there might be no state
200
+	// changes (the subconn will be kept in cache, not actually
201
+	// newed/removed).
202
+	lb.updateStateAndPicker(true, true)
203
+}
204
+
205
+type remoteBalancerCCWrapper struct {
206
+	cc      *grpc.ClientConn
207
+	lb      *lbBalancer
208
+	backoff backoff.Strategy
209
+	done    chan struct{}
210
+
211
+	// waitgroup to wait for all goroutines to exit.
212
+	wg sync.WaitGroup
213
+}
214
+
215
+func (lb *lbBalancer) newRemoteBalancerCCWrapper() {
216
+	var dopts []grpc.DialOption
217
+	if creds := lb.opt.DialCreds; creds != nil {
218
+		dopts = append(dopts, grpc.WithTransportCredentials(creds))
219
+	} else if bundle := lb.grpclbClientConnCreds; bundle != nil {
220
+		dopts = append(dopts, grpc.WithCredentialsBundle(bundle))
221
+	} else {
222
+		dopts = append(dopts, grpc.WithInsecure())
223
+	}
224
+	if lb.opt.Dialer != nil {
225
+		dopts = append(dopts, grpc.WithContextDialer(lb.opt.Dialer))
226
+	}
227
+	// Explicitly set pickfirst as the balancer.
228
+	dopts = append(dopts, grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy":"pick_first"}`))
229
+	dopts = append(dopts, grpc.WithResolvers(lb.manualResolver))
230
+	if channelz.IsOn() {
231
+		dopts = append(dopts, grpc.WithChannelzParentID(lb.opt.ChannelzParentID))
232
+	}
233
+
234
+	// Enable Keepalive for grpclb client.
235
+	dopts = append(dopts, grpc.WithKeepaliveParams(keepalive.ClientParameters{
236
+		Time:                20 * time.Second,
237
+		Timeout:             10 * time.Second,
238
+		PermitWithoutStream: true,
239
+	}))
240
+
241
+	// The dial target is not important.
242
+	//
243
+	// The grpclb server addresses will set field ServerName, and creds will
244
+	// receive ServerName as authority.
245
+	cc, err := grpc.DialContext(context.Background(), lb.manualResolver.Scheme()+":///grpclb.subClientConn", dopts...)
246
+	if err != nil {
247
+		grpclog.Fatalf("failed to dial: %v", err)
248
+	}
249
+	ccw := &remoteBalancerCCWrapper{
250
+		cc:      cc,
251
+		lb:      lb,
252
+		backoff: lb.backoff,
253
+		done:    make(chan struct{}),
254
+	}
255
+	lb.ccRemoteLB = ccw
256
+	ccw.wg.Add(1)
257
+	go ccw.watchRemoteBalancer()
258
+}
259
+
260
+// close closed the ClientConn to remote balancer, and waits until all
261
+// goroutines to finish.
262
+func (ccw *remoteBalancerCCWrapper) close() {
263
+	close(ccw.done)
264
+	ccw.cc.Close()
265
+	ccw.wg.Wait()
266
+}
267
+
268
+func (ccw *remoteBalancerCCWrapper) readServerList(s *balanceLoadClientStream) error {
269
+	for {
270
+		reply, err := s.Recv()
271
+		if err != nil {
272
+			if err == io.EOF {
273
+				return errServerTerminatedConnection
274
+			}
275
+			return fmt.Errorf("grpclb: failed to recv server list: %v", err)
276
+		}
277
+		if serverList := reply.GetServerList(); serverList != nil {
278
+			ccw.lb.processServerList(serverList)
279
+		}
280
+	}
281
+}
282
+
283
+func (ccw *remoteBalancerCCWrapper) sendLoadReport(s *balanceLoadClientStream, interval time.Duration) {
284
+	ticker := time.NewTicker(interval)
285
+	defer ticker.Stop()
286
+	lastZero := false
287
+	for {
288
+		select {
289
+		case <-ticker.C:
290
+		case <-s.Context().Done():
291
+			return
292
+		}
293
+		stats := ccw.lb.clientStats.toClientStats()
294
+		zero := isZeroStats(stats)
295
+		if zero && lastZero {
296
+			// Quash redundant empty load reports.
297
+			continue
298
+		}
299
+		lastZero = zero
300
+		t := time.Now()
301
+		stats.Timestamp = &timestamppb.Timestamp{
302
+			Seconds: t.Unix(),
303
+			Nanos:   int32(t.Nanosecond()),
304
+		}
305
+		if err := s.Send(&lbpb.LoadBalanceRequest{
306
+			LoadBalanceRequestType: &lbpb.LoadBalanceRequest_ClientStats{
307
+				ClientStats: stats,
308
+			},
309
+		}); err != nil {
310
+			return
311
+		}
312
+	}
313
+}
314
+
315
+func (ccw *remoteBalancerCCWrapper) callRemoteBalancer() (backoff bool, _ error) {
316
+	lbClient := &loadBalancerClient{cc: ccw.cc}
317
+	ctx, cancel := context.WithCancel(context.Background())
318
+	defer cancel()
319
+	stream, err := lbClient.BalanceLoad(ctx, grpc.WaitForReady(true))
320
+	if err != nil {
321
+		return true, fmt.Errorf("grpclb: failed to perform RPC to the remote balancer %v", err)
322
+	}
323
+	ccw.lb.mu.Lock()
324
+	ccw.lb.remoteBalancerConnected = true
325
+	ccw.lb.mu.Unlock()
326
+
327
+	// grpclb handshake on the stream.
328
+	initReq := &lbpb.LoadBalanceRequest{
329
+		LoadBalanceRequestType: &lbpb.LoadBalanceRequest_InitialRequest{
330
+			InitialRequest: &lbpb.InitialLoadBalanceRequest{
331
+				Name: ccw.lb.target,
332
+			},
333
+		},
334
+	}
335
+	if err := stream.Send(initReq); err != nil {
336
+		return true, fmt.Errorf("grpclb: failed to send init request: %v", err)
337
+	}
338
+	reply, err := stream.Recv()
339
+	if err != nil {
340
+		return true, fmt.Errorf("grpclb: failed to recv init response: %v", err)
341
+	}
342
+	initResp := reply.GetInitialResponse()
343
+	if initResp == nil {
344
+		return true, fmt.Errorf("grpclb: reply from remote balancer did not include initial response")
345
+	}
346
+	if initResp.LoadBalancerDelegate != "" {
347
+		return true, fmt.Errorf("grpclb: Delegation is not supported")
348
+	}
349
+
350
+	ccw.wg.Add(1)
351
+	go func() {
352
+		defer ccw.wg.Done()
353
+		if d := convertDuration(initResp.ClientStatsReportInterval); d > 0 {
354
+			ccw.sendLoadReport(stream, d)
355
+		}
356
+	}()
357
+	// No backoff if init req/resp handshake was successful.
358
+	return false, ccw.readServerList(stream)
359
+}
360
+
361
+func (ccw *remoteBalancerCCWrapper) watchRemoteBalancer() {
362
+	defer ccw.wg.Done()
363
+	var retryCount int
364
+	for {
365
+		doBackoff, err := ccw.callRemoteBalancer()
366
+		select {
367
+		case <-ccw.done:
368
+			return
369
+		default:
370
+			if err != nil {
371
+				if err == errServerTerminatedConnection {
372
+					grpclog.Info(err)
373
+				} else {
374
+					grpclog.Warning(err)
375
+				}
376
+			}
377
+		}
378
+		// Trigger a re-resolve when the stream errors.
379
+		ccw.lb.cc.cc.ResolveNow(resolver.ResolveNowOptions{})
380
+
381
+		ccw.lb.mu.Lock()
382
+		ccw.lb.remoteBalancerConnected = false
383
+		ccw.lb.fullServerList = nil
384
+		// Enter fallback when connection to remote balancer is lost, and the
385
+		// aggregated state is not Ready.
386
+		if !ccw.lb.inFallback && ccw.lb.state != connectivity.Ready {
387
+			// Entering fallback.
388
+			ccw.lb.refreshSubConns(ccw.lb.resolvedBackendAddrs, true, ccw.lb.usePickFirst)
389
+		}
390
+		ccw.lb.mu.Unlock()
391
+
392
+		if !doBackoff {
393
+			retryCount = 0
394
+			continue
395
+		}
396
+
397
+		timer := time.NewTimer(ccw.backoff.Backoff(retryCount)) // Copy backoff
398
+		select {
399
+		case <-timer.C:
400
+		case <-ccw.done:
401
+			timer.Stop()
402
+			return
403
+		}
404
+		retryCount++
405
+	}
406
+}
0 407
new file mode 100644
... ...
@@ -0,0 +1,208 @@
0
+/*
1
+ *
2
+ * Copyright 2016 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+package grpclb
19
+
20
+import (
21
+	"fmt"
22
+	"sync"
23
+	"time"
24
+
25
+	"google.golang.org/grpc/balancer"
26
+	"google.golang.org/grpc/resolver"
27
+)
28
+
29
+// The parent ClientConn should re-resolve when grpclb loses connection to the
30
+// remote balancer. When the ClientConn inside grpclb gets a TransientFailure,
31
+// it calls lbManualResolver.ResolveNow(), which calls parent ClientConn's
32
+// ResolveNow, and eventually results in re-resolve happening in parent
33
+// ClientConn's resolver (DNS for example).
34
+//
35
+//                          parent
36
+//                          ClientConn
37
+//  +-----------------------------------------------------------------+
38
+//  |             parent          +---------------------------------+ |
39
+//  | DNS         ClientConn      |  grpclb                         | |
40
+//  | resolver    balancerWrapper |                                 | |
41
+//  | +              +            |    grpclb          grpclb       | |
42
+//  | |              |            |    ManualResolver  ClientConn   | |
43
+//  | |              |            |     +              +            | |
44
+//  | |              |            |     |              | Transient  | |
45
+//  | |              |            |     |              | Failure    | |
46
+//  | |              |            |     |  <---------  |            | |
47
+//  | |              | <--------------- |  ResolveNow  |            | |
48
+//  | |  <---------  | ResolveNow |     |              |            | |
49
+//  | |  ResolveNow  |            |     |              |            | |
50
+//  | |              |            |     |              |            | |
51
+//  | +              +            |     +              +            | |
52
+//  |                             +---------------------------------+ |
53
+//  +-----------------------------------------------------------------+
54
+
55
+// lbManualResolver is used by the ClientConn inside grpclb. It's a manual
56
+// resolver with a special ResolveNow() function.
57
+//
58
+// When ResolveNow() is called, it calls ResolveNow() on the parent ClientConn,
59
+// so when grpclb client lose contact with remote balancers, the parent
60
+// ClientConn's resolver will re-resolve.
61
+type lbManualResolver struct {
62
+	scheme string
63
+	ccr    resolver.ClientConn
64
+
65
+	ccb balancer.ClientConn
66
+}
67
+
68
+func (r *lbManualResolver) Build(_ resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) (resolver.Resolver, error) {
69
+	r.ccr = cc
70
+	return r, nil
71
+}
72
+
73
+func (r *lbManualResolver) Scheme() string {
74
+	return r.scheme
75
+}
76
+
77
+// ResolveNow calls resolveNow on the parent ClientConn.
78
+func (r *lbManualResolver) ResolveNow(o resolver.ResolveNowOptions) {
79
+	r.ccb.ResolveNow(o)
80
+}
81
+
82
+// Close is a noop for Resolver.
83
+func (*lbManualResolver) Close() {}
84
+
85
+// UpdateState calls cc.UpdateState.
86
+func (r *lbManualResolver) UpdateState(s resolver.State) {
87
+	r.ccr.UpdateState(s)
88
+}
89
+
90
+const subConnCacheTime = time.Second * 10
91
+
92
+// lbCacheClientConn is a wrapper balancer.ClientConn with a SubConn cache.
93
+// SubConns will be kept in cache for subConnCacheTime before being removed.
94
+//
95
+// Its new and remove methods are updated to do cache first.
96
+type lbCacheClientConn struct {
97
+	cc      balancer.ClientConn
98
+	timeout time.Duration
99
+
100
+	mu sync.Mutex
101
+	// subConnCache only keeps subConns that are being deleted.
102
+	subConnCache  map[resolver.Address]*subConnCacheEntry
103
+	subConnToAddr map[balancer.SubConn]resolver.Address
104
+}
105
+
106
+type subConnCacheEntry struct {
107
+	sc balancer.SubConn
108
+
109
+	cancel        func()
110
+	abortDeleting bool
111
+}
112
+
113
+func newLBCacheClientConn(cc balancer.ClientConn) *lbCacheClientConn {
114
+	return &lbCacheClientConn{
115
+		cc:            cc,
116
+		timeout:       subConnCacheTime,
117
+		subConnCache:  make(map[resolver.Address]*subConnCacheEntry),
118
+		subConnToAddr: make(map[balancer.SubConn]resolver.Address),
119
+	}
120
+}
121
+
122
+func (ccc *lbCacheClientConn) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
123
+	if len(addrs) != 1 {
124
+		return nil, fmt.Errorf("grpclb calling NewSubConn with addrs of length %v", len(addrs))
125
+	}
126
+	addrWithoutMD := addrs[0]
127
+	addrWithoutMD.Metadata = nil
128
+
129
+	ccc.mu.Lock()
130
+	defer ccc.mu.Unlock()
131
+	if entry, ok := ccc.subConnCache[addrWithoutMD]; ok {
132
+		// If entry is in subConnCache, the SubConn was being deleted.
133
+		// cancel function will never be nil.
134
+		entry.cancel()
135
+		delete(ccc.subConnCache, addrWithoutMD)
136
+		return entry.sc, nil
137
+	}
138
+
139
+	scNew, err := ccc.cc.NewSubConn(addrs, opts)
140
+	if err != nil {
141
+		return nil, err
142
+	}
143
+
144
+	ccc.subConnToAddr[scNew] = addrWithoutMD
145
+	return scNew, nil
146
+}
147
+
148
+func (ccc *lbCacheClientConn) RemoveSubConn(sc balancer.SubConn) {
149
+	ccc.mu.Lock()
150
+	defer ccc.mu.Unlock()
151
+	addr, ok := ccc.subConnToAddr[sc]
152
+	if !ok {
153
+		return
154
+	}
155
+
156
+	if entry, ok := ccc.subConnCache[addr]; ok {
157
+		if entry.sc != sc {
158
+			// This could happen if NewSubConn was called multiple times for the
159
+			// same address, and those SubConns are all removed. We remove sc
160
+			// immediately here.
161
+			delete(ccc.subConnToAddr, sc)
162
+			ccc.cc.RemoveSubConn(sc)
163
+		}
164
+		return
165
+	}
166
+
167
+	entry := &subConnCacheEntry{
168
+		sc: sc,
169
+	}
170
+	ccc.subConnCache[addr] = entry
171
+
172
+	timer := time.AfterFunc(ccc.timeout, func() {
173
+		ccc.mu.Lock()
174
+		defer ccc.mu.Unlock()
175
+		if entry.abortDeleting {
176
+			return
177
+		}
178
+		ccc.cc.RemoveSubConn(sc)
179
+		delete(ccc.subConnToAddr, sc)
180
+		delete(ccc.subConnCache, addr)
181
+	})
182
+	entry.cancel = func() {
183
+		if !timer.Stop() {
184
+			// If stop was not successful, the timer has fired (this can only
185
+			// happen in a race). But the deleting function is blocked on ccc.mu
186
+			// because the mutex was held by the caller of this function.
187
+			//
188
+			// Set abortDeleting to true to abort the deleting function. When
189
+			// the lock is released, the deleting function will acquire the
190
+			// lock, check the value of abortDeleting and return.
191
+			entry.abortDeleting = true
192
+		}
193
+	}
194
+}
195
+
196
+func (ccc *lbCacheClientConn) UpdateState(s balancer.State) {
197
+	ccc.cc.UpdateState(s)
198
+}
199
+
200
+func (ccc *lbCacheClientConn) close() {
201
+	ccc.mu.Lock()
202
+	// Only cancel all existing timers. There's no need to remove SubConns.
203
+	for _, entry := range ccc.subConnCache {
204
+		entry.cancel()
205
+	}
206
+	ccc.mu.Unlock()
207
+}
0 208
new file mode 100644
... ...
@@ -0,0 +1,330 @@
0
+/*
1
+ *
2
+ * Copyright 2018 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+// Package alts implements the ALTS credential support by gRPC library, which
19
+// encapsulates all the state needed by a client to authenticate with a server
20
+// using ALTS and make various assertions, e.g., about the client's identity,
21
+// role, or whether it is authorized to make a particular call.
22
+// This package is experimental.
23
+package alts
24
+
25
+import (
26
+	"context"
27
+	"errors"
28
+	"fmt"
29
+	"net"
30
+	"sync"
31
+	"time"
32
+
33
+	"google.golang.org/grpc/credentials"
34
+	core "google.golang.org/grpc/credentials/alts/internal"
35
+	"google.golang.org/grpc/credentials/alts/internal/handshaker"
36
+	"google.golang.org/grpc/credentials/alts/internal/handshaker/service"
37
+	altspb "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
38
+	"google.golang.org/grpc/grpclog"
39
+)
40
+
41
+const (
42
+	// hypervisorHandshakerServiceAddress represents the default ALTS gRPC
43
+	// handshaker service address in the hypervisor.
44
+	hypervisorHandshakerServiceAddress = "metadata.google.internal:8080"
45
+	// defaultTimeout specifies the server handshake timeout.
46
+	defaultTimeout = 30.0 * time.Second
47
+	// The following constants specify the minimum and maximum acceptable
48
+	// protocol versions.
49
+	protocolVersionMaxMajor = 2
50
+	protocolVersionMaxMinor = 1
51
+	protocolVersionMinMajor = 2
52
+	protocolVersionMinMinor = 1
53
+)
54
+
55
+var (
56
+	once          sync.Once
57
+	maxRPCVersion = &altspb.RpcProtocolVersions_Version{
58
+		Major: protocolVersionMaxMajor,
59
+		Minor: protocolVersionMaxMinor,
60
+	}
61
+	minRPCVersion = &altspb.RpcProtocolVersions_Version{
62
+		Major: protocolVersionMinMajor,
63
+		Minor: protocolVersionMinMinor,
64
+	}
65
+	// ErrUntrustedPlatform is returned from ClientHandshake and
66
+	// ServerHandshake is running on a platform where the trustworthiness of
67
+	// the handshaker service is not guaranteed.
68
+	ErrUntrustedPlatform = errors.New("ALTS: untrusted platform. ALTS is only supported on GCP")
69
+)
70
+
71
+// AuthInfo exposes security information from the ALTS handshake to the
72
+// application. This interface is to be implemented by ALTS. Users should not
73
+// need a brand new implementation of this interface. For situations like
74
+// testing, any new implementation should embed this interface. This allows
75
+// ALTS to add new methods to this interface.
76
+type AuthInfo interface {
77
+	// ApplicationProtocol returns application protocol negotiated for the
78
+	// ALTS connection.
79
+	ApplicationProtocol() string
80
+	// RecordProtocol returns the record protocol negotiated for the ALTS
81
+	// connection.
82
+	RecordProtocol() string
83
+	// SecurityLevel returns the security level of the created ALTS secure
84
+	// channel.
85
+	SecurityLevel() altspb.SecurityLevel
86
+	// PeerServiceAccount returns the peer service account.
87
+	PeerServiceAccount() string
88
+	// LocalServiceAccount returns the local service account.
89
+	LocalServiceAccount() string
90
+	// PeerRPCVersions returns the RPC version supported by the peer.
91
+	PeerRPCVersions() *altspb.RpcProtocolVersions
92
+}
93
+
94
+// ClientOptions contains the client-side options of an ALTS channel. These
95
+// options will be passed to the underlying ALTS handshaker.
96
+type ClientOptions struct {
97
+	// TargetServiceAccounts contains a list of expected target service
98
+	// accounts.
99
+	TargetServiceAccounts []string
100
+	// HandshakerServiceAddress represents the ALTS handshaker gRPC service
101
+	// address to connect to.
102
+	HandshakerServiceAddress string
103
+}
104
+
105
+// DefaultClientOptions creates a new ClientOptions object with the default
106
+// values.
107
+func DefaultClientOptions() *ClientOptions {
108
+	return &ClientOptions{
109
+		HandshakerServiceAddress: hypervisorHandshakerServiceAddress,
110
+	}
111
+}
112
+
113
+// ServerOptions contains the server-side options of an ALTS channel. These
114
+// options will be passed to the underlying ALTS handshaker.
115
+type ServerOptions struct {
116
+	// HandshakerServiceAddress represents the ALTS handshaker gRPC service
117
+	// address to connect to.
118
+	HandshakerServiceAddress string
119
+}
120
+
121
+// DefaultServerOptions creates a new ServerOptions object with the default
122
+// values.
123
+func DefaultServerOptions() *ServerOptions {
124
+	return &ServerOptions{
125
+		HandshakerServiceAddress: hypervisorHandshakerServiceAddress,
126
+	}
127
+}
128
+
129
+// altsTC is the credentials required for authenticating a connection using ALTS.
130
+// It implements credentials.TransportCredentials interface.
131
+type altsTC struct {
132
+	info      *credentials.ProtocolInfo
133
+	side      core.Side
134
+	accounts  []string
135
+	hsAddress string
136
+}
137
+
138
+// NewClientCreds constructs a client-side ALTS TransportCredentials object.
139
+func NewClientCreds(opts *ClientOptions) credentials.TransportCredentials {
140
+	return newALTS(core.ClientSide, opts.TargetServiceAccounts, opts.HandshakerServiceAddress)
141
+}
142
+
143
+// NewServerCreds constructs a server-side ALTS TransportCredentials object.
144
+func NewServerCreds(opts *ServerOptions) credentials.TransportCredentials {
145
+	return newALTS(core.ServerSide, nil, opts.HandshakerServiceAddress)
146
+}
147
+
148
+func newALTS(side core.Side, accounts []string, hsAddress string) credentials.TransportCredentials {
149
+	once.Do(func() {
150
+		vmOnGCP = isRunningOnGCP()
151
+	})
152
+
153
+	if hsAddress == "" {
154
+		hsAddress = hypervisorHandshakerServiceAddress
155
+	}
156
+	return &altsTC{
157
+		info: &credentials.ProtocolInfo{
158
+			SecurityProtocol: "alts",
159
+			SecurityVersion:  "1.0",
160
+		},
161
+		side:      side,
162
+		accounts:  accounts,
163
+		hsAddress: hsAddress,
164
+	}
165
+}
166
+
167
+// ClientHandshake implements the client side handshake protocol.
168
+func (g *altsTC) ClientHandshake(ctx context.Context, addr string, rawConn net.Conn) (_ net.Conn, _ credentials.AuthInfo, err error) {
169
+	if !vmOnGCP {
170
+		return nil, nil, ErrUntrustedPlatform
171
+	}
172
+
173
+	// Connecting to ALTS handshaker service.
174
+	hsConn, err := service.Dial(g.hsAddress)
175
+	if err != nil {
176
+		return nil, nil, err
177
+	}
178
+	// Do not close hsConn since it is shared with other handshakes.
179
+
180
+	// Possible context leak:
181
+	// The cancel function for the child context we create will only be
182
+	// called a non-nil error is returned.
183
+	var cancel context.CancelFunc
184
+	ctx, cancel = context.WithCancel(ctx)
185
+	defer func() {
186
+		if err != nil {
187
+			cancel()
188
+		}
189
+	}()
190
+
191
+	opts := handshaker.DefaultClientHandshakerOptions()
192
+	opts.TargetName = addr
193
+	opts.TargetServiceAccounts = g.accounts
194
+	opts.RPCVersions = &altspb.RpcProtocolVersions{
195
+		MaxRpcVersion: maxRPCVersion,
196
+		MinRpcVersion: minRPCVersion,
197
+	}
198
+	chs, err := handshaker.NewClientHandshaker(ctx, hsConn, rawConn, opts)
199
+	if err != nil {
200
+		return nil, nil, err
201
+	}
202
+	defer func() {
203
+		if err != nil {
204
+			chs.Close()
205
+		}
206
+	}()
207
+	secConn, authInfo, err := chs.ClientHandshake(ctx)
208
+	if err != nil {
209
+		return nil, nil, err
210
+	}
211
+	altsAuthInfo, ok := authInfo.(AuthInfo)
212
+	if !ok {
213
+		return nil, nil, errors.New("client-side auth info is not of type alts.AuthInfo")
214
+	}
215
+	match, _ := checkRPCVersions(opts.RPCVersions, altsAuthInfo.PeerRPCVersions())
216
+	if !match {
217
+		return nil, nil, fmt.Errorf("server-side RPC versions are not compatible with this client, local versions: %v, peer versions: %v", opts.RPCVersions, altsAuthInfo.PeerRPCVersions())
218
+	}
219
+	return secConn, authInfo, nil
220
+}
221
+
222
+// ServerHandshake implements the server side ALTS handshaker.
223
+func (g *altsTC) ServerHandshake(rawConn net.Conn) (_ net.Conn, _ credentials.AuthInfo, err error) {
224
+	if !vmOnGCP {
225
+		return nil, nil, ErrUntrustedPlatform
226
+	}
227
+	// Connecting to ALTS handshaker service.
228
+	hsConn, err := service.Dial(g.hsAddress)
229
+	if err != nil {
230
+		return nil, nil, err
231
+	}
232
+	// Do not close hsConn since it's shared with other handshakes.
233
+
234
+	ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
235
+	defer cancel()
236
+	opts := handshaker.DefaultServerHandshakerOptions()
237
+	opts.RPCVersions = &altspb.RpcProtocolVersions{
238
+		MaxRpcVersion: maxRPCVersion,
239
+		MinRpcVersion: minRPCVersion,
240
+	}
241
+	shs, err := handshaker.NewServerHandshaker(ctx, hsConn, rawConn, opts)
242
+	if err != nil {
243
+		return nil, nil, err
244
+	}
245
+	defer func() {
246
+		if err != nil {
247
+			shs.Close()
248
+		}
249
+	}()
250
+	secConn, authInfo, err := shs.ServerHandshake(ctx)
251
+	if err != nil {
252
+		return nil, nil, err
253
+	}
254
+	altsAuthInfo, ok := authInfo.(AuthInfo)
255
+	if !ok {
256
+		return nil, nil, errors.New("server-side auth info is not of type alts.AuthInfo")
257
+	}
258
+	match, _ := checkRPCVersions(opts.RPCVersions, altsAuthInfo.PeerRPCVersions())
259
+	if !match {
260
+		return nil, nil, fmt.Errorf("client-side RPC versions is not compatible with this server, local versions: %v, peer versions: %v", opts.RPCVersions, altsAuthInfo.PeerRPCVersions())
261
+	}
262
+	return secConn, authInfo, nil
263
+}
264
+
265
+func (g *altsTC) Info() credentials.ProtocolInfo {
266
+	return *g.info
267
+}
268
+
269
+func (g *altsTC) Clone() credentials.TransportCredentials {
270
+	info := *g.info
271
+	var accounts []string
272
+	if g.accounts != nil {
273
+		accounts = make([]string, len(g.accounts))
274
+		copy(accounts, g.accounts)
275
+	}
276
+	return &altsTC{
277
+		info:      &info,
278
+		side:      g.side,
279
+		hsAddress: g.hsAddress,
280
+		accounts:  accounts,
281
+	}
282
+}
283
+
284
+func (g *altsTC) OverrideServerName(serverNameOverride string) error {
285
+	g.info.ServerName = serverNameOverride
286
+	return nil
287
+}
288
+
289
+// compareRPCVersion returns 0 if v1 == v2, 1 if v1 > v2 and -1 if v1 < v2.
290
+func compareRPCVersions(v1, v2 *altspb.RpcProtocolVersions_Version) int {
291
+	switch {
292
+	case v1.GetMajor() > v2.GetMajor(),
293
+		v1.GetMajor() == v2.GetMajor() && v1.GetMinor() > v2.GetMinor():
294
+		return 1
295
+	case v1.GetMajor() < v2.GetMajor(),
296
+		v1.GetMajor() == v2.GetMajor() && v1.GetMinor() < v2.GetMinor():
297
+		return -1
298
+	}
299
+	return 0
300
+}
301
+
302
+// checkRPCVersions performs a version check between local and peer rpc protocol
303
+// versions. This function returns true if the check passes which means both
304
+// parties agreed on a common rpc protocol to use, and false otherwise. The
305
+// function also returns the highest common RPC protocol version both parties
306
+// agreed on.
307
+func checkRPCVersions(local, peer *altspb.RpcProtocolVersions) (bool, *altspb.RpcProtocolVersions_Version) {
308
+	if local == nil || peer == nil {
309
+		grpclog.Error("invalid checkRPCVersions argument, either local or peer is nil.")
310
+		return false, nil
311
+	}
312
+
313
+	// maxCommonVersion is MIN(local.max, peer.max).
314
+	maxCommonVersion := local.GetMaxRpcVersion()
315
+	if compareRPCVersions(local.GetMaxRpcVersion(), peer.GetMaxRpcVersion()) > 0 {
316
+		maxCommonVersion = peer.GetMaxRpcVersion()
317
+	}
318
+
319
+	// minCommonVersion is MAX(local.min, peer.min).
320
+	minCommonVersion := peer.GetMinRpcVersion()
321
+	if compareRPCVersions(local.GetMinRpcVersion(), peer.GetMinRpcVersion()) > 0 {
322
+		minCommonVersion = local.GetMinRpcVersion()
323
+	}
324
+
325
+	if compareRPCVersions(maxCommonVersion, minCommonVersion) < 0 {
326
+		return false, nil
327
+	}
328
+	return true, maxCommonVersion
329
+}
0 330
new file mode 100644
... ...
@@ -0,0 +1,89 @@
0
+/*
1
+ *
2
+ * Copyright 2018 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+// Package authinfo provide authentication information returned by handshakers.
19
+package authinfo
20
+
21
+import (
22
+	"google.golang.org/grpc/credentials"
23
+	altspb "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
24
+)
25
+
26
+var _ credentials.AuthInfo = (*altsAuthInfo)(nil)
27
+
28
+// altsAuthInfo exposes security information from the ALTS handshake to the
29
+// application. altsAuthInfo is immutable and implements credentials.AuthInfo.
30
+type altsAuthInfo struct {
31
+	p *altspb.AltsContext
32
+	credentials.CommonAuthInfo
33
+}
34
+
35
+// New returns a new altsAuthInfo object given handshaker results.
36
+func New(result *altspb.HandshakerResult) credentials.AuthInfo {
37
+	return newAuthInfo(result)
38
+}
39
+
40
+func newAuthInfo(result *altspb.HandshakerResult) *altsAuthInfo {
41
+	return &altsAuthInfo{
42
+		p: &altspb.AltsContext{
43
+			ApplicationProtocol: result.GetApplicationProtocol(),
44
+			RecordProtocol:      result.GetRecordProtocol(),
45
+			// TODO: assign security level from result.
46
+			SecurityLevel:       altspb.SecurityLevel_INTEGRITY_AND_PRIVACY,
47
+			PeerServiceAccount:  result.GetPeerIdentity().GetServiceAccount(),
48
+			LocalServiceAccount: result.GetLocalIdentity().GetServiceAccount(),
49
+			PeerRpcVersions:     result.GetPeerRpcVersions(),
50
+		},
51
+		CommonAuthInfo: credentials.CommonAuthInfo{SecurityLevel: credentials.PrivacyAndIntegrity},
52
+	}
53
+}
54
+
55
+// AuthType identifies the context as providing ALTS authentication information.
56
+func (s *altsAuthInfo) AuthType() string {
57
+	return "alts"
58
+}
59
+
60
+// ApplicationProtocol returns the context's application protocol.
61
+func (s *altsAuthInfo) ApplicationProtocol() string {
62
+	return s.p.GetApplicationProtocol()
63
+}
64
+
65
+// RecordProtocol returns the context's record protocol.
66
+func (s *altsAuthInfo) RecordProtocol() string {
67
+	return s.p.GetRecordProtocol()
68
+}
69
+
70
+// SecurityLevel returns the context's security level.
71
+func (s *altsAuthInfo) SecurityLevel() altspb.SecurityLevel {
72
+	return s.p.GetSecurityLevel()
73
+}
74
+
75
+// PeerServiceAccount returns the context's peer service account.
76
+func (s *altsAuthInfo) PeerServiceAccount() string {
77
+	return s.p.GetPeerServiceAccount()
78
+}
79
+
80
+// LocalServiceAccount returns the context's local service account.
81
+func (s *altsAuthInfo) LocalServiceAccount() string {
82
+	return s.p.GetLocalServiceAccount()
83
+}
84
+
85
+// PeerRPCVersions returns the context's peer RPC versions.
86
+func (s *altsAuthInfo) PeerRPCVersions() *altspb.RpcProtocolVersions {
87
+	return s.p.GetPeerRpcVersions()
88
+}
0 89
new file mode 100644
... ...
@@ -0,0 +1,69 @@
0
+/*
1
+ *
2
+ * Copyright 2018 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+//go:generate ./regenerate.sh
19
+
20
+// Package internal contains common core functionality for ALTS.
21
+package internal
22
+
23
+import (
24
+	"context"
25
+	"net"
26
+
27
+	"google.golang.org/grpc/credentials"
28
+)
29
+
30
+const (
31
+	// ClientSide identifies the client in this communication.
32
+	ClientSide Side = iota
33
+	// ServerSide identifies the server in this communication.
34
+	ServerSide
35
+)
36
+
37
+// PeerNotRespondingError is returned when a peer server is not responding
38
+// after a channel has been established. It is treated as a temporary connection
39
+// error and re-connection to the server should be attempted.
40
+var PeerNotRespondingError = &peerNotRespondingError{}
41
+
42
+// Side identifies the party's role: client or server.
43
+type Side int
44
+
45
+type peerNotRespondingError struct{}
46
+
47
+// Return an error message for the purpose of logging.
48
+func (e *peerNotRespondingError) Error() string {
49
+	return "peer server is not responding and re-connection should be attempted."
50
+}
51
+
52
+// Temporary indicates if this connection error is temporary or fatal.
53
+func (e *peerNotRespondingError) Temporary() bool {
54
+	return true
55
+}
56
+
57
+// Handshaker defines a ALTS handshaker interface.
58
+type Handshaker interface {
59
+	// ClientHandshake starts and completes a client-side handshaking and
60
+	// returns a secure connection and corresponding auth information.
61
+	ClientHandshake(ctx context.Context) (net.Conn, credentials.AuthInfo, error)
62
+	// ServerHandshake starts and completes a server-side handshaking and
63
+	// returns a secure connection and corresponding auth information.
64
+	ServerHandshake(ctx context.Context) (net.Conn, credentials.AuthInfo, error)
65
+	// Close terminates the Handshaker. It should be called when the caller
66
+	// obtains the secure connection.
67
+	Close()
68
+}
0 69
new file mode 100644
... ...
@@ -0,0 +1,131 @@
0
+/*
1
+ *
2
+ * Copyright 2018 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+package conn
19
+
20
+import (
21
+	"bytes"
22
+	"crypto/aes"
23
+	"crypto/cipher"
24
+	"crypto/hmac"
25
+	"crypto/sha256"
26
+	"encoding/binary"
27
+	"fmt"
28
+	"strconv"
29
+)
30
+
31
+// rekeyAEAD holds the necessary information for an AEAD based on
32
+// AES-GCM that performs nonce-based key derivation and XORs the
33
+// nonce with a random mask.
34
+type rekeyAEAD struct {
35
+	kdfKey     []byte
36
+	kdfCounter []byte
37
+	nonceMask  []byte
38
+	nonceBuf   []byte
39
+	gcmAEAD    cipher.AEAD
40
+}
41
+
42
+// KeySizeError signals that the given key does not have the correct size.
43
+type KeySizeError int
44
+
45
+func (k KeySizeError) Error() string {
46
+	return "alts/conn: invalid key size " + strconv.Itoa(int(k))
47
+}
48
+
49
+// newRekeyAEAD creates a new instance of aes128gcm with rekeying.
50
+// The key argument should be 44 bytes, the first 32 bytes are used as a key
51
+// for HKDF-expand and the remainining 12 bytes are used as a random mask for
52
+// the counter.
53
+func newRekeyAEAD(key []byte) (*rekeyAEAD, error) {
54
+	k := len(key)
55
+	if k != kdfKeyLen+nonceLen {
56
+		return nil, KeySizeError(k)
57
+	}
58
+	return &rekeyAEAD{
59
+		kdfKey:     key[:kdfKeyLen],
60
+		kdfCounter: make([]byte, kdfCounterLen),
61
+		nonceMask:  key[kdfKeyLen:],
62
+		nonceBuf:   make([]byte, nonceLen),
63
+		gcmAEAD:    nil,
64
+	}, nil
65
+}
66
+
67
+// Seal rekeys if nonce[2:8] is different than in the last call, masks the nonce,
68
+// and calls Seal for aes128gcm.
69
+func (s *rekeyAEAD) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
70
+	if err := s.rekeyIfRequired(nonce); err != nil {
71
+		panic(fmt.Sprintf("Rekeying failed with: %s", err.Error()))
72
+	}
73
+	maskNonce(s.nonceBuf, nonce, s.nonceMask)
74
+	return s.gcmAEAD.Seal(dst, s.nonceBuf, plaintext, additionalData)
75
+}
76
+
77
+// Open rekeys if nonce[2:8] is different than in the last call, masks the nonce,
78
+// and calls Open for aes128gcm.
79
+func (s *rekeyAEAD) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
80
+	if err := s.rekeyIfRequired(nonce); err != nil {
81
+		return nil, err
82
+	}
83
+	maskNonce(s.nonceBuf, nonce, s.nonceMask)
84
+	return s.gcmAEAD.Open(dst, s.nonceBuf, ciphertext, additionalData)
85
+}
86
+
87
+// rekeyIfRequired creates a new aes128gcm AEAD if the existing AEAD is nil
88
+// or cannot be used with given nonce.
89
+func (s *rekeyAEAD) rekeyIfRequired(nonce []byte) error {
90
+	newKdfCounter := nonce[kdfCounterOffset : kdfCounterOffset+kdfCounterLen]
91
+	if s.gcmAEAD != nil && bytes.Equal(newKdfCounter, s.kdfCounter) {
92
+		return nil
93
+	}
94
+	copy(s.kdfCounter, newKdfCounter)
95
+	a, err := aes.NewCipher(hkdfExpand(s.kdfKey, s.kdfCounter))
96
+	if err != nil {
97
+		return err
98
+	}
99
+	s.gcmAEAD, err = cipher.NewGCM(a)
100
+	return err
101
+}
102
+
103
+// maskNonce XORs the given nonce with the mask and stores the result in dst.
104
+func maskNonce(dst, nonce, mask []byte) {
105
+	nonce1 := binary.LittleEndian.Uint64(nonce[:sizeUint64])
106
+	nonce2 := binary.LittleEndian.Uint32(nonce[sizeUint64:])
107
+	mask1 := binary.LittleEndian.Uint64(mask[:sizeUint64])
108
+	mask2 := binary.LittleEndian.Uint32(mask[sizeUint64:])
109
+	binary.LittleEndian.PutUint64(dst[:sizeUint64], nonce1^mask1)
110
+	binary.LittleEndian.PutUint32(dst[sizeUint64:], nonce2^mask2)
111
+}
112
+
113
+// NonceSize returns the required nonce size.
114
+func (s *rekeyAEAD) NonceSize() int {
115
+	return s.gcmAEAD.NonceSize()
116
+}
117
+
118
+// Overhead returns the ciphertext overhead.
119
+func (s *rekeyAEAD) Overhead() int {
120
+	return s.gcmAEAD.Overhead()
121
+}
122
+
123
+// hkdfExpand computes the first 16 bytes of the HKDF-expand function
124
+// defined in RFC5869.
125
+func hkdfExpand(key, info []byte) []byte {
126
+	mac := hmac.New(sha256.New, key)
127
+	mac.Write(info)
128
+	mac.Write([]byte{0x01}[:])
129
+	return mac.Sum(nil)[:aeadKeyLen]
130
+}
0 131
new file mode 100644
... ...
@@ -0,0 +1,105 @@
0
+/*
1
+ *
2
+ * Copyright 2018 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+package conn
19
+
20
+import (
21
+	"crypto/aes"
22
+	"crypto/cipher"
23
+
24
+	core "google.golang.org/grpc/credentials/alts/internal"
25
+)
26
+
27
+const (
28
+	// Overflow length n in bytes, never encrypt more than 2^(n*8) frames (in
29
+	// each direction).
30
+	overflowLenAES128GCM = 5
31
+)
32
+
33
+// aes128gcm is the struct that holds necessary information for ALTS record.
34
+// The counter value is NOT included in the payload during the encryption and
35
+// decryption operations.
36
+type aes128gcm struct {
37
+	// inCounter is used in ALTS record to check that incoming counters are
38
+	// as expected, since ALTS record guarantees that messages are unwrapped
39
+	// in the same order that the peer wrapped them.
40
+	inCounter  Counter
41
+	outCounter Counter
42
+	aead       cipher.AEAD
43
+}
44
+
45
+// NewAES128GCM creates an instance that uses aes128gcm for ALTS record.
46
+func NewAES128GCM(side core.Side, key []byte) (ALTSRecordCrypto, error) {
47
+	c, err := aes.NewCipher(key)
48
+	if err != nil {
49
+		return nil, err
50
+	}
51
+	a, err := cipher.NewGCM(c)
52
+	if err != nil {
53
+		return nil, err
54
+	}
55
+	return &aes128gcm{
56
+		inCounter:  NewInCounter(side, overflowLenAES128GCM),
57
+		outCounter: NewOutCounter(side, overflowLenAES128GCM),
58
+		aead:       a,
59
+	}, nil
60
+}
61
+
62
+// Encrypt is the encryption function. dst can contain bytes at the beginning of
63
+// the ciphertext that will not be encrypted but will be authenticated. If dst
64
+// has enough capacity to hold these bytes, the ciphertext and the tag, no
65
+// allocation and copy operations will be performed. dst and plaintext do not
66
+// overlap.
67
+func (s *aes128gcm) Encrypt(dst, plaintext []byte) ([]byte, error) {
68
+	// If we need to allocate an output buffer, we want to include space for
69
+	// GCM tag to avoid forcing ALTS record to reallocate as well.
70
+	dlen := len(dst)
71
+	dst, out := SliceForAppend(dst, len(plaintext)+GcmTagSize)
72
+	seq, err := s.outCounter.Value()
73
+	if err != nil {
74
+		return nil, err
75
+	}
76
+	data := out[:len(plaintext)]
77
+	copy(data, plaintext) // data may alias plaintext
78
+
79
+	// Seal appends the ciphertext and the tag to its first argument and
80
+	// returns the updated slice. However, SliceForAppend above ensures that
81
+	// dst has enough capacity to avoid a reallocation and copy due to the
82
+	// append.
83
+	dst = s.aead.Seal(dst[:dlen], seq, data, nil)
84
+	s.outCounter.Inc()
85
+	return dst, nil
86
+}
87
+
88
+func (s *aes128gcm) EncryptionOverhead() int {
89
+	return GcmTagSize
90
+}
91
+
92
+func (s *aes128gcm) Decrypt(dst, ciphertext []byte) ([]byte, error) {
93
+	seq, err := s.inCounter.Value()
94
+	if err != nil {
95
+		return nil, err
96
+	}
97
+	// If dst is equal to ciphertext[:0], ciphertext storage is reused.
98
+	plaintext, err := s.aead.Open(dst, seq, ciphertext, nil)
99
+	if err != nil {
100
+		return nil, ErrAuth
101
+	}
102
+	s.inCounter.Inc()
103
+	return plaintext, nil
104
+}
0 105
new file mode 100644
... ...
@@ -0,0 +1,116 @@
0
+/*
1
+ *
2
+ * Copyright 2018 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+package conn
19
+
20
+import (
21
+	"crypto/cipher"
22
+
23
+	core "google.golang.org/grpc/credentials/alts/internal"
24
+)
25
+
26
+const (
27
+	// Overflow length n in bytes, never encrypt more than 2^(n*8) frames (in
28
+	// each direction).
29
+	overflowLenAES128GCMRekey = 8
30
+	nonceLen                  = 12
31
+	aeadKeyLen                = 16
32
+	kdfKeyLen                 = 32
33
+	kdfCounterOffset          = 2
34
+	kdfCounterLen             = 6
35
+	sizeUint64                = 8
36
+)
37
+
38
+// aes128gcmRekey is the struct that holds necessary information for ALTS record.
39
+// The counter value is NOT included in the payload during the encryption and
40
+// decryption operations.
41
+type aes128gcmRekey struct {
42
+	// inCounter is used in ALTS record to check that incoming counters are
43
+	// as expected, since ALTS record guarantees that messages are unwrapped
44
+	// in the same order that the peer wrapped them.
45
+	inCounter  Counter
46
+	outCounter Counter
47
+	inAEAD     cipher.AEAD
48
+	outAEAD    cipher.AEAD
49
+}
50
+
51
+// NewAES128GCMRekey creates an instance that uses aes128gcm with rekeying
52
+// for ALTS record. The key argument should be 44 bytes, the first 32 bytes
53
+// are used as a key for HKDF-expand and the remainining 12 bytes are used
54
+// as a random mask for the counter.
55
+func NewAES128GCMRekey(side core.Side, key []byte) (ALTSRecordCrypto, error) {
56
+	inCounter := NewInCounter(side, overflowLenAES128GCMRekey)
57
+	outCounter := NewOutCounter(side, overflowLenAES128GCMRekey)
58
+	inAEAD, err := newRekeyAEAD(key)
59
+	if err != nil {
60
+		return nil, err
61
+	}
62
+	outAEAD, err := newRekeyAEAD(key)
63
+	if err != nil {
64
+		return nil, err
65
+	}
66
+	return &aes128gcmRekey{
67
+		inCounter,
68
+		outCounter,
69
+		inAEAD,
70
+		outAEAD,
71
+	}, nil
72
+}
73
+
74
+// Encrypt is the encryption function. dst can contain bytes at the beginning of
75
+// the ciphertext that will not be encrypted but will be authenticated. If dst
76
+// has enough capacity to hold these bytes, the ciphertext and the tag, no
77
+// allocation and copy operations will be performed. dst and plaintext do not
78
+// overlap.
79
+func (s *aes128gcmRekey) Encrypt(dst, plaintext []byte) ([]byte, error) {
80
+	// If we need to allocate an output buffer, we want to include space for
81
+	// GCM tag to avoid forcing ALTS record to reallocate as well.
82
+	dlen := len(dst)
83
+	dst, out := SliceForAppend(dst, len(plaintext)+GcmTagSize)
84
+	seq, err := s.outCounter.Value()
85
+	if err != nil {
86
+		return nil, err
87
+	}
88
+	data := out[:len(plaintext)]
89
+	copy(data, plaintext) // data may alias plaintext
90
+
91
+	// Seal appends the ciphertext and the tag to its first argument and
92
+	// returns the updated slice. However, SliceForAppend above ensures that
93
+	// dst has enough capacity to avoid a reallocation and copy due to the
94
+	// append.
95
+	dst = s.outAEAD.Seal(dst[:dlen], seq, data, nil)
96
+	s.outCounter.Inc()
97
+	return dst, nil
98
+}
99
+
100
+func (s *aes128gcmRekey) EncryptionOverhead() int {
101
+	return GcmTagSize
102
+}
103
+
104
+func (s *aes128gcmRekey) Decrypt(dst, ciphertext []byte) ([]byte, error) {
105
+	seq, err := s.inCounter.Value()
106
+	if err != nil {
107
+		return nil, err
108
+	}
109
+	plaintext, err := s.inAEAD.Open(dst, seq, ciphertext, nil)
110
+	if err != nil {
111
+		return nil, ErrAuth
112
+	}
113
+	s.inCounter.Inc()
114
+	return plaintext, nil
115
+}
0 116
new file mode 100644
... ...
@@ -0,0 +1,70 @@
0
+/*
1
+ *
2
+ * Copyright 2018 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+package conn
19
+
20
+import (
21
+	"encoding/binary"
22
+	"errors"
23
+	"fmt"
24
+)
25
+
26
+const (
27
+	// GcmTagSize is the GCM tag size is the difference in length between
28
+	// plaintext and ciphertext. From crypto/cipher/gcm.go in Go crypto
29
+	// library.
30
+	GcmTagSize = 16
31
+)
32
+
33
+// ErrAuth occurs on authentication failure.
34
+var ErrAuth = errors.New("message authentication failed")
35
+
36
+// SliceForAppend takes a slice and a requested number of bytes. It returns a
37
+// slice with the contents of the given slice followed by that many bytes and a
38
+// second slice that aliases into it and contains only the extra bytes. If the
39
+// original slice has sufficient capacity then no allocation is performed.
40
+func SliceForAppend(in []byte, n int) (head, tail []byte) {
41
+	if total := len(in) + n; cap(in) >= total {
42
+		head = in[:total]
43
+	} else {
44
+		head = make([]byte, total)
45
+		copy(head, in)
46
+	}
47
+	tail = head[len(in):]
48
+	return head, tail
49
+}
50
+
51
+// ParseFramedMsg parse the provided buffer and returns a frame of the format
52
+// msgLength+msg and any remaining bytes in that buffer.
53
+func ParseFramedMsg(b []byte, maxLen uint32) ([]byte, []byte, error) {
54
+	// If the size field is not complete, return the provided buffer as
55
+	// remaining buffer.
56
+	if len(b) < MsgLenFieldSize {
57
+		return nil, b, nil
58
+	}
59
+	msgLenField := b[:MsgLenFieldSize]
60
+	length := binary.LittleEndian.Uint32(msgLenField)
61
+	if length > maxLen {
62
+		return nil, nil, fmt.Errorf("received the frame length %d larger than the limit %d", length, maxLen)
63
+	}
64
+	if len(b) < int(length)+4 { // account for the first 4 msg length bytes.
65
+		// Frame is not complete yet.
66
+		return nil, b, nil
67
+	}
68
+	return b[:MsgLenFieldSize+length], b[MsgLenFieldSize+length:], nil
69
+}
0 70
new file mode 100644
... ...
@@ -0,0 +1,62 @@
0
+/*
1
+ *
2
+ * Copyright 2018 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+package conn
19
+
20
+import (
21
+	"errors"
22
+)
23
+
24
+const counterLen = 12
25
+
26
+var (
27
+	errInvalidCounter = errors.New("invalid counter")
28
+)
29
+
30
+// Counter is a 96-bit, little-endian counter.
31
+type Counter struct {
32
+	value       [counterLen]byte
33
+	invalid     bool
34
+	overflowLen int
35
+}
36
+
37
+// Value returns the current value of the counter as a byte slice.
38
+func (c *Counter) Value() ([]byte, error) {
39
+	if c.invalid {
40
+		return nil, errInvalidCounter
41
+	}
42
+	return c.value[:], nil
43
+}
44
+
45
+// Inc increments the counter and checks for overflow.
46
+func (c *Counter) Inc() {
47
+	// If the counter is already invalid, there is no need to increase it.
48
+	if c.invalid {
49
+		return
50
+	}
51
+	i := 0
52
+	for ; i < c.overflowLen; i++ {
53
+		c.value[i]++
54
+		if c.value[i] != 0 {
55
+			break
56
+		}
57
+	}
58
+	if i == c.overflowLen {
59
+		c.invalid = true
60
+	}
61
+}
0 62
new file mode 100644
... ...
@@ -0,0 +1,271 @@
0
+/*
1
+ *
2
+ * Copyright 2018 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+// Package conn contains an implementation of a secure channel created by gRPC
19
+// handshakers.
20
+package conn
21
+
22
+import (
23
+	"encoding/binary"
24
+	"fmt"
25
+	"math"
26
+	"net"
27
+
28
+	core "google.golang.org/grpc/credentials/alts/internal"
29
+)
30
+
31
+// ALTSRecordCrypto is the interface for gRPC ALTS record protocol.
32
+type ALTSRecordCrypto interface {
33
+	// Encrypt encrypts the plaintext and computes the tag (if any) of dst
34
+	// and plaintext, dst and plaintext do not overlap.
35
+	Encrypt(dst, plaintext []byte) ([]byte, error)
36
+	// EncryptionOverhead returns the tag size (if any) in bytes.
37
+	EncryptionOverhead() int
38
+	// Decrypt decrypts ciphertext and verify the tag (if any). dst and
39
+	// ciphertext may alias exactly or not at all. To reuse ciphertext's
40
+	// storage for the decrypted output, use ciphertext[:0] as dst.
41
+	Decrypt(dst, ciphertext []byte) ([]byte, error)
42
+}
43
+
44
+// ALTSRecordFunc is a function type for factory functions that create
45
+// ALTSRecordCrypto instances.
46
+type ALTSRecordFunc func(s core.Side, keyData []byte) (ALTSRecordCrypto, error)
47
+
48
+const (
49
+	// MsgLenFieldSize is the byte size of the frame length field of a
50
+	// framed message.
51
+	MsgLenFieldSize = 4
52
+	// The byte size of the message type field of a framed message.
53
+	msgTypeFieldSize = 4
54
+	// The bytes size limit for a ALTS record message.
55
+	altsRecordLengthLimit = 1024 * 1024 // 1 MiB
56
+	// The default bytes size of a ALTS record message.
57
+	altsRecordDefaultLength = 4 * 1024 // 4KiB
58
+	// Message type value included in ALTS record framing.
59
+	altsRecordMsgType = uint32(0x06)
60
+	// The initial write buffer size.
61
+	altsWriteBufferInitialSize = 32 * 1024 // 32KiB
62
+	// The maximum write buffer size. This *must* be multiple of
63
+	// altsRecordDefaultLength.
64
+	altsWriteBufferMaxSize = 512 * 1024 // 512KiB
65
+)
66
+
67
+var (
68
+	protocols = make(map[string]ALTSRecordFunc)
69
+)
70
+
71
+// RegisterProtocol register a ALTS record encryption protocol.
72
+func RegisterProtocol(protocol string, f ALTSRecordFunc) error {
73
+	if _, ok := protocols[protocol]; ok {
74
+		return fmt.Errorf("protocol %v is already registered", protocol)
75
+	}
76
+	protocols[protocol] = f
77
+	return nil
78
+}
79
+
80
+// conn represents a secured connection. It implements the net.Conn interface.
81
+type conn struct {
82
+	net.Conn
83
+	crypto ALTSRecordCrypto
84
+	// buf holds data that has been read from the connection and decrypted,
85
+	// but has not yet been returned by Read.
86
+	buf                []byte
87
+	payloadLengthLimit int
88
+	// protected holds data read from the network but have not yet been
89
+	// decrypted. This data might not compose a complete frame.
90
+	protected []byte
91
+	// writeBuf is a buffer used to contain encrypted frames before being
92
+	// written to the network.
93
+	writeBuf []byte
94
+	// nextFrame stores the next frame (in protected buffer) info.
95
+	nextFrame []byte
96
+	// overhead is the calculated overhead of each frame.
97
+	overhead int
98
+}
99
+
100
+// NewConn creates a new secure channel instance given the other party role and
101
+// handshaking result.
102
+func NewConn(c net.Conn, side core.Side, recordProtocol string, key []byte, protected []byte) (net.Conn, error) {
103
+	newCrypto := protocols[recordProtocol]
104
+	if newCrypto == nil {
105
+		return nil, fmt.Errorf("negotiated unknown next_protocol %q", recordProtocol)
106
+	}
107
+	crypto, err := newCrypto(side, key)
108
+	if err != nil {
109
+		return nil, fmt.Errorf("protocol %q: %v", recordProtocol, err)
110
+	}
111
+	overhead := MsgLenFieldSize + msgTypeFieldSize + crypto.EncryptionOverhead()
112
+	payloadLengthLimit := altsRecordDefaultLength - overhead
113
+	if protected == nil {
114
+		// We pre-allocate protected to be of size
115
+		// 2*altsRecordDefaultLength-1 during initialization. We only
116
+		// read from the network into protected when protected does not
117
+		// contain a complete frame, which is at most
118
+		// altsRecordDefaultLength-1 (bytes). And we read at most
119
+		// altsRecordDefaultLength (bytes) data into protected at one
120
+		// time. Therefore, 2*altsRecordDefaultLength-1 is large enough
121
+		// to buffer data read from the network.
122
+		protected = make([]byte, 0, 2*altsRecordDefaultLength-1)
123
+	}
124
+
125
+	altsConn := &conn{
126
+		Conn:               c,
127
+		crypto:             crypto,
128
+		payloadLengthLimit: payloadLengthLimit,
129
+		protected:          protected,
130
+		writeBuf:           make([]byte, altsWriteBufferInitialSize),
131
+		nextFrame:          protected,
132
+		overhead:           overhead,
133
+	}
134
+	return altsConn, nil
135
+}
136
+
137
+// Read reads and decrypts a frame from the underlying connection, and copies the
138
+// decrypted payload into b. If the size of the payload is greater than len(b),
139
+// Read retains the remaining bytes in an internal buffer, and subsequent calls
140
+// to Read will read from this buffer until it is exhausted.
141
+func (p *conn) Read(b []byte) (n int, err error) {
142
+	if len(p.buf) == 0 {
143
+		var framedMsg []byte
144
+		framedMsg, p.nextFrame, err = ParseFramedMsg(p.nextFrame, altsRecordLengthLimit)
145
+		if err != nil {
146
+			return n, err
147
+		}
148
+		// Check whether the next frame to be decrypted has been
149
+		// completely received yet.
150
+		if len(framedMsg) == 0 {
151
+			copy(p.protected, p.nextFrame)
152
+			p.protected = p.protected[:len(p.nextFrame)]
153
+			// Always copy next incomplete frame to the beginning of
154
+			// the protected buffer and reset nextFrame to it.
155
+			p.nextFrame = p.protected
156
+		}
157
+		// Check whether a complete frame has been received yet.
158
+		for len(framedMsg) == 0 {
159
+			if len(p.protected) == cap(p.protected) {
160
+				tmp := make([]byte, len(p.protected), cap(p.protected)+altsRecordDefaultLength)
161
+				copy(tmp, p.protected)
162
+				p.protected = tmp
163
+			}
164
+			n, err = p.Conn.Read(p.protected[len(p.protected):min(cap(p.protected), len(p.protected)+altsRecordDefaultLength)])
165
+			if err != nil {
166
+				return 0, err
167
+			}
168
+			p.protected = p.protected[:len(p.protected)+n]
169
+			framedMsg, p.nextFrame, err = ParseFramedMsg(p.protected, altsRecordLengthLimit)
170
+			if err != nil {
171
+				return 0, err
172
+			}
173
+		}
174
+		// Now we have a complete frame, decrypted it.
175
+		msg := framedMsg[MsgLenFieldSize:]
176
+		msgType := binary.LittleEndian.Uint32(msg[:msgTypeFieldSize])
177
+		if msgType&0xff != altsRecordMsgType {
178
+			return 0, fmt.Errorf("received frame with incorrect message type %v, expected lower byte %v",
179
+				msgType, altsRecordMsgType)
180
+		}
181
+		ciphertext := msg[msgTypeFieldSize:]
182
+
183
+		// Decrypt requires that if the dst and ciphertext alias, they
184
+		// must alias exactly. Code here used to use msg[:0], but msg
185
+		// starts MsgLenFieldSize+msgTypeFieldSize bytes earlier than
186
+		// ciphertext, so they alias inexactly. Using ciphertext[:0]
187
+		// arranges the appropriate aliasing without needing to copy
188
+		// ciphertext or use a separate destination buffer. For more info
189
+		// check: https://golang.org/pkg/crypto/cipher/#AEAD.
190
+		p.buf, err = p.crypto.Decrypt(ciphertext[:0], ciphertext)
191
+		if err != nil {
192
+			return 0, err
193
+		}
194
+	}
195
+
196
+	n = copy(b, p.buf)
197
+	p.buf = p.buf[n:]
198
+	return n, nil
199
+}
200
+
201
+// Write encrypts, frames, and writes bytes from b to the underlying connection.
202
+func (p *conn) Write(b []byte) (n int, err error) {
203
+	n = len(b)
204
+	// Calculate the output buffer size with framing and encryption overhead.
205
+	numOfFrames := int(math.Ceil(float64(len(b)) / float64(p.payloadLengthLimit)))
206
+	size := len(b) + numOfFrames*p.overhead
207
+	// If writeBuf is too small, increase its size up to the maximum size.
208
+	partialBSize := len(b)
209
+	if size > altsWriteBufferMaxSize {
210
+		size = altsWriteBufferMaxSize
211
+		const numOfFramesInMaxWriteBuf = altsWriteBufferMaxSize / altsRecordDefaultLength
212
+		partialBSize = numOfFramesInMaxWriteBuf * p.payloadLengthLimit
213
+	}
214
+	if len(p.writeBuf) < size {
215
+		p.writeBuf = make([]byte, size)
216
+	}
217
+
218
+	for partialBStart := 0; partialBStart < len(b); partialBStart += partialBSize {
219
+		partialBEnd := partialBStart + partialBSize
220
+		if partialBEnd > len(b) {
221
+			partialBEnd = len(b)
222
+		}
223
+		partialB := b[partialBStart:partialBEnd]
224
+		writeBufIndex := 0
225
+		for len(partialB) > 0 {
226
+			payloadLen := len(partialB)
227
+			if payloadLen > p.payloadLengthLimit {
228
+				payloadLen = p.payloadLengthLimit
229
+			}
230
+			buf := partialB[:payloadLen]
231
+			partialB = partialB[payloadLen:]
232
+
233
+			// Write buffer contains: length, type, payload, and tag
234
+			// if any.
235
+
236
+			// 1. Fill in type field.
237
+			msg := p.writeBuf[writeBufIndex+MsgLenFieldSize:]
238
+			binary.LittleEndian.PutUint32(msg, altsRecordMsgType)
239
+
240
+			// 2. Encrypt the payload and create a tag if any.
241
+			msg, err = p.crypto.Encrypt(msg[:msgTypeFieldSize], buf)
242
+			if err != nil {
243
+				return n, err
244
+			}
245
+
246
+			// 3. Fill in the size field.
247
+			binary.LittleEndian.PutUint32(p.writeBuf[writeBufIndex:], uint32(len(msg)))
248
+
249
+			// 4. Increase writeBufIndex.
250
+			writeBufIndex += len(buf) + p.overhead
251
+		}
252
+		nn, err := p.Conn.Write(p.writeBuf[:writeBufIndex])
253
+		if err != nil {
254
+			// We need to calculate the actual data size that was
255
+			// written. This means we need to remove header,
256
+			// encryption overheads, and any partially-written
257
+			// frame data.
258
+			numOfWrittenFrames := int(math.Floor(float64(nn) / float64(altsRecordDefaultLength)))
259
+			return partialBStart + numOfWrittenFrames*p.payloadLengthLimit, err
260
+		}
261
+	}
262
+	return n, nil
263
+}
264
+
265
+func min(a, b int) int {
266
+	if a < b {
267
+		return a
268
+	}
269
+	return b
270
+}
0 271
new file mode 100644
... ...
@@ -0,0 +1,63 @@
0
+/*
1
+ *
2
+ * Copyright 2018 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+package conn
19
+
20
+import core "google.golang.org/grpc/credentials/alts/internal"
21
+
22
+// NewOutCounter returns an outgoing counter initialized to the starting sequence
23
+// number for the client/server side of a connection.
24
+func NewOutCounter(s core.Side, overflowLen int) (c Counter) {
25
+	c.overflowLen = overflowLen
26
+	if s == core.ServerSide {
27
+		// Server counters in ALTS record have the little-endian high bit
28
+		// set.
29
+		c.value[counterLen-1] = 0x80
30
+	}
31
+	return
32
+}
33
+
34
+// NewInCounter returns an incoming counter initialized to the starting sequence
35
+// number for the client/server side of a connection. This is used in ALTS record
36
+// to check that incoming counters are as expected, since ALTS record guarantees
37
+// that messages are unwrapped in the same order that the peer wrapped them.
38
+func NewInCounter(s core.Side, overflowLen int) (c Counter) {
39
+	c.overflowLen = overflowLen
40
+	if s == core.ClientSide {
41
+		// Server counters in ALTS record have the little-endian high bit
42
+		// set.
43
+		c.value[counterLen-1] = 0x80
44
+	}
45
+	return
46
+}
47
+
48
+// CounterFromValue creates a new counter given an initial value.
49
+func CounterFromValue(value []byte, overflowLen int) (c Counter) {
50
+	c.overflowLen = overflowLen
51
+	copy(c.value[:], value)
52
+	return
53
+}
54
+
55
+// CounterSide returns the connection side (client/server) a sequence counter is
56
+// associated with.
57
+func CounterSide(c []byte) core.Side {
58
+	if c[counterLen-1]&0x80 == 0x80 {
59
+		return core.ServerSide
60
+	}
61
+	return core.ClientSide
62
+}
0 63
new file mode 100644
... ...
@@ -0,0 +1,375 @@
0
+/*
1
+ *
2
+ * Copyright 2018 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+// Package handshaker provides ALTS handshaking functionality for GCP.
19
+package handshaker
20
+
21
+import (
22
+	"context"
23
+	"errors"
24
+	"fmt"
25
+	"io"
26
+	"net"
27
+	"sync"
28
+
29
+	grpc "google.golang.org/grpc"
30
+	"google.golang.org/grpc/codes"
31
+	"google.golang.org/grpc/credentials"
32
+	core "google.golang.org/grpc/credentials/alts/internal"
33
+	"google.golang.org/grpc/credentials/alts/internal/authinfo"
34
+	"google.golang.org/grpc/credentials/alts/internal/conn"
35
+	altsgrpc "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
36
+	altspb "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
37
+)
38
+
39
+const (
40
+	// The maximum byte size of receive frames.
41
+	frameLimit              = 64 * 1024 // 64 KB
42
+	rekeyRecordProtocolName = "ALTSRP_GCM_AES128_REKEY"
43
+	// maxPendingHandshakes represents the maximum number of concurrent
44
+	// handshakes.
45
+	maxPendingHandshakes = 100
46
+)
47
+
48
+var (
49
+	hsProtocol      = altspb.HandshakeProtocol_ALTS
50
+	appProtocols    = []string{"grpc"}
51
+	recordProtocols = []string{rekeyRecordProtocolName}
52
+	keyLength       = map[string]int{
53
+		rekeyRecordProtocolName: 44,
54
+	}
55
+	altsRecordFuncs = map[string]conn.ALTSRecordFunc{
56
+		// ALTS handshaker protocols.
57
+		rekeyRecordProtocolName: func(s core.Side, keyData []byte) (conn.ALTSRecordCrypto, error) {
58
+			return conn.NewAES128GCMRekey(s, keyData)
59
+		},
60
+	}
61
+	// control number of concurrent created (but not closed) handshakers.
62
+	mu                   sync.Mutex
63
+	concurrentHandshakes = int64(0)
64
+	// errDropped occurs when maxPendingHandshakes is reached.
65
+	errDropped = errors.New("maximum number of concurrent ALTS handshakes is reached")
66
+	// errOutOfBound occurs when the handshake service returns a consumed
67
+	// bytes value larger than the buffer that was passed to it originally.
68
+	errOutOfBound = errors.New("handshaker service consumed bytes value is out-of-bound")
69
+)
70
+
71
+func init() {
72
+	for protocol, f := range altsRecordFuncs {
73
+		if err := conn.RegisterProtocol(protocol, f); err != nil {
74
+			panic(err)
75
+		}
76
+	}
77
+}
78
+
79
+func acquire() bool {
80
+	mu.Lock()
81
+	// If we need n to be configurable, we can pass it as an argument.
82
+	n := int64(1)
83
+	success := maxPendingHandshakes-concurrentHandshakes >= n
84
+	if success {
85
+		concurrentHandshakes += n
86
+	}
87
+	mu.Unlock()
88
+	return success
89
+}
90
+
91
+func release() {
92
+	mu.Lock()
93
+	// If we need n to be configurable, we can pass it as an argument.
94
+	n := int64(1)
95
+	concurrentHandshakes -= n
96
+	if concurrentHandshakes < 0 {
97
+		mu.Unlock()
98
+		panic("bad release")
99
+	}
100
+	mu.Unlock()
101
+}
102
+
103
+// ClientHandshakerOptions contains the client handshaker options that can
104
+// provided by the caller.
105
+type ClientHandshakerOptions struct {
106
+	// ClientIdentity is the handshaker client local identity.
107
+	ClientIdentity *altspb.Identity
108
+	// TargetName is the server service account name for secure name
109
+	// checking.
110
+	TargetName string
111
+	// TargetServiceAccounts contains a list of expected target service
112
+	// accounts. One of these accounts should match one of the accounts in
113
+	// the handshaker results. Otherwise, the handshake fails.
114
+	TargetServiceAccounts []string
115
+	// RPCVersions specifies the gRPC versions accepted by the client.
116
+	RPCVersions *altspb.RpcProtocolVersions
117
+}
118
+
119
+// ServerHandshakerOptions contains the server handshaker options that can
120
+// provided by the caller.
121
+type ServerHandshakerOptions struct {
122
+	// RPCVersions specifies the gRPC versions accepted by the server.
123
+	RPCVersions *altspb.RpcProtocolVersions
124
+}
125
+
126
+// DefaultClientHandshakerOptions returns the default client handshaker options.
127
+func DefaultClientHandshakerOptions() *ClientHandshakerOptions {
128
+	return &ClientHandshakerOptions{}
129
+}
130
+
131
+// DefaultServerHandshakerOptions returns the default client handshaker options.
132
+func DefaultServerHandshakerOptions() *ServerHandshakerOptions {
133
+	return &ServerHandshakerOptions{}
134
+}
135
+
136
+// TODO: add support for future local and remote endpoint in both client options
137
+//       and server options (server options struct does not exist now. When
138
+//       caller can provide endpoints, it should be created.
139
+
140
+// altsHandshaker is used to complete a ALTS handshaking between client and
141
+// server. This handshaker talks to the ALTS handshaker service in the metadata
142
+// server.
143
+type altsHandshaker struct {
144
+	// RPC stream used to access the ALTS Handshaker service.
145
+	stream altsgrpc.HandshakerService_DoHandshakeClient
146
+	// the connection to the peer.
147
+	conn net.Conn
148
+	// client handshake options.
149
+	clientOpts *ClientHandshakerOptions
150
+	// server handshake options.
151
+	serverOpts *ServerHandshakerOptions
152
+	// defines the side doing the handshake, client or server.
153
+	side core.Side
154
+}
155
+
156
+// NewClientHandshaker creates a ALTS handshaker for GCP which contains an RPC
157
+// stub created using the passed conn and used to talk to the ALTS Handshaker
158
+// service in the metadata server.
159
+func NewClientHandshaker(ctx context.Context, conn *grpc.ClientConn, c net.Conn, opts *ClientHandshakerOptions) (core.Handshaker, error) {
160
+	stream, err := altsgrpc.NewHandshakerServiceClient(conn).DoHandshake(ctx, grpc.WaitForReady(true))
161
+	if err != nil {
162
+		return nil, err
163
+	}
164
+	return &altsHandshaker{
165
+		stream:     stream,
166
+		conn:       c,
167
+		clientOpts: opts,
168
+		side:       core.ClientSide,
169
+	}, nil
170
+}
171
+
172
+// NewServerHandshaker creates a ALTS handshaker for GCP which contains an RPC
173
+// stub created using the passed conn and used to talk to the ALTS Handshaker
174
+// service in the metadata server.
175
+func NewServerHandshaker(ctx context.Context, conn *grpc.ClientConn, c net.Conn, opts *ServerHandshakerOptions) (core.Handshaker, error) {
176
+	stream, err := altsgrpc.NewHandshakerServiceClient(conn).DoHandshake(ctx, grpc.WaitForReady(true))
177
+	if err != nil {
178
+		return nil, err
179
+	}
180
+	return &altsHandshaker{
181
+		stream:     stream,
182
+		conn:       c,
183
+		serverOpts: opts,
184
+		side:       core.ServerSide,
185
+	}, nil
186
+}
187
+
188
+// ClientHandshake starts and completes a client ALTS handshaking for GCP. Once
189
+// done, ClientHandshake returns a secure connection.
190
+func (h *altsHandshaker) ClientHandshake(ctx context.Context) (net.Conn, credentials.AuthInfo, error) {
191
+	if !acquire() {
192
+		return nil, nil, errDropped
193
+	}
194
+	defer release()
195
+
196
+	if h.side != core.ClientSide {
197
+		return nil, nil, errors.New("only handshakers created using NewClientHandshaker can perform a client handshaker")
198
+	}
199
+
200
+	// Create target identities from service account list.
201
+	targetIdentities := make([]*altspb.Identity, 0, len(h.clientOpts.TargetServiceAccounts))
202
+	for _, account := range h.clientOpts.TargetServiceAccounts {
203
+		targetIdentities = append(targetIdentities, &altspb.Identity{
204
+			IdentityOneof: &altspb.Identity_ServiceAccount{
205
+				ServiceAccount: account,
206
+			},
207
+		})
208
+	}
209
+	req := &altspb.HandshakerReq{
210
+		ReqOneof: &altspb.HandshakerReq_ClientStart{
211
+			ClientStart: &altspb.StartClientHandshakeReq{
212
+				HandshakeSecurityProtocol: hsProtocol,
213
+				ApplicationProtocols:      appProtocols,
214
+				RecordProtocols:           recordProtocols,
215
+				TargetIdentities:          targetIdentities,
216
+				LocalIdentity:             h.clientOpts.ClientIdentity,
217
+				TargetName:                h.clientOpts.TargetName,
218
+				RpcVersions:               h.clientOpts.RPCVersions,
219
+			},
220
+		},
221
+	}
222
+
223
+	conn, result, err := h.doHandshake(req)
224
+	if err != nil {
225
+		return nil, nil, err
226
+	}
227
+	authInfo := authinfo.New(result)
228
+	return conn, authInfo, nil
229
+}
230
+
231
+// ServerHandshake starts and completes a server ALTS handshaking for GCP. Once
232
+// done, ServerHandshake returns a secure connection.
233
+func (h *altsHandshaker) ServerHandshake(ctx context.Context) (net.Conn, credentials.AuthInfo, error) {
234
+	if !acquire() {
235
+		return nil, nil, errDropped
236
+	}
237
+	defer release()
238
+
239
+	if h.side != core.ServerSide {
240
+		return nil, nil, errors.New("only handshakers created using NewServerHandshaker can perform a server handshaker")
241
+	}
242
+
243
+	p := make([]byte, frameLimit)
244
+	n, err := h.conn.Read(p)
245
+	if err != nil {
246
+		return nil, nil, err
247
+	}
248
+
249
+	// Prepare server parameters.
250
+	// TODO: currently only ALTS parameters are provided. Might need to use
251
+	//       more options in the future.
252
+	params := make(map[int32]*altspb.ServerHandshakeParameters)
253
+	params[int32(altspb.HandshakeProtocol_ALTS)] = &altspb.ServerHandshakeParameters{
254
+		RecordProtocols: recordProtocols,
255
+	}
256
+	req := &altspb.HandshakerReq{
257
+		ReqOneof: &altspb.HandshakerReq_ServerStart{
258
+			ServerStart: &altspb.StartServerHandshakeReq{
259
+				ApplicationProtocols: appProtocols,
260
+				HandshakeParameters:  params,
261
+				InBytes:              p[:n],
262
+				RpcVersions:          h.serverOpts.RPCVersions,
263
+			},
264
+		},
265
+	}
266
+
267
+	conn, result, err := h.doHandshake(req)
268
+	if err != nil {
269
+		return nil, nil, err
270
+	}
271
+	authInfo := authinfo.New(result)
272
+	return conn, authInfo, nil
273
+}
274
+
275
+func (h *altsHandshaker) doHandshake(req *altspb.HandshakerReq) (net.Conn, *altspb.HandshakerResult, error) {
276
+	resp, err := h.accessHandshakerService(req)
277
+	if err != nil {
278
+		return nil, nil, err
279
+	}
280
+	// Check of the returned status is an error.
281
+	if resp.GetStatus() != nil {
282
+		if got, want := resp.GetStatus().Code, uint32(codes.OK); got != want {
283
+			return nil, nil, fmt.Errorf("%v", resp.GetStatus().Details)
284
+		}
285
+	}
286
+
287
+	var extra []byte
288
+	if req.GetServerStart() != nil {
289
+		if resp.GetBytesConsumed() > uint32(len(req.GetServerStart().GetInBytes())) {
290
+			return nil, nil, errOutOfBound
291
+		}
292
+		extra = req.GetServerStart().GetInBytes()[resp.GetBytesConsumed():]
293
+	}
294
+	result, extra, err := h.processUntilDone(resp, extra)
295
+	if err != nil {
296
+		return nil, nil, err
297
+	}
298
+	// The handshaker returns a 128 bytes key. It should be truncated based
299
+	// on the returned record protocol.
300
+	keyLen, ok := keyLength[result.RecordProtocol]
301
+	if !ok {
302
+		return nil, nil, fmt.Errorf("unknown resulted record protocol %v", result.RecordProtocol)
303
+	}
304
+	sc, err := conn.NewConn(h.conn, h.side, result.GetRecordProtocol(), result.KeyData[:keyLen], extra)
305
+	if err != nil {
306
+		return nil, nil, err
307
+	}
308
+	return sc, result, nil
309
+}
310
+
311
+func (h *altsHandshaker) accessHandshakerService(req *altspb.HandshakerReq) (*altspb.HandshakerResp, error) {
312
+	if err := h.stream.Send(req); err != nil {
313
+		return nil, err
314
+	}
315
+	resp, err := h.stream.Recv()
316
+	if err != nil {
317
+		return nil, err
318
+	}
319
+	return resp, nil
320
+}
321
+
322
+// processUntilDone processes the handshake until the handshaker service returns
323
+// the results. Handshaker service takes care of frame parsing, so we read
324
+// whatever received from the network and send it to the handshaker service.
325
+func (h *altsHandshaker) processUntilDone(resp *altspb.HandshakerResp, extra []byte) (*altspb.HandshakerResult, []byte, error) {
326
+	for {
327
+		if len(resp.OutFrames) > 0 {
328
+			if _, err := h.conn.Write(resp.OutFrames); err != nil {
329
+				return nil, nil, err
330
+			}
331
+		}
332
+		if resp.Result != nil {
333
+			return resp.Result, extra, nil
334
+		}
335
+		buf := make([]byte, frameLimit)
336
+		n, err := h.conn.Read(buf)
337
+		if err != nil && err != io.EOF {
338
+			return nil, nil, err
339
+		}
340
+		// If there is nothing to send to the handshaker service, and
341
+		// nothing is received from the peer, then we are stuck.
342
+		// This covers the case when the peer is not responding. Note
343
+		// that handshaker service connection issues are caught in
344
+		// accessHandshakerService before we even get here.
345
+		if len(resp.OutFrames) == 0 && n == 0 {
346
+			return nil, nil, core.PeerNotRespondingError
347
+		}
348
+		// Append extra bytes from the previous interaction with the
349
+		// handshaker service with the current buffer read from conn.
350
+		p := append(extra, buf[:n]...)
351
+		// From here on, p and extra point to the same slice.
352
+		resp, err = h.accessHandshakerService(&altspb.HandshakerReq{
353
+			ReqOneof: &altspb.HandshakerReq_Next{
354
+				Next: &altspb.NextHandshakeMessageReq{
355
+					InBytes: p,
356
+				},
357
+			},
358
+		})
359
+		if err != nil {
360
+			return nil, nil, err
361
+		}
362
+		// Set extra based on handshaker service response.
363
+		if resp.GetBytesConsumed() > uint32(len(p)) {
364
+			return nil, nil, errOutOfBound
365
+		}
366
+		extra = p[resp.GetBytesConsumed():]
367
+	}
368
+}
369
+
370
+// Close terminates the Handshaker. It should be called when the caller obtains
371
+// the secure connection.
372
+func (h *altsHandshaker) Close() {
373
+	h.stream.CloseSend()
374
+}
0 375
new file mode 100644
... ...
@@ -0,0 +1,54 @@
0
+/*
1
+ *
2
+ * Copyright 2018 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+// Package service manages connections between the VM application and the ALTS
19
+// handshaker service.
20
+package service
21
+
22
+import (
23
+	"sync"
24
+
25
+	grpc "google.golang.org/grpc"
26
+)
27
+
28
+var (
29
+	// hsConn represents a connection to hypervisor handshaker service.
30
+	hsConn *grpc.ClientConn
31
+	mu     sync.Mutex
32
+	// hsDialer will be reassigned in tests.
33
+	hsDialer = grpc.Dial
34
+)
35
+
36
+// Dial dials the handshake service in the hypervisor. If a connection has
37
+// already been established, this function returns it. Otherwise, a new
38
+// connection is created.
39
+func Dial(hsAddress string) (*grpc.ClientConn, error) {
40
+	mu.Lock()
41
+	defer mu.Unlock()
42
+
43
+	if hsConn == nil {
44
+		// Create a new connection to the handshaker service. Note that
45
+		// this connection stays open until the application is closed.
46
+		var err error
47
+		hsConn, err = hsDialer(hsAddress, grpc.WithInsecure())
48
+		if err != nil {
49
+			return nil, err
50
+		}
51
+	}
52
+	return hsConn, nil
53
+}
0 54
new file mode 100644
... ...
@@ -0,0 +1,152 @@
0
+// Code generated by protoc-gen-go. DO NOT EDIT.
1
+// source: grpc/gcp/altscontext.proto
2
+
3
+package grpc_gcp
4
+
5
+import (
6
+	fmt "fmt"
7
+	proto "github.com/golang/protobuf/proto"
8
+	math "math"
9
+)
10
+
11
+// Reference imports to suppress errors if they are not otherwise used.
12
+var _ = proto.Marshal
13
+var _ = fmt.Errorf
14
+var _ = math.Inf
15
+
16
+// This is a compile-time assertion to ensure that this generated file
17
+// is compatible with the proto package it is being compiled against.
18
+// A compilation error at this line likely means your copy of the
19
+// proto package needs to be updated.
20
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
21
+
22
+type AltsContext struct {
23
+	// The application protocol negotiated for this connection.
24
+	ApplicationProtocol string `protobuf:"bytes,1,opt,name=application_protocol,json=applicationProtocol,proto3" json:"application_protocol,omitempty"`
25
+	// The record protocol negotiated for this connection.
26
+	RecordProtocol string `protobuf:"bytes,2,opt,name=record_protocol,json=recordProtocol,proto3" json:"record_protocol,omitempty"`
27
+	// The security level of the created secure channel.
28
+	SecurityLevel SecurityLevel `protobuf:"varint,3,opt,name=security_level,json=securityLevel,proto3,enum=grpc.gcp.SecurityLevel" json:"security_level,omitempty"`
29
+	// The peer service account.
30
+	PeerServiceAccount string `protobuf:"bytes,4,opt,name=peer_service_account,json=peerServiceAccount,proto3" json:"peer_service_account,omitempty"`
31
+	// The local service account.
32
+	LocalServiceAccount string `protobuf:"bytes,5,opt,name=local_service_account,json=localServiceAccount,proto3" json:"local_service_account,omitempty"`
33
+	// The RPC protocol versions supported by the peer.
34
+	PeerRpcVersions *RpcProtocolVersions `protobuf:"bytes,6,opt,name=peer_rpc_versions,json=peerRpcVersions,proto3" json:"peer_rpc_versions,omitempty"`
35
+	// Additional attributes of the peer.
36
+	PeerAttributes       map[string]string `protobuf:"bytes,7,rep,name=peer_attributes,json=peerAttributes,proto3" json:"peer_attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
37
+	XXX_NoUnkeyedLiteral struct{}          `json:"-"`
38
+	XXX_unrecognized     []byte            `json:"-"`
39
+	XXX_sizecache        int32             `json:"-"`
40
+}
41
+
42
+func (m *AltsContext) Reset()         { *m = AltsContext{} }
43
+func (m *AltsContext) String() string { return proto.CompactTextString(m) }
44
+func (*AltsContext) ProtoMessage()    {}
45
+func (*AltsContext) Descriptor() ([]byte, []int) {
46
+	return fileDescriptor_6647a41e53a575a3, []int{0}
47
+}
48
+
49
+func (m *AltsContext) XXX_Unmarshal(b []byte) error {
50
+	return xxx_messageInfo_AltsContext.Unmarshal(m, b)
51
+}
52
+func (m *AltsContext) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
53
+	return xxx_messageInfo_AltsContext.Marshal(b, m, deterministic)
54
+}
55
+func (m *AltsContext) XXX_Merge(src proto.Message) {
56
+	xxx_messageInfo_AltsContext.Merge(m, src)
57
+}
58
+func (m *AltsContext) XXX_Size() int {
59
+	return xxx_messageInfo_AltsContext.Size(m)
60
+}
61
+func (m *AltsContext) XXX_DiscardUnknown() {
62
+	xxx_messageInfo_AltsContext.DiscardUnknown(m)
63
+}
64
+
65
+var xxx_messageInfo_AltsContext proto.InternalMessageInfo
66
+
67
+func (m *AltsContext) GetApplicationProtocol() string {
68
+	if m != nil {
69
+		return m.ApplicationProtocol
70
+	}
71
+	return ""
72
+}
73
+
74
+func (m *AltsContext) GetRecordProtocol() string {
75
+	if m != nil {
76
+		return m.RecordProtocol
77
+	}
78
+	return ""
79
+}
80
+
81
+func (m *AltsContext) GetSecurityLevel() SecurityLevel {
82
+	if m != nil {
83
+		return m.SecurityLevel
84
+	}
85
+	return SecurityLevel_SECURITY_NONE
86
+}
87
+
88
+func (m *AltsContext) GetPeerServiceAccount() string {
89
+	if m != nil {
90
+		return m.PeerServiceAccount
91
+	}
92
+	return ""
93
+}
94
+
95
+func (m *AltsContext) GetLocalServiceAccount() string {
96
+	if m != nil {
97
+		return m.LocalServiceAccount
98
+	}
99
+	return ""
100
+}
101
+
102
+func (m *AltsContext) GetPeerRpcVersions() *RpcProtocolVersions {
103
+	if m != nil {
104
+		return m.PeerRpcVersions
105
+	}
106
+	return nil
107
+}
108
+
109
+func (m *AltsContext) GetPeerAttributes() map[string]string {
110
+	if m != nil {
111
+		return m.PeerAttributes
112
+	}
113
+	return nil
114
+}
115
+
116
+func init() {
117
+	proto.RegisterType((*AltsContext)(nil), "grpc.gcp.AltsContext")
118
+	proto.RegisterMapType((map[string]string)(nil), "grpc.gcp.AltsContext.PeerAttributesEntry")
119
+}
120
+
121
+func init() { proto.RegisterFile("grpc/gcp/altscontext.proto", fileDescriptor_6647a41e53a575a3) }
122
+
123
+var fileDescriptor_6647a41e53a575a3 = []byte{
124
+	// 411 bytes of a gzipped FileDescriptorProto
125
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0x4d, 0x6f, 0x13, 0x31,
126
+	0x10, 0x86, 0xb5, 0x0d, 0x2d, 0xe0, 0x88, 0xb4, 0xb8, 0xa9, 0x58, 0x45, 0x42, 0x8a, 0xb8, 0xb0,
127
+	0x5c, 0x76, 0x21, 0x5c, 0x10, 0x07, 0x50, 0x8a, 0x38, 0x20, 0x71, 0x88, 0xb6, 0x12, 0x07, 0x2e,
128
+	0x2b, 0x77, 0x3a, 0xb2, 0x2c, 0x5c, 0x8f, 0x35, 0x76, 0x22, 0xf2, 0xb3, 0xf9, 0x07, 0x68, 0xed,
129
+	0xcd, 0x07, 0x1f, 0xb7, 0x9d, 0x79, 0x9f, 0x19, 0xbf, 0xb3, 0x33, 0x62, 0xa6, 0xd9, 0x43, 0xa3,
130
+	0xc1, 0x37, 0xca, 0xc6, 0x00, 0xe4, 0x22, 0xfe, 0x8c, 0xb5, 0x67, 0x8a, 0x24, 0x1f, 0xf5, 0x5a,
131
+	0xad, 0xc1, 0xcf, 0xaa, 0x3d, 0x15, 0x59, 0xb9, 0xe0, 0x89, 0x63, 0x17, 0x10, 0xd6, 0x6c, 0xe2,
132
+	0xb6, 0x03, 0xba, 0xbf, 0x27, 0x97, 0x6b, 0x5e, 0xfc, 0x1a, 0x89, 0xf1, 0xd2, 0xc6, 0xf0, 0x29,
133
+	0x77, 0x92, 0x6f, 0xc4, 0x54, 0x79, 0x6f, 0x0d, 0xa8, 0x68, 0xc8, 0x75, 0x09, 0x02, 0xb2, 0x65,
134
+	0x31, 0x2f, 0xaa, 0xc7, 0xed, 0xe5, 0x91, 0xb6, 0x1a, 0x24, 0xf9, 0x52, 0x9c, 0x33, 0x02, 0xf1,
135
+	0xdd, 0x81, 0x3e, 0x49, 0xf4, 0x24, 0xa7, 0xf7, 0xe0, 0x07, 0x31, 0xd9, 0x9b, 0xb0, 0xb8, 0x41,
136
+	0x5b, 0x8e, 0xe6, 0x45, 0x35, 0x59, 0x3c, 0xab, 0x77, 0xc6, 0xeb, 0x9b, 0x41, 0xff, 0xda, 0xcb,
137
+	0xed, 0x93, 0x70, 0x1c, 0xca, 0xd7, 0x62, 0xea, 0x11, 0xb9, 0x0b, 0xc8, 0x1b, 0x03, 0xd8, 0x29,
138
+	0x00, 0x5a, 0xbb, 0x58, 0x3e, 0x48, 0xaf, 0xc9, 0x5e, 0xbb, 0xc9, 0xd2, 0x32, 0x2b, 0x72, 0x21,
139
+	0xae, 0x2c, 0x81, 0xb2, 0xff, 0x94, 0x9c, 0xe6, 0x71, 0x92, 0xf8, 0x57, 0xcd, 0x17, 0xf1, 0x34,
140
+	0xbd, 0xc2, 0x1e, 0xba, 0x0d, 0x72, 0x30, 0xe4, 0x42, 0x79, 0x36, 0x2f, 0xaa, 0xf1, 0xe2, 0xf9,
141
+	0xc1, 0x68, 0xeb, 0x61, 0x37, 0xd7, 0xb7, 0x01, 0x6a, 0xcf, 0xfb, 0xba, 0xd6, 0xc3, 0x2e, 0x21,
142
+	0x5b, 0x91, 0x52, 0x9d, 0x8a, 0x91, 0xcd, 0xed, 0x3a, 0x62, 0x28, 0x1f, 0xce, 0x47, 0xd5, 0x78,
143
+	0xf1, 0xea, 0xd0, 0xe8, 0xe8, 0xe7, 0xd7, 0x2b, 0x44, 0x5e, 0xee, 0xd9, 0xcf, 0x2e, 0xf2, 0xb6,
144
+	0x9d, 0xf8, 0x3f, 0x92, 0xb3, 0xa5, 0xb8, 0xfc, 0x0f, 0x26, 0x2f, 0xc4, 0xe8, 0x07, 0x6e, 0x87,
145
+	0x35, 0xf5, 0x9f, 0x72, 0x2a, 0x4e, 0x37, 0xca, 0xae, 0x71, 0x58, 0x46, 0x0e, 0xde, 0x9f, 0xbc,
146
+	0x2b, 0xae, 0xad, 0xb8, 0x32, 0x94, 0x1d, 0xf4, 0x47, 0x54, 0x1b, 0x17, 0x91, 0x9d, 0xb2, 0xd7,
147
+	0x17, 0x47, 0x66, 0xd2, 0x74, 0xab, 0xe2, 0xfb, 0x47, 0x4d, 0xa4, 0x2d, 0xd6, 0x9a, 0xac, 0x72,
148
+	0xba, 0x26, 0xd6, 0x4d, 0x3a, 0x2e, 0x60, 0xbc, 0x43, 0x17, 0x8d, 0xb2, 0x21, 0x9d, 0x62, 0xb3,
149
+	0xeb, 0xd2, 0xa4, 0x2b, 0x48, 0x50, 0xa7, 0xc1, 0xdf, 0x9e, 0xa5, 0xf8, 0xed, 0xef, 0x00, 0x00,
150
+	0x00, 0xff, 0xff, 0x9b, 0x8c, 0xe4, 0x6a, 0xba, 0x02, 0x00, 0x00,
151
+}
0 152
new file mode 100644
... ...
@@ -0,0 +1,1105 @@
0
+// Code generated by protoc-gen-go. DO NOT EDIT.
1
+// source: grpc/gcp/handshaker.proto
2
+
3
+package grpc_gcp
4
+
5
+import (
6
+	context "context"
7
+	fmt "fmt"
8
+	proto "github.com/golang/protobuf/proto"
9
+	grpc "google.golang.org/grpc"
10
+	codes "google.golang.org/grpc/codes"
11
+	status "google.golang.org/grpc/status"
12
+	math "math"
13
+)
14
+
15
+// Reference imports to suppress errors if they are not otherwise used.
16
+var _ = proto.Marshal
17
+var _ = fmt.Errorf
18
+var _ = math.Inf
19
+
20
+// This is a compile-time assertion to ensure that this generated file
21
+// is compatible with the proto package it is being compiled against.
22
+// A compilation error at this line likely means your copy of the
23
+// proto package needs to be updated.
24
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
25
+
26
+type HandshakeProtocol int32
27
+
28
+const (
29
+	// Default value.
30
+	HandshakeProtocol_HANDSHAKE_PROTOCOL_UNSPECIFIED HandshakeProtocol = 0
31
+	// TLS handshake protocol.
32
+	HandshakeProtocol_TLS HandshakeProtocol = 1
33
+	// Application Layer Transport Security handshake protocol.
34
+	HandshakeProtocol_ALTS HandshakeProtocol = 2
35
+)
36
+
37
+var HandshakeProtocol_name = map[int32]string{
38
+	0: "HANDSHAKE_PROTOCOL_UNSPECIFIED",
39
+	1: "TLS",
40
+	2: "ALTS",
41
+}
42
+
43
+var HandshakeProtocol_value = map[string]int32{
44
+	"HANDSHAKE_PROTOCOL_UNSPECIFIED": 0,
45
+	"TLS":                            1,
46
+	"ALTS":                           2,
47
+}
48
+
49
+func (x HandshakeProtocol) String() string {
50
+	return proto.EnumName(HandshakeProtocol_name, int32(x))
51
+}
52
+
53
+func (HandshakeProtocol) EnumDescriptor() ([]byte, []int) {
54
+	return fileDescriptor_54c074f40c7c7e99, []int{0}
55
+}
56
+
57
+type NetworkProtocol int32
58
+
59
+const (
60
+	NetworkProtocol_NETWORK_PROTOCOL_UNSPECIFIED NetworkProtocol = 0
61
+	NetworkProtocol_TCP                          NetworkProtocol = 1
62
+	NetworkProtocol_UDP                          NetworkProtocol = 2
63
+)
64
+
65
+var NetworkProtocol_name = map[int32]string{
66
+	0: "NETWORK_PROTOCOL_UNSPECIFIED",
67
+	1: "TCP",
68
+	2: "UDP",
69
+}
70
+
71
+var NetworkProtocol_value = map[string]int32{
72
+	"NETWORK_PROTOCOL_UNSPECIFIED": 0,
73
+	"TCP":                          1,
74
+	"UDP":                          2,
75
+}
76
+
77
+func (x NetworkProtocol) String() string {
78
+	return proto.EnumName(NetworkProtocol_name, int32(x))
79
+}
80
+
81
+func (NetworkProtocol) EnumDescriptor() ([]byte, []int) {
82
+	return fileDescriptor_54c074f40c7c7e99, []int{1}
83
+}
84
+
85
+type Endpoint struct {
86
+	// IP address. It should contain an IPv4 or IPv6 string literal, e.g.
87
+	// "192.168.0.1" or "2001:db8::1".
88
+	IpAddress string `protobuf:"bytes,1,opt,name=ip_address,json=ipAddress,proto3" json:"ip_address,omitempty"`
89
+	// Port number.
90
+	Port int32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"`
91
+	// Network protocol (e.g., TCP, UDP) associated with this endpoint.
92
+	Protocol             NetworkProtocol `protobuf:"varint,3,opt,name=protocol,proto3,enum=grpc.gcp.NetworkProtocol" json:"protocol,omitempty"`
93
+	XXX_NoUnkeyedLiteral struct{}        `json:"-"`
94
+	XXX_unrecognized     []byte          `json:"-"`
95
+	XXX_sizecache        int32           `json:"-"`
96
+}
97
+
98
+func (m *Endpoint) Reset()         { *m = Endpoint{} }
99
+func (m *Endpoint) String() string { return proto.CompactTextString(m) }
100
+func (*Endpoint) ProtoMessage()    {}
101
+func (*Endpoint) Descriptor() ([]byte, []int) {
102
+	return fileDescriptor_54c074f40c7c7e99, []int{0}
103
+}
104
+
105
+func (m *Endpoint) XXX_Unmarshal(b []byte) error {
106
+	return xxx_messageInfo_Endpoint.Unmarshal(m, b)
107
+}
108
+func (m *Endpoint) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
109
+	return xxx_messageInfo_Endpoint.Marshal(b, m, deterministic)
110
+}
111
+func (m *Endpoint) XXX_Merge(src proto.Message) {
112
+	xxx_messageInfo_Endpoint.Merge(m, src)
113
+}
114
+func (m *Endpoint) XXX_Size() int {
115
+	return xxx_messageInfo_Endpoint.Size(m)
116
+}
117
+func (m *Endpoint) XXX_DiscardUnknown() {
118
+	xxx_messageInfo_Endpoint.DiscardUnknown(m)
119
+}
120
+
121
+var xxx_messageInfo_Endpoint proto.InternalMessageInfo
122
+
123
+func (m *Endpoint) GetIpAddress() string {
124
+	if m != nil {
125
+		return m.IpAddress
126
+	}
127
+	return ""
128
+}
129
+
130
+func (m *Endpoint) GetPort() int32 {
131
+	if m != nil {
132
+		return m.Port
133
+	}
134
+	return 0
135
+}
136
+
137
+func (m *Endpoint) GetProtocol() NetworkProtocol {
138
+	if m != nil {
139
+		return m.Protocol
140
+	}
141
+	return NetworkProtocol_NETWORK_PROTOCOL_UNSPECIFIED
142
+}
143
+
144
+type Identity struct {
145
+	// Types that are valid to be assigned to IdentityOneof:
146
+	//	*Identity_ServiceAccount
147
+	//	*Identity_Hostname
148
+	IdentityOneof isIdentity_IdentityOneof `protobuf_oneof:"identity_oneof"`
149
+	// Additional attributes of the identity.
150
+	Attributes           map[string]string `protobuf:"bytes,3,rep,name=attributes,proto3" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
151
+	XXX_NoUnkeyedLiteral struct{}          `json:"-"`
152
+	XXX_unrecognized     []byte            `json:"-"`
153
+	XXX_sizecache        int32             `json:"-"`
154
+}
155
+
156
+func (m *Identity) Reset()         { *m = Identity{} }
157
+func (m *Identity) String() string { return proto.CompactTextString(m) }
158
+func (*Identity) ProtoMessage()    {}
159
+func (*Identity) Descriptor() ([]byte, []int) {
160
+	return fileDescriptor_54c074f40c7c7e99, []int{1}
161
+}
162
+
163
+func (m *Identity) XXX_Unmarshal(b []byte) error {
164
+	return xxx_messageInfo_Identity.Unmarshal(m, b)
165
+}
166
+func (m *Identity) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
167
+	return xxx_messageInfo_Identity.Marshal(b, m, deterministic)
168
+}
169
+func (m *Identity) XXX_Merge(src proto.Message) {
170
+	xxx_messageInfo_Identity.Merge(m, src)
171
+}
172
+func (m *Identity) XXX_Size() int {
173
+	return xxx_messageInfo_Identity.Size(m)
174
+}
175
+func (m *Identity) XXX_DiscardUnknown() {
176
+	xxx_messageInfo_Identity.DiscardUnknown(m)
177
+}
178
+
179
+var xxx_messageInfo_Identity proto.InternalMessageInfo
180
+
181
+type isIdentity_IdentityOneof interface {
182
+	isIdentity_IdentityOneof()
183
+}
184
+
185
+type Identity_ServiceAccount struct {
186
+	ServiceAccount string `protobuf:"bytes,1,opt,name=service_account,json=serviceAccount,proto3,oneof"`
187
+}
188
+
189
+type Identity_Hostname struct {
190
+	Hostname string `protobuf:"bytes,2,opt,name=hostname,proto3,oneof"`
191
+}
192
+
193
+func (*Identity_ServiceAccount) isIdentity_IdentityOneof() {}
194
+
195
+func (*Identity_Hostname) isIdentity_IdentityOneof() {}
196
+
197
+func (m *Identity) GetIdentityOneof() isIdentity_IdentityOneof {
198
+	if m != nil {
199
+		return m.IdentityOneof
200
+	}
201
+	return nil
202
+}
203
+
204
+func (m *Identity) GetServiceAccount() string {
205
+	if x, ok := m.GetIdentityOneof().(*Identity_ServiceAccount); ok {
206
+		return x.ServiceAccount
207
+	}
208
+	return ""
209
+}
210
+
211
+func (m *Identity) GetHostname() string {
212
+	if x, ok := m.GetIdentityOneof().(*Identity_Hostname); ok {
213
+		return x.Hostname
214
+	}
215
+	return ""
216
+}
217
+
218
+func (m *Identity) GetAttributes() map[string]string {
219
+	if m != nil {
220
+		return m.Attributes
221
+	}
222
+	return nil
223
+}
224
+
225
+// XXX_OneofWrappers is for the internal use of the proto package.
226
+func (*Identity) XXX_OneofWrappers() []interface{} {
227
+	return []interface{}{
228
+		(*Identity_ServiceAccount)(nil),
229
+		(*Identity_Hostname)(nil),
230
+	}
231
+}
232
+
233
+type StartClientHandshakeReq struct {
234
+	// Handshake security protocol requested by the client.
235
+	HandshakeSecurityProtocol HandshakeProtocol `protobuf:"varint,1,opt,name=handshake_security_protocol,json=handshakeSecurityProtocol,proto3,enum=grpc.gcp.HandshakeProtocol" json:"handshake_security_protocol,omitempty"`
236
+	// The application protocols supported by the client, e.g., "h2" (for http2),
237
+	// "grpc".
238
+	ApplicationProtocols []string `protobuf:"bytes,2,rep,name=application_protocols,json=applicationProtocols,proto3" json:"application_protocols,omitempty"`
239
+	// The record protocols supported by the client, e.g.,
240
+	// "ALTSRP_GCM_AES128".
241
+	RecordProtocols []string `protobuf:"bytes,3,rep,name=record_protocols,json=recordProtocols,proto3" json:"record_protocols,omitempty"`
242
+	// (Optional) Describes which server identities are acceptable by the client.
243
+	// If target identities are provided and none of them matches the peer
244
+	// identity of the server, handshake will fail.
245
+	TargetIdentities []*Identity `protobuf:"bytes,4,rep,name=target_identities,json=targetIdentities,proto3" json:"target_identities,omitempty"`
246
+	// (Optional) Application may specify a local identity. Otherwise, the
247
+	// handshaker chooses a default local identity.
248
+	LocalIdentity *Identity `protobuf:"bytes,5,opt,name=local_identity,json=localIdentity,proto3" json:"local_identity,omitempty"`
249
+	// (Optional) Local endpoint information of the connection to the server,
250
+	// such as local IP address, port number, and network protocol.
251
+	LocalEndpoint *Endpoint `protobuf:"bytes,6,opt,name=local_endpoint,json=localEndpoint,proto3" json:"local_endpoint,omitempty"`
252
+	// (Optional) Endpoint information of the remote server, such as IP address,
253
+	// port number, and network protocol.
254
+	RemoteEndpoint *Endpoint `protobuf:"bytes,7,opt,name=remote_endpoint,json=remoteEndpoint,proto3" json:"remote_endpoint,omitempty"`
255
+	// (Optional) If target name is provided, a secure naming check is performed
256
+	// to verify that the peer authenticated identity is indeed authorized to run
257
+	// the target name.
258
+	TargetName string `protobuf:"bytes,8,opt,name=target_name,json=targetName,proto3" json:"target_name,omitempty"`
259
+	// (Optional) RPC protocol versions supported by the client.
260
+	RpcVersions *RpcProtocolVersions `protobuf:"bytes,9,opt,name=rpc_versions,json=rpcVersions,proto3" json:"rpc_versions,omitempty"`
261
+	// (Optional) Maximum frame size supported by the client.
262
+	MaxFrameSize         uint32   `protobuf:"varint,10,opt,name=max_frame_size,json=maxFrameSize,proto3" json:"max_frame_size,omitempty"`
263
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
264
+	XXX_unrecognized     []byte   `json:"-"`
265
+	XXX_sizecache        int32    `json:"-"`
266
+}
267
+
268
+func (m *StartClientHandshakeReq) Reset()         { *m = StartClientHandshakeReq{} }
269
+func (m *StartClientHandshakeReq) String() string { return proto.CompactTextString(m) }
270
+func (*StartClientHandshakeReq) ProtoMessage()    {}
271
+func (*StartClientHandshakeReq) Descriptor() ([]byte, []int) {
272
+	return fileDescriptor_54c074f40c7c7e99, []int{2}
273
+}
274
+
275
+func (m *StartClientHandshakeReq) XXX_Unmarshal(b []byte) error {
276
+	return xxx_messageInfo_StartClientHandshakeReq.Unmarshal(m, b)
277
+}
278
+func (m *StartClientHandshakeReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
279
+	return xxx_messageInfo_StartClientHandshakeReq.Marshal(b, m, deterministic)
280
+}
281
+func (m *StartClientHandshakeReq) XXX_Merge(src proto.Message) {
282
+	xxx_messageInfo_StartClientHandshakeReq.Merge(m, src)
283
+}
284
+func (m *StartClientHandshakeReq) XXX_Size() int {
285
+	return xxx_messageInfo_StartClientHandshakeReq.Size(m)
286
+}
287
+func (m *StartClientHandshakeReq) XXX_DiscardUnknown() {
288
+	xxx_messageInfo_StartClientHandshakeReq.DiscardUnknown(m)
289
+}
290
+
291
+var xxx_messageInfo_StartClientHandshakeReq proto.InternalMessageInfo
292
+
293
+func (m *StartClientHandshakeReq) GetHandshakeSecurityProtocol() HandshakeProtocol {
294
+	if m != nil {
295
+		return m.HandshakeSecurityProtocol
296
+	}
297
+	return HandshakeProtocol_HANDSHAKE_PROTOCOL_UNSPECIFIED
298
+}
299
+
300
+func (m *StartClientHandshakeReq) GetApplicationProtocols() []string {
301
+	if m != nil {
302
+		return m.ApplicationProtocols
303
+	}
304
+	return nil
305
+}
306
+
307
+func (m *StartClientHandshakeReq) GetRecordProtocols() []string {
308
+	if m != nil {
309
+		return m.RecordProtocols
310
+	}
311
+	return nil
312
+}
313
+
314
+func (m *StartClientHandshakeReq) GetTargetIdentities() []*Identity {
315
+	if m != nil {
316
+		return m.TargetIdentities
317
+	}
318
+	return nil
319
+}
320
+
321
+func (m *StartClientHandshakeReq) GetLocalIdentity() *Identity {
322
+	if m != nil {
323
+		return m.LocalIdentity
324
+	}
325
+	return nil
326
+}
327
+
328
+func (m *StartClientHandshakeReq) GetLocalEndpoint() *Endpoint {
329
+	if m != nil {
330
+		return m.LocalEndpoint
331
+	}
332
+	return nil
333
+}
334
+
335
+func (m *StartClientHandshakeReq) GetRemoteEndpoint() *Endpoint {
336
+	if m != nil {
337
+		return m.RemoteEndpoint
338
+	}
339
+	return nil
340
+}
341
+
342
+func (m *StartClientHandshakeReq) GetTargetName() string {
343
+	if m != nil {
344
+		return m.TargetName
345
+	}
346
+	return ""
347
+}
348
+
349
+func (m *StartClientHandshakeReq) GetRpcVersions() *RpcProtocolVersions {
350
+	if m != nil {
351
+		return m.RpcVersions
352
+	}
353
+	return nil
354
+}
355
+
356
+func (m *StartClientHandshakeReq) GetMaxFrameSize() uint32 {
357
+	if m != nil {
358
+		return m.MaxFrameSize
359
+	}
360
+	return 0
361
+}
362
+
363
+type ServerHandshakeParameters struct {
364
+	// The record protocols supported by the server, e.g.,
365
+	// "ALTSRP_GCM_AES128".
366
+	RecordProtocols []string `protobuf:"bytes,1,rep,name=record_protocols,json=recordProtocols,proto3" json:"record_protocols,omitempty"`
367
+	// (Optional) A list of local identities supported by the server, if
368
+	// specified. Otherwise, the handshaker chooses a default local identity.
369
+	LocalIdentities      []*Identity `protobuf:"bytes,2,rep,name=local_identities,json=localIdentities,proto3" json:"local_identities,omitempty"`
370
+	XXX_NoUnkeyedLiteral struct{}    `json:"-"`
371
+	XXX_unrecognized     []byte      `json:"-"`
372
+	XXX_sizecache        int32       `json:"-"`
373
+}
374
+
375
+func (m *ServerHandshakeParameters) Reset()         { *m = ServerHandshakeParameters{} }
376
+func (m *ServerHandshakeParameters) String() string { return proto.CompactTextString(m) }
377
+func (*ServerHandshakeParameters) ProtoMessage()    {}
378
+func (*ServerHandshakeParameters) Descriptor() ([]byte, []int) {
379
+	return fileDescriptor_54c074f40c7c7e99, []int{3}
380
+}
381
+
382
+func (m *ServerHandshakeParameters) XXX_Unmarshal(b []byte) error {
383
+	return xxx_messageInfo_ServerHandshakeParameters.Unmarshal(m, b)
384
+}
385
+func (m *ServerHandshakeParameters) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
386
+	return xxx_messageInfo_ServerHandshakeParameters.Marshal(b, m, deterministic)
387
+}
388
+func (m *ServerHandshakeParameters) XXX_Merge(src proto.Message) {
389
+	xxx_messageInfo_ServerHandshakeParameters.Merge(m, src)
390
+}
391
+func (m *ServerHandshakeParameters) XXX_Size() int {
392
+	return xxx_messageInfo_ServerHandshakeParameters.Size(m)
393
+}
394
+func (m *ServerHandshakeParameters) XXX_DiscardUnknown() {
395
+	xxx_messageInfo_ServerHandshakeParameters.DiscardUnknown(m)
396
+}
397
+
398
+var xxx_messageInfo_ServerHandshakeParameters proto.InternalMessageInfo
399
+
400
+func (m *ServerHandshakeParameters) GetRecordProtocols() []string {
401
+	if m != nil {
402
+		return m.RecordProtocols
403
+	}
404
+	return nil
405
+}
406
+
407
+func (m *ServerHandshakeParameters) GetLocalIdentities() []*Identity {
408
+	if m != nil {
409
+		return m.LocalIdentities
410
+	}
411
+	return nil
412
+}
413
+
414
+type StartServerHandshakeReq struct {
415
+	// The application protocols supported by the server, e.g., "h2" (for http2),
416
+	// "grpc".
417
+	ApplicationProtocols []string `protobuf:"bytes,1,rep,name=application_protocols,json=applicationProtocols,proto3" json:"application_protocols,omitempty"`
418
+	// Handshake parameters (record protocols and local identities supported by
419
+	// the server) mapped by the handshake protocol. Each handshake security
420
+	// protocol (e.g., TLS or ALTS) has its own set of record protocols and local
421
+	// identities. Since protobuf does not support enum as key to the map, the key
422
+	// to handshake_parameters is the integer value of HandshakeProtocol enum.
423
+	HandshakeParameters map[int32]*ServerHandshakeParameters `protobuf:"bytes,2,rep,name=handshake_parameters,json=handshakeParameters,proto3" json:"handshake_parameters,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
424
+	// Bytes in out_frames returned from the peer's HandshakerResp. It is possible
425
+	// that the peer's out_frames are split into multiple HandshakReq messages.
426
+	InBytes []byte `protobuf:"bytes,3,opt,name=in_bytes,json=inBytes,proto3" json:"in_bytes,omitempty"`
427
+	// (Optional) Local endpoint information of the connection to the client,
428
+	// such as local IP address, port number, and network protocol.
429
+	LocalEndpoint *Endpoint `protobuf:"bytes,4,opt,name=local_endpoint,json=localEndpoint,proto3" json:"local_endpoint,omitempty"`
430
+	// (Optional) Endpoint information of the remote client, such as IP address,
431
+	// port number, and network protocol.
432
+	RemoteEndpoint *Endpoint `protobuf:"bytes,5,opt,name=remote_endpoint,json=remoteEndpoint,proto3" json:"remote_endpoint,omitempty"`
433
+	// (Optional) RPC protocol versions supported by the server.
434
+	RpcVersions *RpcProtocolVersions `protobuf:"bytes,6,opt,name=rpc_versions,json=rpcVersions,proto3" json:"rpc_versions,omitempty"`
435
+	// (Optional) Maximum frame size supported by the server.
436
+	MaxFrameSize         uint32   `protobuf:"varint,7,opt,name=max_frame_size,json=maxFrameSize,proto3" json:"max_frame_size,omitempty"`
437
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
438
+	XXX_unrecognized     []byte   `json:"-"`
439
+	XXX_sizecache        int32    `json:"-"`
440
+}
441
+
442
+func (m *StartServerHandshakeReq) Reset()         { *m = StartServerHandshakeReq{} }
443
+func (m *StartServerHandshakeReq) String() string { return proto.CompactTextString(m) }
444
+func (*StartServerHandshakeReq) ProtoMessage()    {}
445
+func (*StartServerHandshakeReq) Descriptor() ([]byte, []int) {
446
+	return fileDescriptor_54c074f40c7c7e99, []int{4}
447
+}
448
+
449
+func (m *StartServerHandshakeReq) XXX_Unmarshal(b []byte) error {
450
+	return xxx_messageInfo_StartServerHandshakeReq.Unmarshal(m, b)
451
+}
452
+func (m *StartServerHandshakeReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
453
+	return xxx_messageInfo_StartServerHandshakeReq.Marshal(b, m, deterministic)
454
+}
455
+func (m *StartServerHandshakeReq) XXX_Merge(src proto.Message) {
456
+	xxx_messageInfo_StartServerHandshakeReq.Merge(m, src)
457
+}
458
+func (m *StartServerHandshakeReq) XXX_Size() int {
459
+	return xxx_messageInfo_StartServerHandshakeReq.Size(m)
460
+}
461
+func (m *StartServerHandshakeReq) XXX_DiscardUnknown() {
462
+	xxx_messageInfo_StartServerHandshakeReq.DiscardUnknown(m)
463
+}
464
+
465
+var xxx_messageInfo_StartServerHandshakeReq proto.InternalMessageInfo
466
+
467
+func (m *StartServerHandshakeReq) GetApplicationProtocols() []string {
468
+	if m != nil {
469
+		return m.ApplicationProtocols
470
+	}
471
+	return nil
472
+}
473
+
474
+func (m *StartServerHandshakeReq) GetHandshakeParameters() map[int32]*ServerHandshakeParameters {
475
+	if m != nil {
476
+		return m.HandshakeParameters
477
+	}
478
+	return nil
479
+}
480
+
481
+func (m *StartServerHandshakeReq) GetInBytes() []byte {
482
+	if m != nil {
483
+		return m.InBytes
484
+	}
485
+	return nil
486
+}
487
+
488
+func (m *StartServerHandshakeReq) GetLocalEndpoint() *Endpoint {
489
+	if m != nil {
490
+		return m.LocalEndpoint
491
+	}
492
+	return nil
493
+}
494
+
495
+func (m *StartServerHandshakeReq) GetRemoteEndpoint() *Endpoint {
496
+	if m != nil {
497
+		return m.RemoteEndpoint
498
+	}
499
+	return nil
500
+}
501
+
502
+func (m *StartServerHandshakeReq) GetRpcVersions() *RpcProtocolVersions {
503
+	if m != nil {
504
+		return m.RpcVersions
505
+	}
506
+	return nil
507
+}
508
+
509
+func (m *StartServerHandshakeReq) GetMaxFrameSize() uint32 {
510
+	if m != nil {
511
+		return m.MaxFrameSize
512
+	}
513
+	return 0
514
+}
515
+
516
+type NextHandshakeMessageReq struct {
517
+	// Bytes in out_frames returned from the peer's HandshakerResp. It is possible
518
+	// that the peer's out_frames are split into multiple NextHandshakerMessageReq
519
+	// messages.
520
+	InBytes              []byte   `protobuf:"bytes,1,opt,name=in_bytes,json=inBytes,proto3" json:"in_bytes,omitempty"`
521
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
522
+	XXX_unrecognized     []byte   `json:"-"`
523
+	XXX_sizecache        int32    `json:"-"`
524
+}
525
+
526
+func (m *NextHandshakeMessageReq) Reset()         { *m = NextHandshakeMessageReq{} }
527
+func (m *NextHandshakeMessageReq) String() string { return proto.CompactTextString(m) }
528
+func (*NextHandshakeMessageReq) ProtoMessage()    {}
529
+func (*NextHandshakeMessageReq) Descriptor() ([]byte, []int) {
530
+	return fileDescriptor_54c074f40c7c7e99, []int{5}
531
+}
532
+
533
+func (m *NextHandshakeMessageReq) XXX_Unmarshal(b []byte) error {
534
+	return xxx_messageInfo_NextHandshakeMessageReq.Unmarshal(m, b)
535
+}
536
+func (m *NextHandshakeMessageReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
537
+	return xxx_messageInfo_NextHandshakeMessageReq.Marshal(b, m, deterministic)
538
+}
539
+func (m *NextHandshakeMessageReq) XXX_Merge(src proto.Message) {
540
+	xxx_messageInfo_NextHandshakeMessageReq.Merge(m, src)
541
+}
542
+func (m *NextHandshakeMessageReq) XXX_Size() int {
543
+	return xxx_messageInfo_NextHandshakeMessageReq.Size(m)
544
+}
545
+func (m *NextHandshakeMessageReq) XXX_DiscardUnknown() {
546
+	xxx_messageInfo_NextHandshakeMessageReq.DiscardUnknown(m)
547
+}
548
+
549
+var xxx_messageInfo_NextHandshakeMessageReq proto.InternalMessageInfo
550
+
551
+func (m *NextHandshakeMessageReq) GetInBytes() []byte {
552
+	if m != nil {
553
+		return m.InBytes
554
+	}
555
+	return nil
556
+}
557
+
558
+type HandshakerReq struct {
559
+	// Types that are valid to be assigned to ReqOneof:
560
+	//	*HandshakerReq_ClientStart
561
+	//	*HandshakerReq_ServerStart
562
+	//	*HandshakerReq_Next
563
+	ReqOneof             isHandshakerReq_ReqOneof `protobuf_oneof:"req_oneof"`
564
+	XXX_NoUnkeyedLiteral struct{}                 `json:"-"`
565
+	XXX_unrecognized     []byte                   `json:"-"`
566
+	XXX_sizecache        int32                    `json:"-"`
567
+}
568
+
569
+func (m *HandshakerReq) Reset()         { *m = HandshakerReq{} }
570
+func (m *HandshakerReq) String() string { return proto.CompactTextString(m) }
571
+func (*HandshakerReq) ProtoMessage()    {}
572
+func (*HandshakerReq) Descriptor() ([]byte, []int) {
573
+	return fileDescriptor_54c074f40c7c7e99, []int{6}
574
+}
575
+
576
+func (m *HandshakerReq) XXX_Unmarshal(b []byte) error {
577
+	return xxx_messageInfo_HandshakerReq.Unmarshal(m, b)
578
+}
579
+func (m *HandshakerReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
580
+	return xxx_messageInfo_HandshakerReq.Marshal(b, m, deterministic)
581
+}
582
+func (m *HandshakerReq) XXX_Merge(src proto.Message) {
583
+	xxx_messageInfo_HandshakerReq.Merge(m, src)
584
+}
585
+func (m *HandshakerReq) XXX_Size() int {
586
+	return xxx_messageInfo_HandshakerReq.Size(m)
587
+}
588
+func (m *HandshakerReq) XXX_DiscardUnknown() {
589
+	xxx_messageInfo_HandshakerReq.DiscardUnknown(m)
590
+}
591
+
592
+var xxx_messageInfo_HandshakerReq proto.InternalMessageInfo
593
+
594
+type isHandshakerReq_ReqOneof interface {
595
+	isHandshakerReq_ReqOneof()
596
+}
597
+
598
+type HandshakerReq_ClientStart struct {
599
+	ClientStart *StartClientHandshakeReq `protobuf:"bytes,1,opt,name=client_start,json=clientStart,proto3,oneof"`
600
+}
601
+
602
+type HandshakerReq_ServerStart struct {
603
+	ServerStart *StartServerHandshakeReq `protobuf:"bytes,2,opt,name=server_start,json=serverStart,proto3,oneof"`
604
+}
605
+
606
+type HandshakerReq_Next struct {
607
+	Next *NextHandshakeMessageReq `protobuf:"bytes,3,opt,name=next,proto3,oneof"`
608
+}
609
+
610
+func (*HandshakerReq_ClientStart) isHandshakerReq_ReqOneof() {}
611
+
612
+func (*HandshakerReq_ServerStart) isHandshakerReq_ReqOneof() {}
613
+
614
+func (*HandshakerReq_Next) isHandshakerReq_ReqOneof() {}
615
+
616
+func (m *HandshakerReq) GetReqOneof() isHandshakerReq_ReqOneof {
617
+	if m != nil {
618
+		return m.ReqOneof
619
+	}
620
+	return nil
621
+}
622
+
623
+func (m *HandshakerReq) GetClientStart() *StartClientHandshakeReq {
624
+	if x, ok := m.GetReqOneof().(*HandshakerReq_ClientStart); ok {
625
+		return x.ClientStart
626
+	}
627
+	return nil
628
+}
629
+
630
+func (m *HandshakerReq) GetServerStart() *StartServerHandshakeReq {
631
+	if x, ok := m.GetReqOneof().(*HandshakerReq_ServerStart); ok {
632
+		return x.ServerStart
633
+	}
634
+	return nil
635
+}
636
+
637
+func (m *HandshakerReq) GetNext() *NextHandshakeMessageReq {
638
+	if x, ok := m.GetReqOneof().(*HandshakerReq_Next); ok {
639
+		return x.Next
640
+	}
641
+	return nil
642
+}
643
+
644
+// XXX_OneofWrappers is for the internal use of the proto package.
645
+func (*HandshakerReq) XXX_OneofWrappers() []interface{} {
646
+	return []interface{}{
647
+		(*HandshakerReq_ClientStart)(nil),
648
+		(*HandshakerReq_ServerStart)(nil),
649
+		(*HandshakerReq_Next)(nil),
650
+	}
651
+}
652
+
653
+type HandshakerResult struct {
654
+	// The application protocol negotiated for this connection.
655
+	ApplicationProtocol string `protobuf:"bytes,1,opt,name=application_protocol,json=applicationProtocol,proto3" json:"application_protocol,omitempty"`
656
+	// The record protocol negotiated for this connection.
657
+	RecordProtocol string `protobuf:"bytes,2,opt,name=record_protocol,json=recordProtocol,proto3" json:"record_protocol,omitempty"`
658
+	// Cryptographic key data. The key data may be more than the key length
659
+	// required for the record protocol, thus the client of the handshaker
660
+	// service needs to truncate the key data into the right key length.
661
+	KeyData []byte `protobuf:"bytes,3,opt,name=key_data,json=keyData,proto3" json:"key_data,omitempty"`
662
+	// The authenticated identity of the peer.
663
+	PeerIdentity *Identity `protobuf:"bytes,4,opt,name=peer_identity,json=peerIdentity,proto3" json:"peer_identity,omitempty"`
664
+	// The local identity used in the handshake.
665
+	LocalIdentity *Identity `protobuf:"bytes,5,opt,name=local_identity,json=localIdentity,proto3" json:"local_identity,omitempty"`
666
+	// Indicate whether the handshaker service client should keep the channel
667
+	// between the handshaker service open, e.g., in order to handle
668
+	// post-handshake messages in the future.
669
+	KeepChannelOpen bool `protobuf:"varint,6,opt,name=keep_channel_open,json=keepChannelOpen,proto3" json:"keep_channel_open,omitempty"`
670
+	// The RPC protocol versions supported by the peer.
671
+	PeerRpcVersions *RpcProtocolVersions `protobuf:"bytes,7,opt,name=peer_rpc_versions,json=peerRpcVersions,proto3" json:"peer_rpc_versions,omitempty"`
672
+	// The maximum frame size of the peer.
673
+	MaxFrameSize         uint32   `protobuf:"varint,8,opt,name=max_frame_size,json=maxFrameSize,proto3" json:"max_frame_size,omitempty"`
674
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
675
+	XXX_unrecognized     []byte   `json:"-"`
676
+	XXX_sizecache        int32    `json:"-"`
677
+}
678
+
679
+func (m *HandshakerResult) Reset()         { *m = HandshakerResult{} }
680
+func (m *HandshakerResult) String() string { return proto.CompactTextString(m) }
681
+func (*HandshakerResult) ProtoMessage()    {}
682
+func (*HandshakerResult) Descriptor() ([]byte, []int) {
683
+	return fileDescriptor_54c074f40c7c7e99, []int{7}
684
+}
685
+
686
+func (m *HandshakerResult) XXX_Unmarshal(b []byte) error {
687
+	return xxx_messageInfo_HandshakerResult.Unmarshal(m, b)
688
+}
689
+func (m *HandshakerResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
690
+	return xxx_messageInfo_HandshakerResult.Marshal(b, m, deterministic)
691
+}
692
+func (m *HandshakerResult) XXX_Merge(src proto.Message) {
693
+	xxx_messageInfo_HandshakerResult.Merge(m, src)
694
+}
695
+func (m *HandshakerResult) XXX_Size() int {
696
+	return xxx_messageInfo_HandshakerResult.Size(m)
697
+}
698
+func (m *HandshakerResult) XXX_DiscardUnknown() {
699
+	xxx_messageInfo_HandshakerResult.DiscardUnknown(m)
700
+}
701
+
702
+var xxx_messageInfo_HandshakerResult proto.InternalMessageInfo
703
+
704
+func (m *HandshakerResult) GetApplicationProtocol() string {
705
+	if m != nil {
706
+		return m.ApplicationProtocol
707
+	}
708
+	return ""
709
+}
710
+
711
+func (m *HandshakerResult) GetRecordProtocol() string {
712
+	if m != nil {
713
+		return m.RecordProtocol
714
+	}
715
+	return ""
716
+}
717
+
718
+func (m *HandshakerResult) GetKeyData() []byte {
719
+	if m != nil {
720
+		return m.KeyData
721
+	}
722
+	return nil
723
+}
724
+
725
+func (m *HandshakerResult) GetPeerIdentity() *Identity {
726
+	if m != nil {
727
+		return m.PeerIdentity
728
+	}
729
+	return nil
730
+}
731
+
732
+func (m *HandshakerResult) GetLocalIdentity() *Identity {
733
+	if m != nil {
734
+		return m.LocalIdentity
735
+	}
736
+	return nil
737
+}
738
+
739
+func (m *HandshakerResult) GetKeepChannelOpen() bool {
740
+	if m != nil {
741
+		return m.KeepChannelOpen
742
+	}
743
+	return false
744
+}
745
+
746
+func (m *HandshakerResult) GetPeerRpcVersions() *RpcProtocolVersions {
747
+	if m != nil {
748
+		return m.PeerRpcVersions
749
+	}
750
+	return nil
751
+}
752
+
753
+func (m *HandshakerResult) GetMaxFrameSize() uint32 {
754
+	if m != nil {
755
+		return m.MaxFrameSize
756
+	}
757
+	return 0
758
+}
759
+
760
+type HandshakerStatus struct {
761
+	// The status code. This could be the gRPC status code.
762
+	Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
763
+	// The status details.
764
+	Details              string   `protobuf:"bytes,2,opt,name=details,proto3" json:"details,omitempty"`
765
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
766
+	XXX_unrecognized     []byte   `json:"-"`
767
+	XXX_sizecache        int32    `json:"-"`
768
+}
769
+
770
+func (m *HandshakerStatus) Reset()         { *m = HandshakerStatus{} }
771
+func (m *HandshakerStatus) String() string { return proto.CompactTextString(m) }
772
+func (*HandshakerStatus) ProtoMessage()    {}
773
+func (*HandshakerStatus) Descriptor() ([]byte, []int) {
774
+	return fileDescriptor_54c074f40c7c7e99, []int{8}
775
+}
776
+
777
+func (m *HandshakerStatus) XXX_Unmarshal(b []byte) error {
778
+	return xxx_messageInfo_HandshakerStatus.Unmarshal(m, b)
779
+}
780
+func (m *HandshakerStatus) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
781
+	return xxx_messageInfo_HandshakerStatus.Marshal(b, m, deterministic)
782
+}
783
+func (m *HandshakerStatus) XXX_Merge(src proto.Message) {
784
+	xxx_messageInfo_HandshakerStatus.Merge(m, src)
785
+}
786
+func (m *HandshakerStatus) XXX_Size() int {
787
+	return xxx_messageInfo_HandshakerStatus.Size(m)
788
+}
789
+func (m *HandshakerStatus) XXX_DiscardUnknown() {
790
+	xxx_messageInfo_HandshakerStatus.DiscardUnknown(m)
791
+}
792
+
793
+var xxx_messageInfo_HandshakerStatus proto.InternalMessageInfo
794
+
795
+func (m *HandshakerStatus) GetCode() uint32 {
796
+	if m != nil {
797
+		return m.Code
798
+	}
799
+	return 0
800
+}
801
+
802
+func (m *HandshakerStatus) GetDetails() string {
803
+	if m != nil {
804
+		return m.Details
805
+	}
806
+	return ""
807
+}
808
+
809
+type HandshakerResp struct {
810
+	// Frames to be given to the peer for the NextHandshakeMessageReq. May be
811
+	// empty if no out_frames have to be sent to the peer or if in_bytes in the
812
+	// HandshakerReq are incomplete. All the non-empty out frames must be sent to
813
+	// the peer even if the handshaker status is not OK as these frames may
814
+	// contain the alert frames.
815
+	OutFrames []byte `protobuf:"bytes,1,opt,name=out_frames,json=outFrames,proto3" json:"out_frames,omitempty"`
816
+	// Number of bytes in the in_bytes consumed by the handshaker. It is possible
817
+	// that part of in_bytes in HandshakerReq was unrelated to the handshake
818
+	// process.
819
+	BytesConsumed uint32 `protobuf:"varint,2,opt,name=bytes_consumed,json=bytesConsumed,proto3" json:"bytes_consumed,omitempty"`
820
+	// This is set iff the handshake was successful. out_frames may still be set
821
+	// to frames that needs to be forwarded to the peer.
822
+	Result *HandshakerResult `protobuf:"bytes,3,opt,name=result,proto3" json:"result,omitempty"`
823
+	// Status of the handshaker.
824
+	Status               *HandshakerStatus `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"`
825
+	XXX_NoUnkeyedLiteral struct{}          `json:"-"`
826
+	XXX_unrecognized     []byte            `json:"-"`
827
+	XXX_sizecache        int32             `json:"-"`
828
+}
829
+
830
+func (m *HandshakerResp) Reset()         { *m = HandshakerResp{} }
831
+func (m *HandshakerResp) String() string { return proto.CompactTextString(m) }
832
+func (*HandshakerResp) ProtoMessage()    {}
833
+func (*HandshakerResp) Descriptor() ([]byte, []int) {
834
+	return fileDescriptor_54c074f40c7c7e99, []int{9}
835
+}
836
+
837
+func (m *HandshakerResp) XXX_Unmarshal(b []byte) error {
838
+	return xxx_messageInfo_HandshakerResp.Unmarshal(m, b)
839
+}
840
+func (m *HandshakerResp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
841
+	return xxx_messageInfo_HandshakerResp.Marshal(b, m, deterministic)
842
+}
843
+func (m *HandshakerResp) XXX_Merge(src proto.Message) {
844
+	xxx_messageInfo_HandshakerResp.Merge(m, src)
845
+}
846
+func (m *HandshakerResp) XXX_Size() int {
847
+	return xxx_messageInfo_HandshakerResp.Size(m)
848
+}
849
+func (m *HandshakerResp) XXX_DiscardUnknown() {
850
+	xxx_messageInfo_HandshakerResp.DiscardUnknown(m)
851
+}
852
+
853
+var xxx_messageInfo_HandshakerResp proto.InternalMessageInfo
854
+
855
+func (m *HandshakerResp) GetOutFrames() []byte {
856
+	if m != nil {
857
+		return m.OutFrames
858
+	}
859
+	return nil
860
+}
861
+
862
+func (m *HandshakerResp) GetBytesConsumed() uint32 {
863
+	if m != nil {
864
+		return m.BytesConsumed
865
+	}
866
+	return 0
867
+}
868
+
869
+func (m *HandshakerResp) GetResult() *HandshakerResult {
870
+	if m != nil {
871
+		return m.Result
872
+	}
873
+	return nil
874
+}
875
+
876
+func (m *HandshakerResp) GetStatus() *HandshakerStatus {
877
+	if m != nil {
878
+		return m.Status
879
+	}
880
+	return nil
881
+}
882
+
883
+func init() {
884
+	proto.RegisterEnum("grpc.gcp.HandshakeProtocol", HandshakeProtocol_name, HandshakeProtocol_value)
885
+	proto.RegisterEnum("grpc.gcp.NetworkProtocol", NetworkProtocol_name, NetworkProtocol_value)
886
+	proto.RegisterType((*Endpoint)(nil), "grpc.gcp.Endpoint")
887
+	proto.RegisterType((*Identity)(nil), "grpc.gcp.Identity")
888
+	proto.RegisterMapType((map[string]string)(nil), "grpc.gcp.Identity.AttributesEntry")
889
+	proto.RegisterType((*StartClientHandshakeReq)(nil), "grpc.gcp.StartClientHandshakeReq")
890
+	proto.RegisterType((*ServerHandshakeParameters)(nil), "grpc.gcp.ServerHandshakeParameters")
891
+	proto.RegisterType((*StartServerHandshakeReq)(nil), "grpc.gcp.StartServerHandshakeReq")
892
+	proto.RegisterMapType((map[int32]*ServerHandshakeParameters)(nil), "grpc.gcp.StartServerHandshakeReq.HandshakeParametersEntry")
893
+	proto.RegisterType((*NextHandshakeMessageReq)(nil), "grpc.gcp.NextHandshakeMessageReq")
894
+	proto.RegisterType((*HandshakerReq)(nil), "grpc.gcp.HandshakerReq")
895
+	proto.RegisterType((*HandshakerResult)(nil), "grpc.gcp.HandshakerResult")
896
+	proto.RegisterType((*HandshakerStatus)(nil), "grpc.gcp.HandshakerStatus")
897
+	proto.RegisterType((*HandshakerResp)(nil), "grpc.gcp.HandshakerResp")
898
+}
899
+
900
+func init() { proto.RegisterFile("grpc/gcp/handshaker.proto", fileDescriptor_54c074f40c7c7e99) }
901
+
902
+var fileDescriptor_54c074f40c7c7e99 = []byte{
903
+	// 1203 bytes of a gzipped FileDescriptorProto
904
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xdd, 0x6e, 0x1b, 0x45,
905
+	0x14, 0xce, 0xda, 0x4e, 0xe2, 0x1c, 0xc7, 0x3f, 0x99, 0xa6, 0xea, 0x26, 0x6d, 0xc1, 0x18, 0x10,
906
+	0x6e, 0x2f, 0x6c, 0x70, 0x41, 0xa5, 0x45, 0x55, 0x6b, 0x3b, 0x8e, 0x1c, 0x5a, 0x1c, 0x6b, 0x9d,
907
+	0x82, 0x44, 0x2f, 0x56, 0xd3, 0xf5, 0xd4, 0x59, 0x79, 0x3d, 0xb3, 0x9d, 0x19, 0x87, 0xb8, 0xf7,
908
+	0xbc, 0x04, 0xf7, 0xbc, 0x06, 0x2f, 0xc1, 0x33, 0x20, 0xf1, 0x18, 0x68, 0x67, 0x7f, 0x6d, 0xaf,
909
+	0xab, 0x22, 0xb8, 0xdb, 0x39, 0xf3, 0x7d, 0x67, 0xce, 0x9c, 0xf3, 0x9d, 0xb3, 0x03, 0x47, 0x13,
910
+	0xee, 0x5a, 0xcd, 0x89, 0xe5, 0x36, 0x2f, 0x31, 0x1d, 0x8b, 0x4b, 0x3c, 0x25, 0xbc, 0xe1, 0x72,
911
+	0x26, 0x19, 0xca, 0x7b, 0x5b, 0x8d, 0x89, 0xe5, 0x1e, 0xd7, 0x23, 0x90, 0xe4, 0x98, 0x0a, 0x97,
912
+	0x71, 0x69, 0x0a, 0x62, 0xcd, 0xb9, 0x2d, 0x17, 0xa6, 0xc5, 0x66, 0x33, 0x46, 0x7d, 0x4e, 0x4d,
913
+	0x42, 0xbe, 0x47, 0xc7, 0x2e, 0xb3, 0xa9, 0x44, 0x77, 0x01, 0x6c, 0xd7, 0xc4, 0xe3, 0x31, 0x27,
914
+	0x42, 0xe8, 0x5a, 0x55, 0xab, 0xef, 0x19, 0x7b, 0xb6, 0xdb, 0xf6, 0x0d, 0x08, 0x41, 0xce, 0x73,
915
+	0xa4, 0x67, 0xaa, 0x5a, 0x7d, 0xdb, 0x50, 0xdf, 0xe8, 0x1b, 0xc8, 0x2b, 0x3f, 0x16, 0x73, 0xf4,
916
+	0x6c, 0x55, 0xab, 0x97, 0x5a, 0x47, 0x8d, 0x30, 0x8a, 0xc6, 0x80, 0xc8, 0x5f, 0x18, 0x9f, 0x0e,
917
+	0x03, 0x80, 0x11, 0x41, 0x6b, 0x7f, 0x6b, 0x90, 0x3f, 0x1b, 0x13, 0x2a, 0x6d, 0xb9, 0x40, 0xf7,
918
+	0xa0, 0x2c, 0x08, 0xbf, 0xb2, 0x2d, 0x62, 0x62, 0xcb, 0x62, 0x73, 0x2a, 0xfd, 0xb3, 0xfb, 0x5b,
919
+	0x46, 0x29, 0xd8, 0x68, 0xfb, 0x76, 0x74, 0x07, 0xf2, 0x97, 0x4c, 0x48, 0x8a, 0x67, 0x44, 0x85,
920
+	0xe1, 0x61, 0x22, 0x0b, 0xea, 0x00, 0x60, 0x29, 0xb9, 0xfd, 0x7a, 0x2e, 0x89, 0xd0, 0xb3, 0xd5,
921
+	0x6c, 0xbd, 0xd0, 0xaa, 0xc5, 0xe1, 0x84, 0x07, 0x36, 0xda, 0x11, 0xa8, 0x47, 0x25, 0x5f, 0x18,
922
+	0x09, 0xd6, 0xf1, 0x13, 0x28, 0xaf, 0x6c, 0xa3, 0x0a, 0x64, 0xa7, 0x64, 0x11, 0xe4, 0xc3, 0xfb,
923
+	0x44, 0x87, 0xb0, 0x7d, 0x85, 0x9d, 0x79, 0x10, 0x83, 0xe1, 0x2f, 0x1e, 0x67, 0xbe, 0xd5, 0x3a,
924
+	0x15, 0x28, 0xd9, 0xc1, 0x31, 0x26, 0xa3, 0x84, 0xbd, 0xa9, 0xfd, 0x99, 0x83, 0x5b, 0x23, 0x89,
925
+	0xb9, 0xec, 0x3a, 0x36, 0xa1, 0xb2, 0x1f, 0x16, 0xcd, 0x20, 0x6f, 0xd1, 0x2b, 0xb8, 0x1d, 0x15,
926
+	0x31, 0xae, 0x4f, 0x94, 0x50, 0x4d, 0x25, 0xf4, 0x76, 0x7c, 0x83, 0x88, 0x1c, 0xa5, 0xf4, 0x28,
927
+	0xe2, 0x8f, 0x02, 0x7a, 0xb8, 0x85, 0x1e, 0xc0, 0x4d, 0xec, 0xba, 0x8e, 0x6d, 0x61, 0x69, 0x33,
928
+	0x1a, 0x79, 0x15, 0x7a, 0xa6, 0x9a, 0xad, 0xef, 0x19, 0x87, 0x89, 0xcd, 0x90, 0x23, 0xd0, 0x3d,
929
+	0xa8, 0x70, 0x62, 0x31, 0x3e, 0x4e, 0xe0, 0xb3, 0x0a, 0x5f, 0xf6, 0xed, 0x31, 0xf4, 0x29, 0x1c,
930
+	0x48, 0xcc, 0x27, 0x44, 0x9a, 0xc1, 0x8d, 0x6d, 0x22, 0xf4, 0x9c, 0x4a, 0x3a, 0x5a, 0x4f, 0xba,
931
+	0x51, 0xf1, 0xc1, 0x67, 0x11, 0x16, 0x3d, 0x82, 0x92, 0xc3, 0x2c, 0xec, 0x84, 0xfc, 0x85, 0xbe,
932
+	0x5d, 0xd5, 0x36, 0xb0, 0x8b, 0x0a, 0x19, 0x49, 0x26, 0xa2, 0x92, 0x40, 0xbb, 0xfa, 0xce, 0x2a,
933
+	0x35, 0x54, 0x75, 0x40, 0x8d, 0x44, 0xfe, 0x1d, 0x94, 0x39, 0x99, 0x31, 0x49, 0x62, 0xee, 0xee,
934
+	0x46, 0x6e, 0xc9, 0x87, 0x46, 0xe4, 0x8f, 0xa1, 0x10, 0xdc, 0x59, 0x49, 0x30, 0xaf, 0xca, 0x0f,
935
+	0xbe, 0x69, 0xe0, 0x49, 0xf0, 0x19, 0xec, 0x73, 0xd7, 0x32, 0xaf, 0x08, 0x17, 0x36, 0xa3, 0x42,
936
+	0xdf, 0x53, 0xae, 0xef, 0xc6, 0xae, 0x0d, 0xd7, 0x0a, 0x53, 0xf8, 0x63, 0x00, 0x32, 0x0a, 0xdc,
937
+	0xb5, 0xc2, 0x05, 0xfa, 0x0c, 0x4a, 0x33, 0x7c, 0x6d, 0xbe, 0xe1, 0x78, 0x46, 0x4c, 0x61, 0xbf,
938
+	0x23, 0x3a, 0x54, 0xb5, 0x7a, 0xd1, 0xd8, 0x9f, 0xe1, 0xeb, 0x53, 0xcf, 0x38, 0xb2, 0xdf, 0x91,
939
+	0xda, 0xaf, 0x1a, 0x1c, 0x8d, 0x08, 0xbf, 0x22, 0x3c, 0xd6, 0x04, 0xf6, 0x76, 0x25, 0xe1, 0xe9,
940
+	0x55, 0xd4, 0xd2, 0xab, 0xf8, 0x04, 0x2a, 0x4b, 0x45, 0xf0, 0x8a, 0x98, 0xd9, 0x58, 0xc4, 0x72,
941
+	0xb2, 0x0c, 0x36, 0x11, 0xb5, 0xdf, 0x43, 0x75, 0xaf, 0x04, 0xe3, 0xa9, 0x7b, 0xa3, 0x00, 0xb5,
942
+	0xf7, 0x08, 0x70, 0x06, 0x87, 0x71, 0x4b, 0xb8, 0xd1, 0x95, 0x82, 0x98, 0x1e, 0xc7, 0x31, 0x6d,
943
+	0x38, 0xb5, 0x91, 0x92, 0x0f, 0xbf, 0xcb, 0x6f, 0x5c, 0xa6, 0x64, 0xea, 0x08, 0xf2, 0x36, 0x35,
944
+	0x5f, 0x2f, 0xfc, 0x81, 0xa1, 0xd5, 0xf7, 0x8d, 0x5d, 0x9b, 0x76, 0xbc, 0x65, 0x8a, 0xc6, 0x72,
945
+	0xff, 0x41, 0x63, 0xdb, 0x1f, 0xac, 0xb1, 0x55, 0x09, 0xed, 0xfc, 0x0f, 0x12, 0xda, 0x5d, 0x97,
946
+	0xd0, 0xf1, 0x14, 0xf4, 0x4d, 0xb9, 0x4a, 0x8e, 0xbc, 0x6d, 0x7f, 0xe4, 0x3d, 0x4a, 0x8e, 0xbc,
947
+	0x42, 0xeb, 0xd3, 0x44, 0x21, 0x36, 0xc9, 0x30, 0x31, 0x17, 0x6b, 0x5f, 0xc3, 0xad, 0x01, 0xb9,
948
+	0x8e, 0xa7, 0xdf, 0x0f, 0x44, 0x08, 0x3c, 0x51, 0x32, 0x49, 0x96, 0x40, 0x5b, 0x2a, 0x41, 0xed,
949
+	0x2f, 0x0d, 0x8a, 0x11, 0x85, 0x7b, 0xe0, 0x53, 0xd8, 0xb7, 0xd4, 0x1c, 0x35, 0x85, 0x57, 0x7f,
950
+	0x45, 0x28, 0xb4, 0x3e, 0x59, 0x91, 0xc5, 0xfa, 0xa8, 0xed, 0x6f, 0x19, 0x05, 0x9f, 0xa8, 0x00,
951
+	0x9e, 0x1f, 0xa1, 0xe2, 0x0e, 0xfc, 0x64, 0x52, 0xfd, 0xac, 0xcb, 0xcb, 0xf3, 0xe3, 0x13, 0x7d,
952
+	0x3f, 0x0f, 0x21, 0x47, 0xc9, 0xb5, 0x54, 0xda, 0x59, 0xe2, 0x6f, 0xb8, 0x6d, 0x7f, 0xcb, 0x50,
953
+	0x84, 0x4e, 0x01, 0xf6, 0x38, 0x79, 0x1b, 0xfc, 0x23, 0x7e, 0xcb, 0x42, 0x25, 0x79, 0x4f, 0x31,
954
+	0x77, 0x24, 0xfa, 0x0a, 0x0e, 0xd3, 0xda, 0x27, 0xf8, 0x0f, 0xdd, 0x48, 0xe9, 0x1e, 0xf4, 0x05,
955
+	0x94, 0x57, 0xfa, 0x3e, 0xf8, 0x43, 0x95, 0x96, 0xdb, 0xde, 0xcb, 0xf9, 0x94, 0x2c, 0xcc, 0x31,
956
+	0x96, 0x38, 0x94, 0xfd, 0x94, 0x2c, 0x4e, 0xb0, 0xc4, 0xe8, 0x21, 0x14, 0x5d, 0x42, 0x78, 0x3c,
957
+	0x94, 0x73, 0x1b, 0x87, 0xf2, 0xbe, 0x07, 0x5c, 0x9f, 0xc9, 0xff, 0x7e, 0x9c, 0xdf, 0x87, 0x83,
958
+	0x29, 0x21, 0xae, 0x69, 0x5d, 0x62, 0x4a, 0x89, 0x63, 0x32, 0x97, 0x50, 0xa5, 0xfb, 0xbc, 0x51,
959
+	0xf6, 0x36, 0xba, 0xbe, 0xfd, 0xdc, 0x25, 0x14, 0x9d, 0xc1, 0x81, 0x8a, 0x6f, 0xa9, 0x47, 0x76,
960
+	0x3f, 0xa4, 0x47, 0xca, 0x1e, 0xcf, 0x78, 0x6f, 0x9f, 0xe4, 0x53, 0x46, 0xed, 0xb3, 0x64, 0x6d,
961
+	0x46, 0x12, 0xcb, 0xb9, 0x7a, 0x0a, 0x59, 0x6c, 0x4c, 0x54, 0x2d, 0x8a, 0x86, 0xfa, 0x46, 0x3a,
962
+	0xec, 0x8e, 0x89, 0xc4, 0xb6, 0xfa, 0xc3, 0x7a, 0x49, 0x0f, 0x97, 0xb5, 0x3f, 0x34, 0x28, 0x2d,
963
+	0x95, 0xd7, 0xf5, 0x9e, 0x5a, 0x6c, 0x2e, 0xfd, 0xa3, 0x43, 0xd9, 0xef, 0xb1, 0xb9, 0x54, 0xc7,
964
+	0x0a, 0xf4, 0x39, 0x94, 0x54, 0x43, 0x98, 0x16, 0xa3, 0x62, 0x3e, 0x23, 0x63, 0xe5, 0xb2, 0x68,
965
+	0x14, 0x95, 0xb5, 0x1b, 0x18, 0x51, 0x0b, 0x76, 0xb8, 0x12, 0x4b, 0xa0, 0xbf, 0xe3, 0x94, 0xa7,
966
+	0x42, 0x20, 0x27, 0x23, 0x40, 0x7a, 0x1c, 0xa1, 0x2e, 0x11, 0x14, 0x36, 0x95, 0xe3, 0x5f, 0xd3,
967
+	0x08, 0x90, 0xf7, 0xbf, 0x87, 0x83, 0xb5, 0xa7, 0x07, 0xaa, 0xc1, 0x47, 0xfd, 0xf6, 0xe0, 0x64,
968
+	0xd4, 0x6f, 0x3f, 0xef, 0x99, 0x43, 0xe3, 0xfc, 0xe2, 0xbc, 0x7b, 0xfe, 0xc2, 0x7c, 0x39, 0x18,
969
+	0x0d, 0x7b, 0xdd, 0xb3, 0xd3, 0xb3, 0xde, 0x49, 0x65, 0x0b, 0xed, 0x42, 0xf6, 0xe2, 0xc5, 0xa8,
970
+	0xa2, 0xa1, 0x3c, 0xe4, 0xda, 0x2f, 0x2e, 0x46, 0x95, 0xcc, 0xfd, 0x1e, 0x94, 0x57, 0xde, 0x85,
971
+	0xa8, 0x0a, 0x77, 0x06, 0xbd, 0x8b, 0x9f, 0xce, 0x8d, 0xe7, 0xef, 0xf3, 0xd3, 0x1d, 0x56, 0x34,
972
+	0xef, 0xe3, 0xe5, 0xc9, 0xb0, 0x92, 0x69, 0xbd, 0x4a, 0x84, 0xc4, 0x47, 0xfe, 0x2b, 0x11, 0x9d,
973
+	0x42, 0xe1, 0x84, 0x45, 0x66, 0x74, 0x2b, 0x3d, 0x1d, 0x6f, 0x8f, 0xf5, 0x0d, 0x79, 0x72, 0x6b,
974
+	0x5b, 0x75, 0xed, 0x4b, 0xad, 0x33, 0x85, 0x9b, 0x36, 0xf3, 0x31, 0xd8, 0x91, 0xa2, 0x61, 0x53,
975
+	0x49, 0x38, 0xc5, 0x4e, 0xa7, 0x1c, 0xc3, 0x55, 0xf4, 0x43, 0xed, 0xe7, 0xa7, 0x13, 0xc6, 0x26,
976
+	0x0e, 0x69, 0x4c, 0x98, 0x83, 0xe9, 0xa4, 0xc1, 0xf8, 0xa4, 0xa9, 0x1e, 0xdf, 0x16, 0x27, 0x4a,
977
+	0xde, 0xd8, 0x11, 0x4d, 0xcf, 0x49, 0x33, 0x74, 0xd2, 0x54, 0xbd, 0xa9, 0x40, 0xe6, 0xc4, 0x72,
978
+	0x5f, 0xef, 0xa8, 0xf5, 0x83, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xc1, 0xf9, 0x9d, 0xf2, 0xd9,
979
+	0x0b, 0x00, 0x00,
980
+}
981
+
982
+// Reference imports to suppress errors if they are not otherwise used.
983
+var _ context.Context
984
+var _ grpc.ClientConn
985
+
986
+// This is a compile-time assertion to ensure that this generated file
987
+// is compatible with the grpc package it is being compiled against.
988
+const _ = grpc.SupportPackageIsVersion4
989
+
990
+// HandshakerServiceClient is the client API for HandshakerService service.
991
+//
992
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
993
+type HandshakerServiceClient interface {
994
+	// Handshaker service accepts a stream of handshaker request, returning a
995
+	// stream of handshaker response. Client is expected to send exactly one
996
+	// message with either client_start or server_start followed by one or more
997
+	// messages with next. Each time client sends a request, the handshaker
998
+	// service expects to respond. Client does not have to wait for service's
999
+	// response before sending next request.
1000
+	DoHandshake(ctx context.Context, opts ...grpc.CallOption) (HandshakerService_DoHandshakeClient, error)
1001
+}
1002
+
1003
+type handshakerServiceClient struct {
1004
+	cc *grpc.ClientConn
1005
+}
1006
+
1007
+func NewHandshakerServiceClient(cc *grpc.ClientConn) HandshakerServiceClient {
1008
+	return &handshakerServiceClient{cc}
1009
+}
1010
+
1011
+func (c *handshakerServiceClient) DoHandshake(ctx context.Context, opts ...grpc.CallOption) (HandshakerService_DoHandshakeClient, error) {
1012
+	stream, err := c.cc.NewStream(ctx, &_HandshakerService_serviceDesc.Streams[0], "/grpc.gcp.HandshakerService/DoHandshake", opts...)
1013
+	if err != nil {
1014
+		return nil, err
1015
+	}
1016
+	x := &handshakerServiceDoHandshakeClient{stream}
1017
+	return x, nil
1018
+}
1019
+
1020
+type HandshakerService_DoHandshakeClient interface {
1021
+	Send(*HandshakerReq) error
1022
+	Recv() (*HandshakerResp, error)
1023
+	grpc.ClientStream
1024
+}
1025
+
1026
+type handshakerServiceDoHandshakeClient struct {
1027
+	grpc.ClientStream
1028
+}
1029
+
1030
+func (x *handshakerServiceDoHandshakeClient) Send(m *HandshakerReq) error {
1031
+	return x.ClientStream.SendMsg(m)
1032
+}
1033
+
1034
+func (x *handshakerServiceDoHandshakeClient) Recv() (*HandshakerResp, error) {
1035
+	m := new(HandshakerResp)
1036
+	if err := x.ClientStream.RecvMsg(m); err != nil {
1037
+		return nil, err
1038
+	}
1039
+	return m, nil
1040
+}
1041
+
1042
+// HandshakerServiceServer is the server API for HandshakerService service.
1043
+type HandshakerServiceServer interface {
1044
+	// Handshaker service accepts a stream of handshaker request, returning a
1045
+	// stream of handshaker response. Client is expected to send exactly one
1046
+	// message with either client_start or server_start followed by one or more
1047
+	// messages with next. Each time client sends a request, the handshaker
1048
+	// service expects to respond. Client does not have to wait for service's
1049
+	// response before sending next request.
1050
+	DoHandshake(HandshakerService_DoHandshakeServer) error
1051
+}
1052
+
1053
+// UnimplementedHandshakerServiceServer can be embedded to have forward compatible implementations.
1054
+type UnimplementedHandshakerServiceServer struct {
1055
+}
1056
+
1057
+func (*UnimplementedHandshakerServiceServer) DoHandshake(srv HandshakerService_DoHandshakeServer) error {
1058
+	return status.Errorf(codes.Unimplemented, "method DoHandshake not implemented")
1059
+}
1060
+
1061
+func RegisterHandshakerServiceServer(s *grpc.Server, srv HandshakerServiceServer) {
1062
+	s.RegisterService(&_HandshakerService_serviceDesc, srv)
1063
+}
1064
+
1065
+func _HandshakerService_DoHandshake_Handler(srv interface{}, stream grpc.ServerStream) error {
1066
+	return srv.(HandshakerServiceServer).DoHandshake(&handshakerServiceDoHandshakeServer{stream})
1067
+}
1068
+
1069
+type HandshakerService_DoHandshakeServer interface {
1070
+	Send(*HandshakerResp) error
1071
+	Recv() (*HandshakerReq, error)
1072
+	grpc.ServerStream
1073
+}
1074
+
1075
+type handshakerServiceDoHandshakeServer struct {
1076
+	grpc.ServerStream
1077
+}
1078
+
1079
+func (x *handshakerServiceDoHandshakeServer) Send(m *HandshakerResp) error {
1080
+	return x.ServerStream.SendMsg(m)
1081
+}
1082
+
1083
+func (x *handshakerServiceDoHandshakeServer) Recv() (*HandshakerReq, error) {
1084
+	m := new(HandshakerReq)
1085
+	if err := x.ServerStream.RecvMsg(m); err != nil {
1086
+		return nil, err
1087
+	}
1088
+	return m, nil
1089
+}
1090
+
1091
+var _HandshakerService_serviceDesc = grpc.ServiceDesc{
1092
+	ServiceName: "grpc.gcp.HandshakerService",
1093
+	HandlerType: (*HandshakerServiceServer)(nil),
1094
+	Methods:     []grpc.MethodDesc{},
1095
+	Streams: []grpc.StreamDesc{
1096
+		{
1097
+			StreamName:    "DoHandshake",
1098
+			Handler:       _HandshakerService_DoHandshake_Handler,
1099
+			ServerStreams: true,
1100
+			ClientStreams: true,
1101
+		},
1102
+	},
1103
+	Metadata: "grpc/gcp/handshaker.proto",
1104
+}
0 1105
new file mode 100644
... ...
@@ -0,0 +1,184 @@
0
+// Code generated by protoc-gen-go. DO NOT EDIT.
1
+// source: grpc/gcp/transport_security_common.proto
2
+
3
+package grpc_gcp
4
+
5
+import (
6
+	fmt "fmt"
7
+	proto "github.com/golang/protobuf/proto"
8
+	math "math"
9
+)
10
+
11
+// Reference imports to suppress errors if they are not otherwise used.
12
+var _ = proto.Marshal
13
+var _ = fmt.Errorf
14
+var _ = math.Inf
15
+
16
+// This is a compile-time assertion to ensure that this generated file
17
+// is compatible with the proto package it is being compiled against.
18
+// A compilation error at this line likely means your copy of the
19
+// proto package needs to be updated.
20
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
21
+
22
+// The security level of the created channel. The list is sorted in increasing
23
+// level of security. This order must always be maintained.
24
+type SecurityLevel int32
25
+
26
+const (
27
+	SecurityLevel_SECURITY_NONE         SecurityLevel = 0
28
+	SecurityLevel_INTEGRITY_ONLY        SecurityLevel = 1
29
+	SecurityLevel_INTEGRITY_AND_PRIVACY SecurityLevel = 2
30
+)
31
+
32
+var SecurityLevel_name = map[int32]string{
33
+	0: "SECURITY_NONE",
34
+	1: "INTEGRITY_ONLY",
35
+	2: "INTEGRITY_AND_PRIVACY",
36
+}
37
+
38
+var SecurityLevel_value = map[string]int32{
39
+	"SECURITY_NONE":         0,
40
+	"INTEGRITY_ONLY":        1,
41
+	"INTEGRITY_AND_PRIVACY": 2,
42
+}
43
+
44
+func (x SecurityLevel) String() string {
45
+	return proto.EnumName(SecurityLevel_name, int32(x))
46
+}
47
+
48
+func (SecurityLevel) EnumDescriptor() ([]byte, []int) {
49
+	return fileDescriptor_b97e31e3cc23582a, []int{0}
50
+}
51
+
52
+// Max and min supported RPC protocol versions.
53
+type RpcProtocolVersions struct {
54
+	// Maximum supported RPC version.
55
+	MaxRpcVersion *RpcProtocolVersions_Version `protobuf:"bytes,1,opt,name=max_rpc_version,json=maxRpcVersion,proto3" json:"max_rpc_version,omitempty"`
56
+	// Minimum supported RPC version.
57
+	MinRpcVersion        *RpcProtocolVersions_Version `protobuf:"bytes,2,opt,name=min_rpc_version,json=minRpcVersion,proto3" json:"min_rpc_version,omitempty"`
58
+	XXX_NoUnkeyedLiteral struct{}                     `json:"-"`
59
+	XXX_unrecognized     []byte                       `json:"-"`
60
+	XXX_sizecache        int32                        `json:"-"`
61
+}
62
+
63
+func (m *RpcProtocolVersions) Reset()         { *m = RpcProtocolVersions{} }
64
+func (m *RpcProtocolVersions) String() string { return proto.CompactTextString(m) }
65
+func (*RpcProtocolVersions) ProtoMessage()    {}
66
+func (*RpcProtocolVersions) Descriptor() ([]byte, []int) {
67
+	return fileDescriptor_b97e31e3cc23582a, []int{0}
68
+}
69
+
70
+func (m *RpcProtocolVersions) XXX_Unmarshal(b []byte) error {
71
+	return xxx_messageInfo_RpcProtocolVersions.Unmarshal(m, b)
72
+}
73
+func (m *RpcProtocolVersions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
74
+	return xxx_messageInfo_RpcProtocolVersions.Marshal(b, m, deterministic)
75
+}
76
+func (m *RpcProtocolVersions) XXX_Merge(src proto.Message) {
77
+	xxx_messageInfo_RpcProtocolVersions.Merge(m, src)
78
+}
79
+func (m *RpcProtocolVersions) XXX_Size() int {
80
+	return xxx_messageInfo_RpcProtocolVersions.Size(m)
81
+}
82
+func (m *RpcProtocolVersions) XXX_DiscardUnknown() {
83
+	xxx_messageInfo_RpcProtocolVersions.DiscardUnknown(m)
84
+}
85
+
86
+var xxx_messageInfo_RpcProtocolVersions proto.InternalMessageInfo
87
+
88
+func (m *RpcProtocolVersions) GetMaxRpcVersion() *RpcProtocolVersions_Version {
89
+	if m != nil {
90
+		return m.MaxRpcVersion
91
+	}
92
+	return nil
93
+}
94
+
95
+func (m *RpcProtocolVersions) GetMinRpcVersion() *RpcProtocolVersions_Version {
96
+	if m != nil {
97
+		return m.MinRpcVersion
98
+	}
99
+	return nil
100
+}
101
+
102
+// RPC version contains a major version and a minor version.
103
+type RpcProtocolVersions_Version struct {
104
+	Major                uint32   `protobuf:"varint,1,opt,name=major,proto3" json:"major,omitempty"`
105
+	Minor                uint32   `protobuf:"varint,2,opt,name=minor,proto3" json:"minor,omitempty"`
106
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
107
+	XXX_unrecognized     []byte   `json:"-"`
108
+	XXX_sizecache        int32    `json:"-"`
109
+}
110
+
111
+func (m *RpcProtocolVersions_Version) Reset()         { *m = RpcProtocolVersions_Version{} }
112
+func (m *RpcProtocolVersions_Version) String() string { return proto.CompactTextString(m) }
113
+func (*RpcProtocolVersions_Version) ProtoMessage()    {}
114
+func (*RpcProtocolVersions_Version) Descriptor() ([]byte, []int) {
115
+	return fileDescriptor_b97e31e3cc23582a, []int{0, 0}
116
+}
117
+
118
+func (m *RpcProtocolVersions_Version) XXX_Unmarshal(b []byte) error {
119
+	return xxx_messageInfo_RpcProtocolVersions_Version.Unmarshal(m, b)
120
+}
121
+func (m *RpcProtocolVersions_Version) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
122
+	return xxx_messageInfo_RpcProtocolVersions_Version.Marshal(b, m, deterministic)
123
+}
124
+func (m *RpcProtocolVersions_Version) XXX_Merge(src proto.Message) {
125
+	xxx_messageInfo_RpcProtocolVersions_Version.Merge(m, src)
126
+}
127
+func (m *RpcProtocolVersions_Version) XXX_Size() int {
128
+	return xxx_messageInfo_RpcProtocolVersions_Version.Size(m)
129
+}
130
+func (m *RpcProtocolVersions_Version) XXX_DiscardUnknown() {
131
+	xxx_messageInfo_RpcProtocolVersions_Version.DiscardUnknown(m)
132
+}
133
+
134
+var xxx_messageInfo_RpcProtocolVersions_Version proto.InternalMessageInfo
135
+
136
+func (m *RpcProtocolVersions_Version) GetMajor() uint32 {
137
+	if m != nil {
138
+		return m.Major
139
+	}
140
+	return 0
141
+}
142
+
143
+func (m *RpcProtocolVersions_Version) GetMinor() uint32 {
144
+	if m != nil {
145
+		return m.Minor
146
+	}
147
+	return 0
148
+}
149
+
150
+func init() {
151
+	proto.RegisterEnum("grpc.gcp.SecurityLevel", SecurityLevel_name, SecurityLevel_value)
152
+	proto.RegisterType((*RpcProtocolVersions)(nil), "grpc.gcp.RpcProtocolVersions")
153
+	proto.RegisterType((*RpcProtocolVersions_Version)(nil), "grpc.gcp.RpcProtocolVersions.Version")
154
+}
155
+
156
+func init() {
157
+	proto.RegisterFile("grpc/gcp/transport_security_common.proto", fileDescriptor_b97e31e3cc23582a)
158
+}
159
+
160
+var fileDescriptor_b97e31e3cc23582a = []byte{
161
+	// 323 bytes of a gzipped FileDescriptorProto
162
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0x41, 0x4b, 0x3b, 0x31,
163
+	0x10, 0xc5, 0xff, 0x5b, 0xf8, 0xab, 0x44, 0x56, 0xeb, 0x6a, 0x41, 0xc5, 0x83, 0x08, 0x42, 0xf1,
164
+	0x90, 0x05, 0xc5, 0xb3, 0xb4, 0xb5, 0x48, 0xa1, 0x6e, 0xeb, 0xb6, 0x16, 0xea, 0x25, 0xc4, 0x18,
165
+	0x42, 0x24, 0x9b, 0x09, 0xb3, 0xb1, 0xd4, 0xaf, 0xec, 0xa7, 0x90, 0x4d, 0xbb, 0x14, 0xc1, 0x8b,
166
+	0xb7, 0xbc, 0xc7, 0xcc, 0x6f, 0x32, 0xf3, 0x48, 0x5b, 0xa1, 0x13, 0xa9, 0x12, 0x2e, 0xf5, 0xc8,
167
+	0x6d, 0xe9, 0x00, 0x3d, 0x2b, 0xa5, 0xf8, 0x40, 0xed, 0x3f, 0x99, 0x80, 0xa2, 0x00, 0x4b, 0x1d,
168
+	0x82, 0x87, 0x64, 0xa7, 0xaa, 0xa4, 0x4a, 0xb8, 0x8b, 0xaf, 0x88, 0x1c, 0xe6, 0x4e, 0x8c, 0x2b,
169
+	0x5b, 0x80, 0x99, 0x49, 0x2c, 0x35, 0xd8, 0x32, 0x79, 0x24, 0xfb, 0x05, 0x5f, 0x32, 0x74, 0x82,
170
+	0x2d, 0x56, 0xde, 0x71, 0x74, 0x1e, 0xb5, 0x77, 0xaf, 0x2f, 0x69, 0xdd, 0x4b, 0x7f, 0xe9, 0xa3,
171
+	0xeb, 0x47, 0x1e, 0x17, 0x7c, 0x99, 0x3b, 0xb1, 0x96, 0x01, 0xa7, 0xed, 0x0f, 0x5c, 0xe3, 0x6f,
172
+	0x38, 0x6d, 0x37, 0xb8, 0xd3, 0x5b, 0xb2, 0x5d, 0x93, 0x8f, 0xc8, 0xff, 0x82, 0xbf, 0x03, 0x86,
173
+	0xef, 0xc5, 0xf9, 0x4a, 0x04, 0x57, 0x5b, 0xc0, 0x30, 0xa5, 0x72, 0x2b, 0x71, 0xf5, 0x44, 0xe2,
174
+	0xc9, 0xfa, 0x1e, 0x43, 0xb9, 0x90, 0x26, 0x39, 0x20, 0xf1, 0xa4, 0xdf, 0x7b, 0xce, 0x07, 0xd3,
175
+	0x39, 0xcb, 0x46, 0x59, 0xbf, 0xf9, 0x2f, 0x49, 0xc8, 0xde, 0x20, 0x9b, 0xf6, 0x1f, 0x82, 0x37,
176
+	0xca, 0x86, 0xf3, 0x66, 0x94, 0x9c, 0x90, 0xd6, 0xc6, 0xeb, 0x64, 0xf7, 0x6c, 0x9c, 0x0f, 0x66,
177
+	0x9d, 0xde, 0xbc, 0xd9, 0xe8, 0x2e, 0x49, 0x4b, 0xc3, 0x6a, 0x07, 0x6e, 0x7c, 0x49, 0xb5, 0xf5,
178
+	0x12, 0x2d, 0x37, 0xdd, 0xb3, 0x69, 0x9d, 0x41, 0x3d, 0xb2, 0x17, 0x12, 0x08, 0x2b, 0x8e, 0xa3,
179
+	0x97, 0x3b, 0x05, 0xa0, 0x8c, 0xa4, 0x0a, 0x0c, 0xb7, 0x8a, 0x02, 0xaa, 0x34, 0xc4, 0x27, 0x50,
180
+	0xbe, 0x49, 0xeb, 0x35, 0x37, 0x65, 0x5a, 0x11, 0xd3, 0x9a, 0x98, 0x86, 0xe8, 0x42, 0x11, 0x53,
181
+	0xc2, 0xbd, 0x6e, 0x05, 0x7d, 0xf3, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x31, 0x14, 0xb4, 0x11, 0xf6,
182
+	0x01, 0x00, 0x00,
183
+}
0 184
new file mode 100644
... ...
@@ -0,0 +1,163 @@
0
+/*
1
+ *
2
+ * Copyright 2018 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+package alts
19
+
20
+import (
21
+	"context"
22
+	"errors"
23
+	"fmt"
24
+	"io"
25
+	"io/ioutil"
26
+	"log"
27
+	"os"
28
+	"os/exec"
29
+	"regexp"
30
+	"runtime"
31
+	"strings"
32
+
33
+	"google.golang.org/grpc/codes"
34
+	"google.golang.org/grpc/peer"
35
+	"google.golang.org/grpc/status"
36
+)
37
+
38
+const (
39
+	linuxProductNameFile     = "/sys/class/dmi/id/product_name"
40
+	windowsCheckCommand      = "powershell.exe"
41
+	windowsCheckCommandArgs  = "Get-WmiObject -Class Win32_BIOS"
42
+	powershellOutputFilter   = "Manufacturer"
43
+	windowsManufacturerRegex = ":(.*)"
44
+)
45
+
46
+type platformError string
47
+
48
+func (k platformError) Error() string {
49
+	return fmt.Sprintf("%s is not supported", string(k))
50
+}
51
+
52
+var (
53
+	// The following two variables will be reassigned in tests.
54
+	runningOS          = runtime.GOOS
55
+	manufacturerReader = func() (io.Reader, error) {
56
+		switch runningOS {
57
+		case "linux":
58
+			return os.Open(linuxProductNameFile)
59
+		case "windows":
60
+			cmd := exec.Command(windowsCheckCommand, windowsCheckCommandArgs)
61
+			out, err := cmd.Output()
62
+			if err != nil {
63
+				return nil, err
64
+			}
65
+
66
+			for _, line := range strings.Split(strings.TrimSuffix(string(out), "\n"), "\n") {
67
+				if strings.HasPrefix(line, powershellOutputFilter) {
68
+					re := regexp.MustCompile(windowsManufacturerRegex)
69
+					name := re.FindString(line)
70
+					name = strings.TrimLeft(name, ":")
71
+					return strings.NewReader(name), nil
72
+				}
73
+			}
74
+
75
+			return nil, errors.New("cannot determine the machine's manufacturer")
76
+		default:
77
+			return nil, platformError(runningOS)
78
+		}
79
+	}
80
+	vmOnGCP bool
81
+)
82
+
83
+// isRunningOnGCP checks whether the local system, without doing a network request is
84
+// running on GCP.
85
+func isRunningOnGCP() bool {
86
+	manufacturer, err := readManufacturer()
87
+	if os.IsNotExist(err) {
88
+		return false
89
+	}
90
+	if err != nil {
91
+		log.Fatalf("failure to read manufacturer information: %v", err)
92
+	}
93
+	name := string(manufacturer)
94
+	switch runningOS {
95
+	case "linux":
96
+		name = strings.TrimSpace(name)
97
+		return name == "Google" || name == "Google Compute Engine"
98
+	case "windows":
99
+		name = strings.Replace(name, " ", "", -1)
100
+		name = strings.Replace(name, "\n", "", -1)
101
+		name = strings.Replace(name, "\r", "", -1)
102
+		return name == "Google"
103
+	default:
104
+		log.Fatal(platformError(runningOS))
105
+	}
106
+	return false
107
+}
108
+
109
+func readManufacturer() ([]byte, error) {
110
+	reader, err := manufacturerReader()
111
+	if err != nil {
112
+		return nil, err
113
+	}
114
+	if reader == nil {
115
+		return nil, errors.New("got nil reader")
116
+	}
117
+	manufacturer, err := ioutil.ReadAll(reader)
118
+	if err != nil {
119
+		return nil, fmt.Errorf("failed reading %v: %v", linuxProductNameFile, err)
120
+	}
121
+	return manufacturer, nil
122
+}
123
+
124
+// AuthInfoFromContext extracts the alts.AuthInfo object from the given context,
125
+// if it exists. This API should be used by gRPC server RPC handlers to get
126
+// information about the communicating peer. For client-side, use grpc.Peer()
127
+// CallOption.
128
+func AuthInfoFromContext(ctx context.Context) (AuthInfo, error) {
129
+	p, ok := peer.FromContext(ctx)
130
+	if !ok {
131
+		return nil, errors.New("no Peer found in Context")
132
+	}
133
+	return AuthInfoFromPeer(p)
134
+}
135
+
136
+// AuthInfoFromPeer extracts the alts.AuthInfo object from the given peer, if it
137
+// exists. This API should be used by gRPC clients after obtaining a peer object
138
+// using the grpc.Peer() CallOption.
139
+func AuthInfoFromPeer(p *peer.Peer) (AuthInfo, error) {
140
+	altsAuthInfo, ok := p.AuthInfo.(AuthInfo)
141
+	if !ok {
142
+		return nil, errors.New("no alts.AuthInfo found in Peer")
143
+	}
144
+	return altsAuthInfo, nil
145
+}
146
+
147
+// ClientAuthorizationCheck checks whether the client is authorized to access
148
+// the requested resources based on the given expected client service accounts.
149
+// This API should be used by gRPC server RPC handlers. This API should not be
150
+// used by clients.
151
+func ClientAuthorizationCheck(ctx context.Context, expectedServiceAccounts []string) error {
152
+	authInfo, err := AuthInfoFromContext(ctx)
153
+	if err != nil {
154
+		return status.Newf(codes.PermissionDenied, "The context is not an ALTS-compatible context: %v", err).Err()
155
+	}
156
+	for _, sa := range expectedServiceAccounts {
157
+		if authInfo.PeerServiceAccount() == sa {
158
+			return nil
159
+		}
160
+	}
161
+	return status.Newf(codes.PermissionDenied, "Client %v is not authorized", authInfo.PeerServiceAccount()).Err()
162
+}
0 163
new file mode 100644
... ...
@@ -0,0 +1,125 @@
0
+/*
1
+ *
2
+ * Copyright 2018 gRPC authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+// Package google defines credentials for google cloud services.
19
+package google
20
+
21
+import (
22
+	"context"
23
+	"fmt"
24
+	"time"
25
+
26
+	"google.golang.org/grpc/credentials"
27
+	"google.golang.org/grpc/credentials/alts"
28
+	"google.golang.org/grpc/credentials/oauth"
29
+	"google.golang.org/grpc/grpclog"
30
+	"google.golang.org/grpc/internal"
31
+)
32
+
33
+const tokenRequestTimeout = 30 * time.Second
34
+
35
+// NewDefaultCredentials returns a credentials bundle that is configured to work
36
+// with google services.
37
+//
38
+// This API is experimental.
39
+func NewDefaultCredentials() credentials.Bundle {
40
+	c := &creds{
41
+		newPerRPCCreds: func() credentials.PerRPCCredentials {
42
+			ctx, cancel := context.WithTimeout(context.Background(), tokenRequestTimeout)
43
+			defer cancel()
44
+			perRPCCreds, err := oauth.NewApplicationDefault(ctx)
45
+			if err != nil {
46
+				grpclog.Warningf("google default creds: failed to create application oauth: %v", err)
47
+			}
48
+			return perRPCCreds
49
+		},
50
+	}
51
+	bundle, err := c.NewWithMode(internal.CredsBundleModeFallback)
52
+	if err != nil {
53
+		grpclog.Warningf("google default creds: failed to create new creds: %v", err)
54
+	}
55
+	return bundle
56
+}
57
+
58
+// NewComputeEngineCredentials returns a credentials bundle that is configured to work
59
+// with google services. This API must only be used when running on GCE. Authentication configured
60
+// by this API represents the GCE VM's default service account.
61
+//
62
+// This API is experimental.
63
+func NewComputeEngineCredentials() credentials.Bundle {
64
+	c := &creds{
65
+		newPerRPCCreds: func() credentials.PerRPCCredentials {
66
+			return oauth.NewComputeEngine()
67
+		},
68
+	}
69
+	bundle, err := c.NewWithMode(internal.CredsBundleModeFallback)
70
+	if err != nil {
71
+		grpclog.Warningf("compute engine creds: failed to create new creds: %v", err)
72
+	}
73
+	return bundle
74
+}
75
+
76
+// creds implements credentials.Bundle.
77
+type creds struct {
78
+	// Supported modes are defined in internal/internal.go.
79
+	mode string
80
+	// The transport credentials associated with this bundle.
81
+	transportCreds credentials.TransportCredentials
82
+	// The per RPC credentials associated with this bundle.
83
+	perRPCCreds credentials.PerRPCCredentials
84
+	// Creates new per RPC credentials
85
+	newPerRPCCreds func() credentials.PerRPCCredentials
86
+}
87
+
88
+func (c *creds) TransportCredentials() credentials.TransportCredentials {
89
+	return c.transportCreds
90
+}
91
+
92
+func (c *creds) PerRPCCredentials() credentials.PerRPCCredentials {
93
+	if c == nil {
94
+		return nil
95
+	}
96
+	return c.perRPCCreds
97
+}
98
+
99
+// NewWithMode should make a copy of Bundle, and switch mode. Modifying the
100
+// existing Bundle may cause races.
101
+func (c *creds) NewWithMode(mode string) (credentials.Bundle, error) {
102
+	newCreds := &creds{
103
+		mode:           mode,
104
+		newPerRPCCreds: c.newPerRPCCreds,
105
+	}
106
+
107
+	// Create transport credentials.
108
+	switch mode {
109
+	case internal.CredsBundleModeFallback:
110
+		newCreds.transportCreds = credentials.NewTLS(nil)
111
+	case internal.CredsBundleModeBackendFromBalancer, internal.CredsBundleModeBalancer:
112
+		// Only the clients can use google default credentials, so we only need
113
+		// to create new ALTS client creds here.
114
+		newCreds.transportCreds = alts.NewClientCreds(alts.DefaultClientOptions())
115
+	default:
116
+		return nil, fmt.Errorf("unsupported mode: %v", mode)
117
+	}
118
+
119
+	if mode == internal.CredsBundleModeFallback || mode == internal.CredsBundleModeBackendFromBalancer {
120
+		newCreds.perRPCCreds = newCreds.newPerRPCCreds()
121
+	}
122
+
123
+	return newCreds, nil
124
+}