full diff: https://github.com/googleapis/google-api-go-client/compare/de943baf05a022a8f921b544b7827bacaba1aed5...v0.8.0
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
... | ... |
@@ -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 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 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 = ×tamppb.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 |
+} |