feat: gitea client
This commit is contained in:
1
vendor/google.golang.org/grpc/AUTHORS
generated
vendored
Normal file
1
vendor/google.golang.org/grpc/AUTHORS
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Google Inc.
|
||||
3
vendor/google.golang.org/grpc/CODE-OF-CONDUCT.md
generated
vendored
Normal file
3
vendor/google.golang.org/grpc/CODE-OF-CONDUCT.md
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
## Community Code of Conduct
|
||||
|
||||
gRPC follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
|
||||
73
vendor/google.golang.org/grpc/CONTRIBUTING.md
generated
vendored
Normal file
73
vendor/google.golang.org/grpc/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
# How to contribute
|
||||
|
||||
We definitely welcome your patches and contributions to gRPC! Please read the gRPC
|
||||
organization's [governance rules](https://github.com/grpc/grpc-community/blob/master/governance.md)
|
||||
and [contribution guidelines](https://github.com/grpc/grpc-community/blob/master/CONTRIBUTING.md) before proceeding.
|
||||
|
||||
If you are new to github, please start by reading [Pull Request howto](https://help.github.com/articles/about-pull-requests/)
|
||||
|
||||
## Legal requirements
|
||||
|
||||
In order to protect both you and ourselves, you will need to sign the
|
||||
[Contributor License Agreement](https://identity.linuxfoundation.org/projects/cncf).
|
||||
|
||||
## Guidelines for Pull Requests
|
||||
How to get your contributions merged smoothly and quickly.
|
||||
|
||||
- Create **small PRs** that are narrowly focused on **addressing a single
|
||||
concern**. We often times receive PRs that are trying to fix several things at
|
||||
a time, but only one fix is considered acceptable, nothing gets merged and
|
||||
both author's & review's time is wasted. Create more PRs to address different
|
||||
concerns and everyone will be happy.
|
||||
|
||||
- If you are searching for features to work on, issues labeled [Status: Help
|
||||
Wanted](https://github.com/grpc/grpc-go/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22Status%3A+Help+Wanted%22)
|
||||
is a great place to start. These issues are well-documented and usually can be
|
||||
resolved with a single pull request.
|
||||
|
||||
- If you are adding a new file, make sure it has the copyright message template
|
||||
at the top as a comment. You can copy over the message from an existing file
|
||||
and update the year.
|
||||
|
||||
- The grpc package should only depend on standard Go packages and a small number
|
||||
of exceptions. If your contribution introduces new dependencies which are NOT
|
||||
in the [list](https://godoc.org/google.golang.org/grpc?imports), you need a
|
||||
discussion with gRPC-Go authors and consultants.
|
||||
|
||||
- For speculative changes, consider opening an issue and discussing it first. If
|
||||
you are suggesting a behavioral or API change, consider starting with a [gRFC
|
||||
proposal](https://github.com/grpc/proposal).
|
||||
|
||||
- Provide a good **PR description** as a record of **what** change is being made
|
||||
and **why** it was made. Link to a github issue if it exists.
|
||||
|
||||
- If you want to fix formatting or style, consider whether your changes are an
|
||||
obvious improvement or might be considered a personal preference. If a style
|
||||
change is based on preference, it likely will not be accepted. If it corrects
|
||||
widely agreed-upon anti-patterns, then please do create a PR and explain the
|
||||
benefits of the change.
|
||||
|
||||
- Unless your PR is trivial, you should expect there will be reviewer comments
|
||||
that you'll need to address before merging. We'll mark it as `Status: Requires
|
||||
Reporter Clarification` if we expect you to respond to these comments in a
|
||||
timely manner. If the PR remains inactive for 6 days, it will be marked as
|
||||
`stale` and automatically close 7 days after that if we don't hear back from
|
||||
you.
|
||||
|
||||
- Maintain **clean commit history** and use **meaningful commit messages**. PRs
|
||||
with messy commit history are difficult to review and won't be merged. Use
|
||||
`rebase -i upstream/master` to curate your commit history and/or to bring in
|
||||
latest changes from master (but avoid rebasing in the middle of a code
|
||||
review).
|
||||
|
||||
- Keep your PR up to date with upstream/master (if there are merge conflicts, we
|
||||
can't really merge your change).
|
||||
|
||||
- **All tests need to be passing** before your change can be merged. We
|
||||
recommend you **run tests locally** before creating your PR to catch breakages
|
||||
early on.
|
||||
- `./scripts/vet.sh` to catch vet errors
|
||||
- `go test -cpu 1,4 -timeout 7m ./...` to run the tests
|
||||
- `go test -race -cpu 1,4 -timeout 7m ./...` to run tests in race mode
|
||||
|
||||
- Exceptions to the rules can be made if there's a compelling reason for doing so.
|
||||
1
vendor/google.golang.org/grpc/GOVERNANCE.md
generated
vendored
Normal file
1
vendor/google.golang.org/grpc/GOVERNANCE.md
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
This repository is governed by the gRPC organization's [governance rules](https://github.com/grpc/grpc-community/blob/master/governance.md).
|
||||
202
vendor/google.golang.org/grpc/LICENSE
generated
vendored
Normal file
202
vendor/google.golang.org/grpc/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
29
vendor/google.golang.org/grpc/MAINTAINERS.md
generated
vendored
Normal file
29
vendor/google.golang.org/grpc/MAINTAINERS.md
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
This page lists all active maintainers of this repository. If you were a
|
||||
maintainer and would like to add your name to the Emeritus list, please send us a
|
||||
PR.
|
||||
|
||||
See [GOVERNANCE.md](https://github.com/grpc/grpc-community/blob/master/governance.md)
|
||||
for governance guidelines and how to become a maintainer.
|
||||
See [CONTRIBUTING.md](https://github.com/grpc/grpc-community/blob/master/CONTRIBUTING.md)
|
||||
for general contribution guidelines.
|
||||
|
||||
## Maintainers (in alphabetical order)
|
||||
|
||||
- [atollena](https://github.com/atollena), Datadog, Inc.
|
||||
- [cesarghali](https://github.com/cesarghali), Google LLC
|
||||
- [dfawley](https://github.com/dfawley), Google LLC
|
||||
- [easwars](https://github.com/easwars), Google LLC
|
||||
- [menghanl](https://github.com/menghanl), Google LLC
|
||||
- [srini100](https://github.com/srini100), Google LLC
|
||||
|
||||
## Emeritus Maintainers (in alphabetical order)
|
||||
- [adelez](https://github.com/adelez), Google LLC
|
||||
- [canguler](https://github.com/canguler), Google LLC
|
||||
- [iamqizhao](https://github.com/iamqizhao), Google LLC
|
||||
- [jadekler](https://github.com/jadekler), Google LLC
|
||||
- [jtattermusch](https://github.com/jtattermusch), Google LLC
|
||||
- [lyuxuan](https://github.com/lyuxuan), Google LLC
|
||||
- [makmukhi](https://github.com/makmukhi), Google LLC
|
||||
- [matt-kwong](https://github.com/matt-kwong), Google LLC
|
||||
- [nicolasnoble](https://github.com/nicolasnoble), Google LLC
|
||||
- [yongni](https://github.com/yongni), Google LLC
|
||||
49
vendor/google.golang.org/grpc/Makefile
generated
vendored
Normal file
49
vendor/google.golang.org/grpc/Makefile
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
all: vet test testrace
|
||||
|
||||
build:
|
||||
go build google.golang.org/grpc/...
|
||||
|
||||
clean:
|
||||
go clean -i google.golang.org/grpc/...
|
||||
|
||||
deps:
|
||||
GO111MODULE=on go get -d -v google.golang.org/grpc/...
|
||||
|
||||
proto:
|
||||
@ if ! which protoc > /dev/null; then \
|
||||
echo "error: protoc not installed" >&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
go generate google.golang.org/grpc/...
|
||||
|
||||
test:
|
||||
go test -cpu 1,4 -timeout 7m google.golang.org/grpc/...
|
||||
|
||||
testsubmodule:
|
||||
cd security/advancedtls && go test -cpu 1,4 -timeout 7m google.golang.org/grpc/security/advancedtls/...
|
||||
cd security/authorization && go test -cpu 1,4 -timeout 7m google.golang.org/grpc/security/authorization/...
|
||||
|
||||
testrace:
|
||||
go test -race -cpu 1,4 -timeout 7m google.golang.org/grpc/...
|
||||
|
||||
testdeps:
|
||||
GO111MODULE=on go get -d -v -t google.golang.org/grpc/...
|
||||
|
||||
vet: vetdeps
|
||||
./scripts/vet.sh
|
||||
|
||||
vetdeps:
|
||||
./scripts/vet.sh -install
|
||||
|
||||
.PHONY: \
|
||||
all \
|
||||
build \
|
||||
clean \
|
||||
deps \
|
||||
proto \
|
||||
test \
|
||||
testsubmodule \
|
||||
testrace \
|
||||
testdeps \
|
||||
vet \
|
||||
vetdeps
|
||||
13
vendor/google.golang.org/grpc/NOTICE.txt
generated
vendored
Normal file
13
vendor/google.golang.org/grpc/NOTICE.txt
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
Copyright 2014 gRPC authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
107
vendor/google.golang.org/grpc/README.md
generated
vendored
Normal file
107
vendor/google.golang.org/grpc/README.md
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
# gRPC-Go
|
||||
|
||||
[][API]
|
||||
[](https://goreportcard.com/report/github.com/grpc/grpc-go)
|
||||
[](https://codecov.io/gh/grpc/grpc-go)
|
||||
|
||||
The [Go][] implementation of [gRPC][]: A high performance, open source, general
|
||||
RPC framework that puts mobile and HTTP/2 first. For more information see the
|
||||
[Go gRPC docs][], or jump directly into the [quick start][].
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **[Go][]**: any one of the **three latest major** [releases][go-releases].
|
||||
|
||||
## Installation
|
||||
|
||||
Simply add the following import to your code, and then `go [build|run|test]`
|
||||
will automatically fetch the necessary dependencies:
|
||||
|
||||
|
||||
```go
|
||||
import "google.golang.org/grpc"
|
||||
```
|
||||
|
||||
> **Note:** If you are trying to access `grpc-go` from **China**, see the
|
||||
> [FAQ](#FAQ) below.
|
||||
|
||||
## Learn more
|
||||
|
||||
- [Go gRPC docs][], which include a [quick start][] and [API
|
||||
reference][API] among other resources
|
||||
- [Low-level technical docs](Documentation) from this repository
|
||||
- [Performance benchmark][]
|
||||
- [Examples](examples)
|
||||
|
||||
## FAQ
|
||||
|
||||
### I/O Timeout Errors
|
||||
|
||||
The `golang.org` domain may be blocked from some countries. `go get` usually
|
||||
produces an error like the following when this happens:
|
||||
|
||||
```console
|
||||
$ go get -u google.golang.org/grpc
|
||||
package google.golang.org/grpc: unrecognized import path "google.golang.org/grpc" (https fetch: Get https://google.golang.org/grpc?go-get=1: dial tcp 216.239.37.1:443: i/o timeout)
|
||||
```
|
||||
|
||||
To build Go code, there are several options:
|
||||
|
||||
- Set up a VPN and access google.golang.org through that.
|
||||
|
||||
- With Go module support: it is possible to use the `replace` feature of `go
|
||||
mod` to create aliases for golang.org packages. In your project's directory:
|
||||
|
||||
```sh
|
||||
go mod edit -replace=google.golang.org/grpc=github.com/grpc/grpc-go@latest
|
||||
go mod tidy
|
||||
go mod vendor
|
||||
go build -mod=vendor
|
||||
```
|
||||
|
||||
Again, this will need to be done for all transitive dependencies hosted on
|
||||
golang.org as well. For details, refer to [golang/go issue
|
||||
#28652](https://github.com/golang/go/issues/28652).
|
||||
|
||||
### Compiling error, undefined: grpc.SupportPackageIsVersion
|
||||
|
||||
Please update to the latest version of gRPC-Go using
|
||||
`go get google.golang.org/grpc`.
|
||||
|
||||
### How to turn on logging
|
||||
|
||||
The default logger is controlled by environment variables. Turn everything on
|
||||
like this:
|
||||
|
||||
```console
|
||||
$ export GRPC_GO_LOG_VERBOSITY_LEVEL=99
|
||||
$ export GRPC_GO_LOG_SEVERITY_LEVEL=info
|
||||
```
|
||||
|
||||
### The RPC failed with error `"code = Unavailable desc = transport is closing"`
|
||||
|
||||
This error means the connection the RPC is using was closed, and there are many
|
||||
possible reasons, including:
|
||||
1. mis-configured transport credentials, connection failed on handshaking
|
||||
1. bytes disrupted, possibly by a proxy in between
|
||||
1. server shutdown
|
||||
1. Keepalive parameters caused connection shutdown, for example if you have
|
||||
configured your server to terminate connections regularly to [trigger DNS
|
||||
lookups](https://github.com/grpc/grpc-go/issues/3170#issuecomment-552517779).
|
||||
If this is the case, you may want to increase your
|
||||
[MaxConnectionAgeGrace](https://pkg.go.dev/google.golang.org/grpc/keepalive?tab=doc#ServerParameters),
|
||||
to allow longer RPC calls to finish.
|
||||
|
||||
It can be tricky to debug this because the error happens on the client side but
|
||||
the root cause of the connection being closed is on the server side. Turn on
|
||||
logging on __both client and server__, and see if there are any transport
|
||||
errors.
|
||||
|
||||
[API]: https://pkg.go.dev/google.golang.org/grpc
|
||||
[Go]: https://golang.org
|
||||
[Go module]: https://github.com/golang/go/wiki/Modules
|
||||
[gRPC]: https://grpc.io
|
||||
[Go gRPC docs]: https://grpc.io/docs/languages/go
|
||||
[Performance benchmark]: https://performance-dot-grpc-testing.appspot.com/explore?dashboard=5180705743044608
|
||||
[quick start]: https://grpc.io/docs/languages/go/quickstart
|
||||
[go-releases]: https://golang.org/doc/devel/release.html
|
||||
3
vendor/google.golang.org/grpc/SECURITY.md
generated
vendored
Normal file
3
vendor/google.golang.org/grpc/SECURITY.md
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Security Policy
|
||||
|
||||
For information on gRPC Security Policy and reporting potentional security issues, please see [gRPC CVE Process](https://github.com/grpc/proposal/blob/master/P4-grpc-cve-process.md).
|
||||
141
vendor/google.golang.org/grpc/attributes/attributes.go
generated
vendored
Normal file
141
vendor/google.golang.org/grpc/attributes/attributes.go
generated
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2019 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package attributes defines a generic key/value store used in various gRPC
|
||||
// components.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This package is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
package attributes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Attributes is an immutable struct for storing and retrieving generic
|
||||
// key/value pairs. Keys must be hashable, and users should define their own
|
||||
// types for keys. Values should not be modified after they are added to an
|
||||
// Attributes or if they were received from one. If values implement 'Equal(o
|
||||
// any) bool', it will be called by (*Attributes).Equal to determine whether
|
||||
// two values with the same key should be considered equal.
|
||||
type Attributes struct {
|
||||
m map[any]any
|
||||
}
|
||||
|
||||
// New returns a new Attributes containing the key/value pair.
|
||||
func New(key, value any) *Attributes {
|
||||
return &Attributes{m: map[any]any{key: value}}
|
||||
}
|
||||
|
||||
// WithValue returns a new Attributes containing the previous keys and values
|
||||
// and the new key/value pair. If the same key appears multiple times, the
|
||||
// last value overwrites all previous values for that key. To remove an
|
||||
// existing key, use a nil value. value should not be modified later.
|
||||
func (a *Attributes) WithValue(key, value any) *Attributes {
|
||||
if a == nil {
|
||||
return New(key, value)
|
||||
}
|
||||
n := &Attributes{m: make(map[any]any, len(a.m)+1)}
|
||||
for k, v := range a.m {
|
||||
n.m[k] = v
|
||||
}
|
||||
n.m[key] = value
|
||||
return n
|
||||
}
|
||||
|
||||
// Value returns the value associated with these attributes for key, or nil if
|
||||
// no value is associated with key. The returned value should not be modified.
|
||||
func (a *Attributes) Value(key any) any {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
return a.m[key]
|
||||
}
|
||||
|
||||
// Equal returns whether a and o are equivalent. If 'Equal(o any) bool' is
|
||||
// implemented for a value in the attributes, it is called to determine if the
|
||||
// value matches the one stored in the other attributes. If Equal is not
|
||||
// implemented, standard equality is used to determine if the two values are
|
||||
// equal. Note that some types (e.g. maps) aren't comparable by default, so
|
||||
// they must be wrapped in a struct, or in an alias type, with Equal defined.
|
||||
func (a *Attributes) Equal(o *Attributes) bool {
|
||||
if a == nil && o == nil {
|
||||
return true
|
||||
}
|
||||
if a == nil || o == nil {
|
||||
return false
|
||||
}
|
||||
if len(a.m) != len(o.m) {
|
||||
return false
|
||||
}
|
||||
for k, v := range a.m {
|
||||
ov, ok := o.m[k]
|
||||
if !ok {
|
||||
// o missing element of a
|
||||
return false
|
||||
}
|
||||
if eq, ok := v.(interface{ Equal(o any) bool }); ok {
|
||||
if !eq.Equal(ov) {
|
||||
return false
|
||||
}
|
||||
} else if v != ov {
|
||||
// Fallback to a standard equality check if Value is unimplemented.
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// String prints the attribute map. If any key or values throughout the map
|
||||
// implement fmt.Stringer, it calls that method and appends.
|
||||
func (a *Attributes) String() string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString("{")
|
||||
first := true
|
||||
for k, v := range a.m {
|
||||
if !first {
|
||||
sb.WriteString(", ")
|
||||
}
|
||||
sb.WriteString(fmt.Sprintf("%q: %q ", str(k), str(v)))
|
||||
first = false
|
||||
}
|
||||
sb.WriteString("}")
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func str(x any) (s string) {
|
||||
if v, ok := x.(fmt.Stringer); ok {
|
||||
return fmt.Sprint(v)
|
||||
} else if v, ok := x.(string); ok {
|
||||
return v
|
||||
}
|
||||
return fmt.Sprintf("<%p>", x)
|
||||
}
|
||||
|
||||
// MarshalJSON helps implement the json.Marshaler interface, thereby rendering
|
||||
// the Attributes correctly when printing (via pretty.JSON) structs containing
|
||||
// Attributes as fields.
|
||||
//
|
||||
// Is it impossible to unmarshal attributes from a JSON representation and this
|
||||
// method is meant only for debugging purposes.
|
||||
func (a *Attributes) MarshalJSON() ([]byte, error) {
|
||||
return []byte(a.String()), nil
|
||||
}
|
||||
61
vendor/google.golang.org/grpc/backoff.go
generated
vendored
Normal file
61
vendor/google.golang.org/grpc/backoff.go
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// See internal/backoff package for the backoff implementation. This file is
|
||||
// kept for the exported types and API backward compatibility.
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/backoff"
|
||||
)
|
||||
|
||||
// DefaultBackoffConfig uses values specified for backoff in
|
||||
// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md.
|
||||
//
|
||||
// Deprecated: use ConnectParams instead. Will be supported throughout 1.x.
|
||||
var DefaultBackoffConfig = BackoffConfig{
|
||||
MaxDelay: 120 * time.Second,
|
||||
}
|
||||
|
||||
// BackoffConfig defines the parameters for the default gRPC backoff strategy.
|
||||
//
|
||||
// Deprecated: use ConnectParams instead. Will be supported throughout 1.x.
|
||||
type BackoffConfig struct {
|
||||
// MaxDelay is the upper bound of backoff delay.
|
||||
MaxDelay time.Duration
|
||||
}
|
||||
|
||||
// ConnectParams defines the parameters for connecting and retrying. Users are
|
||||
// encouraged to use this instead of the BackoffConfig type defined above. See
|
||||
// here for more details:
|
||||
// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This type is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
type ConnectParams struct {
|
||||
// Backoff specifies the configuration options for connection backoff.
|
||||
Backoff backoff.Config
|
||||
// MinConnectTimeout is the minimum amount of time we are willing to give a
|
||||
// connection to complete.
|
||||
MinConnectTimeout time.Duration
|
||||
}
|
||||
52
vendor/google.golang.org/grpc/backoff/backoff.go
generated
vendored
Normal file
52
vendor/google.golang.org/grpc/backoff/backoff.go
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2019 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package backoff provides configuration options for backoff.
|
||||
//
|
||||
// More details can be found at:
|
||||
// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md.
|
||||
//
|
||||
// All APIs in this package are experimental.
|
||||
package backoff
|
||||
|
||||
import "time"
|
||||
|
||||
// Config defines the configuration options for backoff.
|
||||
type Config struct {
|
||||
// BaseDelay is the amount of time to backoff after the first failure.
|
||||
BaseDelay time.Duration
|
||||
// Multiplier is the factor with which to multiply backoffs after a
|
||||
// failed retry. Should ideally be greater than 1.
|
||||
Multiplier float64
|
||||
// Jitter is the factor with which backoffs are randomized.
|
||||
Jitter float64
|
||||
// MaxDelay is the upper bound of backoff delay.
|
||||
MaxDelay time.Duration
|
||||
}
|
||||
|
||||
// DefaultConfig is a backoff configuration with the default values specfied
|
||||
// at https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md.
|
||||
//
|
||||
// This should be useful for callers who want to configure backoff with
|
||||
// non-default values only for a subset of the options.
|
||||
var DefaultConfig = Config{
|
||||
BaseDelay: 1.0 * time.Second,
|
||||
Multiplier: 1.6,
|
||||
Jitter: 0.2,
|
||||
MaxDelay: 120 * time.Second,
|
||||
}
|
||||
443
vendor/google.golang.org/grpc/balancer/balancer.go
generated
vendored
Normal file
443
vendor/google.golang.org/grpc/balancer/balancer.go
generated
vendored
Normal file
@@ -0,0 +1,443 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package balancer defines APIs for load balancing in gRPC.
|
||||
// All APIs in this package are experimental.
|
||||
package balancer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/grpc/channelz"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/internal"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"google.golang.org/grpc/serviceconfig"
|
||||
)
|
||||
|
||||
var (
|
||||
// m is a map from name to balancer builder.
|
||||
m = make(map[string]Builder)
|
||||
|
||||
logger = grpclog.Component("balancer")
|
||||
)
|
||||
|
||||
// Register registers the balancer builder to the balancer map. b.Name
|
||||
// (lowercased) will be used as the name registered with this builder. If the
|
||||
// Builder implements ConfigParser, ParseConfig will be called when new service
|
||||
// configs are received by the resolver, and the result will be provided to the
|
||||
// Balancer in UpdateClientConnState.
|
||||
//
|
||||
// NOTE: this function must only be called during initialization time (i.e. in
|
||||
// an init() function), and is not thread-safe. If multiple Balancers are
|
||||
// registered with the same name, the one registered last will take effect.
|
||||
func Register(b Builder) {
|
||||
name := strings.ToLower(b.Name())
|
||||
if name != b.Name() {
|
||||
// TODO: Skip the use of strings.ToLower() to index the map after v1.59
|
||||
// is released to switch to case sensitive balancer registry. Also,
|
||||
// remove this warning and update the docstrings for Register and Get.
|
||||
logger.Warningf("Balancer registered with name %q. grpc-go will be switching to case sensitive balancer registries soon", b.Name())
|
||||
}
|
||||
m[name] = b
|
||||
}
|
||||
|
||||
// unregisterForTesting deletes the balancer with the given name from the
|
||||
// balancer map.
|
||||
//
|
||||
// This function is not thread-safe.
|
||||
func unregisterForTesting(name string) {
|
||||
delete(m, name)
|
||||
}
|
||||
|
||||
func init() {
|
||||
internal.BalancerUnregister = unregisterForTesting
|
||||
}
|
||||
|
||||
// Get returns the resolver builder registered with the given name.
|
||||
// Note that the compare is done in a case-insensitive fashion.
|
||||
// If no builder is register with the name, nil will be returned.
|
||||
func Get(name string) Builder {
|
||||
if strings.ToLower(name) != name {
|
||||
// TODO: Skip the use of strings.ToLower() to index the map after v1.59
|
||||
// is released to switch to case sensitive balancer registry. Also,
|
||||
// remove this warning and update the docstrings for Register and Get.
|
||||
logger.Warningf("Balancer retrieved for name %q. grpc-go will be switching to case sensitive balancer registries soon", name)
|
||||
}
|
||||
if b, ok := m[strings.ToLower(name)]; ok {
|
||||
return b
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// A SubConn represents a single connection to a gRPC backend service.
|
||||
//
|
||||
// Each SubConn contains a list of addresses.
|
||||
//
|
||||
// All SubConns start in IDLE, and will not try to connect. To trigger the
|
||||
// connecting, Balancers must call Connect. If a connection re-enters IDLE,
|
||||
// Balancers must call Connect again to trigger a new connection attempt.
|
||||
//
|
||||
// gRPC will try to connect to the addresses in sequence, and stop trying the
|
||||
// remainder once the first connection is successful. If an attempt to connect
|
||||
// to all addresses encounters an error, the SubConn will enter
|
||||
// TRANSIENT_FAILURE for a backoff period, and then transition to IDLE.
|
||||
//
|
||||
// Once established, if a connection is lost, the SubConn will transition
|
||||
// directly to IDLE.
|
||||
//
|
||||
// This interface is to be implemented by gRPC. Users should not need their own
|
||||
// implementation of this interface. For situations like testing, any
|
||||
// implementations should embed this interface. This allows gRPC to add new
|
||||
// methods to this interface.
|
||||
type SubConn interface {
|
||||
// UpdateAddresses updates the addresses used in this SubConn.
|
||||
// gRPC checks if currently-connected address is still in the new list.
|
||||
// If it's in the list, the connection will be kept.
|
||||
// If it's not in the list, the connection will gracefully closed, and
|
||||
// a new connection will be created.
|
||||
//
|
||||
// This will trigger a state transition for the SubConn.
|
||||
//
|
||||
// Deprecated: this method will be removed. Create new SubConns for new
|
||||
// addresses instead.
|
||||
UpdateAddresses([]resolver.Address)
|
||||
// Connect starts the connecting for this SubConn.
|
||||
Connect()
|
||||
// GetOrBuildProducer returns a reference to the existing Producer for this
|
||||
// ProducerBuilder in this SubConn, or, if one does not currently exist,
|
||||
// creates a new one and returns it. Returns a close function which must
|
||||
// be called when the Producer is no longer needed.
|
||||
GetOrBuildProducer(ProducerBuilder) (p Producer, close func())
|
||||
// Shutdown shuts down the SubConn gracefully. Any started RPCs will be
|
||||
// allowed to complete. No future calls should be made on the SubConn.
|
||||
// One final state update will be delivered to the StateListener (or
|
||||
// UpdateSubConnState; deprecated) with ConnectivityState of Shutdown to
|
||||
// indicate the shutdown operation. This may be delivered before
|
||||
// in-progress RPCs are complete and the actual connection is closed.
|
||||
Shutdown()
|
||||
}
|
||||
|
||||
// NewSubConnOptions contains options to create new SubConn.
|
||||
type NewSubConnOptions struct {
|
||||
// CredsBundle is the credentials bundle that will be used in the created
|
||||
// SubConn. If it's nil, the original creds from grpc DialOptions will be
|
||||
// used.
|
||||
//
|
||||
// Deprecated: Use the Attributes field in resolver.Address to pass
|
||||
// arbitrary data to the credential handshaker.
|
||||
CredsBundle credentials.Bundle
|
||||
// HealthCheckEnabled indicates whether health check service should be
|
||||
// enabled on this SubConn
|
||||
HealthCheckEnabled bool
|
||||
// StateListener is called when the state of the subconn changes. If nil,
|
||||
// Balancer.UpdateSubConnState will be called instead. Will never be
|
||||
// invoked until after Connect() is called on the SubConn created with
|
||||
// these options.
|
||||
StateListener func(SubConnState)
|
||||
}
|
||||
|
||||
// State contains the balancer's state relevant to the gRPC ClientConn.
|
||||
type State struct {
|
||||
// State contains the connectivity state of the balancer, which is used to
|
||||
// determine the state of the ClientConn.
|
||||
ConnectivityState connectivity.State
|
||||
// Picker is used to choose connections (SubConns) for RPCs.
|
||||
Picker Picker
|
||||
}
|
||||
|
||||
// ClientConn represents a gRPC ClientConn.
|
||||
//
|
||||
// This interface is to be implemented by gRPC. Users should not need a
|
||||
// brand new implementation of this interface. For the situations like
|
||||
// testing, the new implementation should embed this interface. This allows
|
||||
// gRPC to add new methods to this interface.
|
||||
type ClientConn interface {
|
||||
// NewSubConn is called by balancer to create a new SubConn.
|
||||
// It doesn't block and wait for the connections to be established.
|
||||
// Behaviors of the SubConn can be controlled by options.
|
||||
//
|
||||
// Deprecated: please be aware that in a future version, SubConns will only
|
||||
// support one address per SubConn.
|
||||
NewSubConn([]resolver.Address, NewSubConnOptions) (SubConn, error)
|
||||
// RemoveSubConn removes the SubConn from ClientConn.
|
||||
// The SubConn will be shutdown.
|
||||
//
|
||||
// Deprecated: use SubConn.Shutdown instead.
|
||||
RemoveSubConn(SubConn)
|
||||
// UpdateAddresses updates the addresses used in the passed in SubConn.
|
||||
// gRPC checks if the currently connected address is still in the new list.
|
||||
// If so, the connection will be kept. Else, the connection will be
|
||||
// gracefully closed, and a new connection will be created.
|
||||
//
|
||||
// This may trigger a state transition for the SubConn.
|
||||
//
|
||||
// Deprecated: this method will be removed. Create new SubConns for new
|
||||
// addresses instead.
|
||||
UpdateAddresses(SubConn, []resolver.Address)
|
||||
|
||||
// UpdateState notifies gRPC that the balancer's internal state has
|
||||
// changed.
|
||||
//
|
||||
// gRPC will update the connectivity state of the ClientConn, and will call
|
||||
// Pick on the new Picker to pick new SubConns.
|
||||
UpdateState(State)
|
||||
|
||||
// ResolveNow is called by balancer to notify gRPC to do a name resolving.
|
||||
ResolveNow(resolver.ResolveNowOptions)
|
||||
|
||||
// Target returns the dial target for this ClientConn.
|
||||
//
|
||||
// Deprecated: Use the Target field in the BuildOptions instead.
|
||||
Target() string
|
||||
}
|
||||
|
||||
// BuildOptions contains additional information for Build.
|
||||
type BuildOptions struct {
|
||||
// DialCreds is the transport credentials to use when communicating with a
|
||||
// remote load balancer server. Balancer implementations which do not
|
||||
// communicate with a remote load balancer server can ignore this field.
|
||||
DialCreds credentials.TransportCredentials
|
||||
// CredsBundle is the credentials bundle to use when communicating with a
|
||||
// remote load balancer server. Balancer implementations which do not
|
||||
// communicate with a remote load balancer server can ignore this field.
|
||||
CredsBundle credentials.Bundle
|
||||
// Dialer is the custom dialer to use when communicating with a remote load
|
||||
// balancer server. Balancer implementations which do not communicate with a
|
||||
// remote load balancer server can ignore this field.
|
||||
Dialer func(context.Context, string) (net.Conn, error)
|
||||
// Authority is the server name to use as part of the authentication
|
||||
// handshake when communicating with a remote load balancer server. Balancer
|
||||
// implementations which do not communicate with a remote load balancer
|
||||
// server can ignore this field.
|
||||
Authority string
|
||||
// ChannelzParent is the parent ClientConn's channelz channel.
|
||||
ChannelzParent channelz.Identifier
|
||||
// CustomUserAgent is the custom user agent set on the parent ClientConn.
|
||||
// The balancer should set the same custom user agent if it creates a
|
||||
// ClientConn.
|
||||
CustomUserAgent string
|
||||
// Target contains the parsed address info of the dial target. It is the
|
||||
// same resolver.Target as passed to the resolver. See the documentation for
|
||||
// the resolver.Target type for details about what it contains.
|
||||
Target resolver.Target
|
||||
}
|
||||
|
||||
// Builder creates a balancer.
|
||||
type Builder interface {
|
||||
// Build creates a new balancer with the ClientConn.
|
||||
Build(cc ClientConn, opts BuildOptions) Balancer
|
||||
// Name returns the name of balancers built by this builder.
|
||||
// It will be used to pick balancers (for example in service config).
|
||||
Name() string
|
||||
}
|
||||
|
||||
// ConfigParser parses load balancer configs.
|
||||
type ConfigParser interface {
|
||||
// ParseConfig parses the JSON load balancer config provided into an
|
||||
// internal form or returns an error if the config is invalid. For future
|
||||
// compatibility reasons, unknown fields in the config should be ignored.
|
||||
ParseConfig(LoadBalancingConfigJSON json.RawMessage) (serviceconfig.LoadBalancingConfig, error)
|
||||
}
|
||||
|
||||
// PickInfo contains additional information for the Pick operation.
|
||||
type PickInfo struct {
|
||||
// FullMethodName is the method name that NewClientStream() is called
|
||||
// with. The canonical format is /service/Method.
|
||||
FullMethodName string
|
||||
// Ctx is the RPC's context, and may contain relevant RPC-level information
|
||||
// like the outgoing header metadata.
|
||||
Ctx context.Context
|
||||
}
|
||||
|
||||
// DoneInfo contains additional information for done.
|
||||
type DoneInfo struct {
|
||||
// Err is the rpc error the RPC finished with. It could be nil.
|
||||
Err error
|
||||
// Trailer contains the metadata from the RPC's trailer, if present.
|
||||
Trailer metadata.MD
|
||||
// BytesSent indicates if any bytes have been sent to the server.
|
||||
BytesSent bool
|
||||
// BytesReceived indicates if any byte has been received from the server.
|
||||
BytesReceived bool
|
||||
// ServerLoad is the load received from server. It's usually sent as part of
|
||||
// trailing metadata.
|
||||
//
|
||||
// The only supported type now is *orca_v3.LoadReport.
|
||||
ServerLoad any
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrNoSubConnAvailable indicates no SubConn is available for pick().
|
||||
// gRPC will block the RPC until a new picker is available via UpdateState().
|
||||
ErrNoSubConnAvailable = errors.New("no SubConn is available")
|
||||
// ErrTransientFailure indicates all SubConns are in TransientFailure.
|
||||
// WaitForReady RPCs will block, non-WaitForReady RPCs will fail.
|
||||
//
|
||||
// Deprecated: return an appropriate error based on the last resolution or
|
||||
// connection attempt instead. The behavior is the same for any non-gRPC
|
||||
// status error.
|
||||
ErrTransientFailure = errors.New("all SubConns are in TransientFailure")
|
||||
)
|
||||
|
||||
// PickResult contains information related to a connection chosen for an RPC.
|
||||
type PickResult struct {
|
||||
// SubConn is the connection to use for this pick, if its state is Ready.
|
||||
// If the state is not Ready, gRPC will block the RPC until a new Picker is
|
||||
// provided by the balancer (using ClientConn.UpdateState). The SubConn
|
||||
// must be one returned by ClientConn.NewSubConn.
|
||||
SubConn SubConn
|
||||
|
||||
// Done is called when the RPC is completed. If the SubConn is not ready,
|
||||
// this will be called with a nil parameter. If the SubConn is not a valid
|
||||
// type, Done may not be called. May be nil if the balancer does not wish
|
||||
// to be notified when the RPC completes.
|
||||
Done func(DoneInfo)
|
||||
|
||||
// Metadata provides a way for LB policies to inject arbitrary per-call
|
||||
// metadata. Any metadata returned here will be merged with existing
|
||||
// metadata added by the client application.
|
||||
//
|
||||
// LB policies with child policies are responsible for propagating metadata
|
||||
// injected by their children to the ClientConn, as part of Pick().
|
||||
Metadata metadata.MD
|
||||
}
|
||||
|
||||
// TransientFailureError returns e. It exists for backward compatibility and
|
||||
// will be deleted soon.
|
||||
//
|
||||
// Deprecated: no longer necessary, picker errors are treated this way by
|
||||
// default.
|
||||
func TransientFailureError(e error) error { return e }
|
||||
|
||||
// Picker is used by gRPC to pick a SubConn to send an RPC.
|
||||
// Balancer is expected to generate a new picker from its snapshot every time its
|
||||
// internal state has changed.
|
||||
//
|
||||
// The pickers used by gRPC can be updated by ClientConn.UpdateState().
|
||||
type Picker interface {
|
||||
// Pick returns the connection to use for this RPC and related information.
|
||||
//
|
||||
// Pick should not block. If the balancer needs to do I/O or any blocking
|
||||
// or time-consuming work to service this call, it should return
|
||||
// ErrNoSubConnAvailable, and the Pick call will be repeated by gRPC when
|
||||
// the Picker is updated (using ClientConn.UpdateState).
|
||||
//
|
||||
// If an error is returned:
|
||||
//
|
||||
// - If the error is ErrNoSubConnAvailable, gRPC will block until a new
|
||||
// Picker is provided by the balancer (using ClientConn.UpdateState).
|
||||
//
|
||||
// - If the error is a status error (implemented by the grpc/status
|
||||
// package), gRPC will terminate the RPC with the code and message
|
||||
// provided.
|
||||
//
|
||||
// - For all other errors, wait for ready RPCs will wait, but non-wait for
|
||||
// ready RPCs will be terminated with this error's Error() string and
|
||||
// status code Unavailable.
|
||||
Pick(info PickInfo) (PickResult, error)
|
||||
}
|
||||
|
||||
// Balancer takes input from gRPC, manages SubConns, and collects and aggregates
|
||||
// the connectivity states.
|
||||
//
|
||||
// It also generates and updates the Picker used by gRPC to pick SubConns for RPCs.
|
||||
//
|
||||
// UpdateClientConnState, ResolverError, UpdateSubConnState, and Close are
|
||||
// guaranteed to be called synchronously from the same goroutine. There's no
|
||||
// guarantee on picker.Pick, it may be called anytime.
|
||||
type Balancer interface {
|
||||
// UpdateClientConnState is called by gRPC when the state of the ClientConn
|
||||
// changes. If the error returned is ErrBadResolverState, the ClientConn
|
||||
// will begin calling ResolveNow on the active name resolver with
|
||||
// exponential backoff until a subsequent call to UpdateClientConnState
|
||||
// returns a nil error. Any other errors are currently ignored.
|
||||
UpdateClientConnState(ClientConnState) error
|
||||
// ResolverError is called by gRPC when the name resolver reports an error.
|
||||
ResolverError(error)
|
||||
// UpdateSubConnState is called by gRPC when the state of a SubConn
|
||||
// changes.
|
||||
//
|
||||
// Deprecated: Use NewSubConnOptions.StateListener when creating the
|
||||
// SubConn instead.
|
||||
UpdateSubConnState(SubConn, SubConnState)
|
||||
// Close closes the balancer. The balancer is not currently required to
|
||||
// call SubConn.Shutdown for its existing SubConns; however, this will be
|
||||
// required in a future release, so it is recommended.
|
||||
Close()
|
||||
}
|
||||
|
||||
// ExitIdler is an optional interface for balancers to implement. If
|
||||
// implemented, ExitIdle will be called when ClientConn.Connect is called, if
|
||||
// the ClientConn is idle. If unimplemented, ClientConn.Connect will cause
|
||||
// all SubConns to connect.
|
||||
//
|
||||
// Notice: it will be required for all balancers to implement this in a future
|
||||
// release.
|
||||
type ExitIdler interface {
|
||||
// ExitIdle instructs the LB policy to reconnect to backends / exit the
|
||||
// IDLE state, if appropriate and possible. Note that SubConns that enter
|
||||
// the IDLE state will not reconnect until SubConn.Connect is called.
|
||||
ExitIdle()
|
||||
}
|
||||
|
||||
// SubConnState describes the state of a SubConn.
|
||||
type SubConnState struct {
|
||||
// ConnectivityState is the connectivity state of the SubConn.
|
||||
ConnectivityState connectivity.State
|
||||
// ConnectionError is set if the ConnectivityState is TransientFailure,
|
||||
// describing the reason the SubConn failed. Otherwise, it is nil.
|
||||
ConnectionError error
|
||||
}
|
||||
|
||||
// ClientConnState describes the state of a ClientConn relevant to the
|
||||
// balancer.
|
||||
type ClientConnState struct {
|
||||
ResolverState resolver.State
|
||||
// The parsed load balancing configuration returned by the builder's
|
||||
// ParseConfig method, if implemented.
|
||||
BalancerConfig serviceconfig.LoadBalancingConfig
|
||||
}
|
||||
|
||||
// ErrBadResolverState may be returned by UpdateClientConnState to indicate a
|
||||
// problem with the provided name resolver data.
|
||||
var ErrBadResolverState = errors.New("bad resolver state")
|
||||
|
||||
// A ProducerBuilder is a simple constructor for a Producer. It is used by the
|
||||
// SubConn to create producers when needed.
|
||||
type ProducerBuilder interface {
|
||||
// Build creates a Producer. The first parameter is always a
|
||||
// grpc.ClientConnInterface (a type to allow creating RPCs/streams on the
|
||||
// associated SubConn), but is declared as `any` to avoid a dependency
|
||||
// cycle. Should also return a close function that will be called when all
|
||||
// references to the Producer have been given up.
|
||||
Build(grpcClientConnInterface any) (p Producer, close func())
|
||||
}
|
||||
|
||||
// A Producer is a type shared among potentially many consumers. It is
|
||||
// associated with a SubConn, and an implementation will typically contain
|
||||
// other methods to provide additional functionality, e.g. configuration or
|
||||
// subscription registration.
|
||||
type Producer any
|
||||
264
vendor/google.golang.org/grpc/balancer/base/balancer.go
generated
vendored
Normal file
264
vendor/google.golang.org/grpc/balancer/base/balancer.go
generated
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package base
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
|
||||
var logger = grpclog.Component("balancer")
|
||||
|
||||
type baseBuilder struct {
|
||||
name string
|
||||
pickerBuilder PickerBuilder
|
||||
config Config
|
||||
}
|
||||
|
||||
func (bb *baseBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer {
|
||||
bal := &baseBalancer{
|
||||
cc: cc,
|
||||
pickerBuilder: bb.pickerBuilder,
|
||||
|
||||
subConns: resolver.NewAddressMap(),
|
||||
scStates: make(map[balancer.SubConn]connectivity.State),
|
||||
csEvltr: &balancer.ConnectivityStateEvaluator{},
|
||||
config: bb.config,
|
||||
state: connectivity.Connecting,
|
||||
}
|
||||
// Initialize picker to a picker that always returns
|
||||
// ErrNoSubConnAvailable, because when state of a SubConn changes, we
|
||||
// may call UpdateState with this picker.
|
||||
bal.picker = NewErrPicker(balancer.ErrNoSubConnAvailable)
|
||||
return bal
|
||||
}
|
||||
|
||||
func (bb *baseBuilder) Name() string {
|
||||
return bb.name
|
||||
}
|
||||
|
||||
type baseBalancer struct {
|
||||
cc balancer.ClientConn
|
||||
pickerBuilder PickerBuilder
|
||||
|
||||
csEvltr *balancer.ConnectivityStateEvaluator
|
||||
state connectivity.State
|
||||
|
||||
subConns *resolver.AddressMap
|
||||
scStates map[balancer.SubConn]connectivity.State
|
||||
picker balancer.Picker
|
||||
config Config
|
||||
|
||||
resolverErr error // the last error reported by the resolver; cleared on successful resolution
|
||||
connErr error // the last connection error; cleared upon leaving TransientFailure
|
||||
}
|
||||
|
||||
func (b *baseBalancer) ResolverError(err error) {
|
||||
b.resolverErr = err
|
||||
if b.subConns.Len() == 0 {
|
||||
b.state = connectivity.TransientFailure
|
||||
}
|
||||
|
||||
if b.state != connectivity.TransientFailure {
|
||||
// The picker will not change since the balancer does not currently
|
||||
// report an error.
|
||||
return
|
||||
}
|
||||
b.regeneratePicker()
|
||||
b.cc.UpdateState(balancer.State{
|
||||
ConnectivityState: b.state,
|
||||
Picker: b.picker,
|
||||
})
|
||||
}
|
||||
|
||||
func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
|
||||
// TODO: handle s.ResolverState.ServiceConfig?
|
||||
if logger.V(2) {
|
||||
logger.Info("base.baseBalancer: got new ClientConn state: ", s)
|
||||
}
|
||||
// Successful resolution; clear resolver error and ensure we return nil.
|
||||
b.resolverErr = nil
|
||||
// addrsSet is the set converted from addrs, it's used for quick lookup of an address.
|
||||
addrsSet := resolver.NewAddressMap()
|
||||
for _, a := range s.ResolverState.Addresses {
|
||||
addrsSet.Set(a, nil)
|
||||
if _, ok := b.subConns.Get(a); !ok {
|
||||
// a is a new address (not existing in b.subConns).
|
||||
var sc balancer.SubConn
|
||||
opts := balancer.NewSubConnOptions{
|
||||
HealthCheckEnabled: b.config.HealthCheck,
|
||||
StateListener: func(scs balancer.SubConnState) { b.updateSubConnState(sc, scs) },
|
||||
}
|
||||
sc, err := b.cc.NewSubConn([]resolver.Address{a}, opts)
|
||||
if err != nil {
|
||||
logger.Warningf("base.baseBalancer: failed to create new SubConn: %v", err)
|
||||
continue
|
||||
}
|
||||
b.subConns.Set(a, sc)
|
||||
b.scStates[sc] = connectivity.Idle
|
||||
b.csEvltr.RecordTransition(connectivity.Shutdown, connectivity.Idle)
|
||||
sc.Connect()
|
||||
}
|
||||
}
|
||||
for _, a := range b.subConns.Keys() {
|
||||
sci, _ := b.subConns.Get(a)
|
||||
sc := sci.(balancer.SubConn)
|
||||
// a was removed by resolver.
|
||||
if _, ok := addrsSet.Get(a); !ok {
|
||||
sc.Shutdown()
|
||||
b.subConns.Delete(a)
|
||||
// Keep the state of this sc in b.scStates until sc's state becomes Shutdown.
|
||||
// The entry will be deleted in updateSubConnState.
|
||||
}
|
||||
}
|
||||
// If resolver state contains no addresses, return an error so ClientConn
|
||||
// will trigger re-resolve. Also records this as an resolver error, so when
|
||||
// the overall state turns transient failure, the error message will have
|
||||
// the zero address information.
|
||||
if len(s.ResolverState.Addresses) == 0 {
|
||||
b.ResolverError(errors.New("produced zero addresses"))
|
||||
return balancer.ErrBadResolverState
|
||||
}
|
||||
|
||||
b.regeneratePicker()
|
||||
b.cc.UpdateState(balancer.State{ConnectivityState: b.state, Picker: b.picker})
|
||||
return nil
|
||||
}
|
||||
|
||||
// mergeErrors builds an error from the last connection error and the last
|
||||
// resolver error. Must only be called if b.state is TransientFailure.
|
||||
func (b *baseBalancer) mergeErrors() error {
|
||||
// connErr must always be non-nil unless there are no SubConns, in which
|
||||
// case resolverErr must be non-nil.
|
||||
if b.connErr == nil {
|
||||
return fmt.Errorf("last resolver error: %v", b.resolverErr)
|
||||
}
|
||||
if b.resolverErr == nil {
|
||||
return fmt.Errorf("last connection error: %v", b.connErr)
|
||||
}
|
||||
return fmt.Errorf("last connection error: %v; last resolver error: %v", b.connErr, b.resolverErr)
|
||||
}
|
||||
|
||||
// regeneratePicker takes a snapshot of the balancer, and generates a picker
|
||||
// from it. The picker is
|
||||
// - errPicker if the balancer is in TransientFailure,
|
||||
// - built by the pickerBuilder with all READY SubConns otherwise.
|
||||
func (b *baseBalancer) regeneratePicker() {
|
||||
if b.state == connectivity.TransientFailure {
|
||||
b.picker = NewErrPicker(b.mergeErrors())
|
||||
return
|
||||
}
|
||||
readySCs := make(map[balancer.SubConn]SubConnInfo)
|
||||
|
||||
// Filter out all ready SCs from full subConn map.
|
||||
for _, addr := range b.subConns.Keys() {
|
||||
sci, _ := b.subConns.Get(addr)
|
||||
sc := sci.(balancer.SubConn)
|
||||
if st, ok := b.scStates[sc]; ok && st == connectivity.Ready {
|
||||
readySCs[sc] = SubConnInfo{Address: addr}
|
||||
}
|
||||
}
|
||||
b.picker = b.pickerBuilder.Build(PickerBuildInfo{ReadySCs: readySCs})
|
||||
}
|
||||
|
||||
// UpdateSubConnState is a nop because a StateListener is always set in NewSubConn.
|
||||
func (b *baseBalancer) UpdateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {
|
||||
logger.Errorf("base.baseBalancer: UpdateSubConnState(%v, %+v) called unexpectedly", sc, state)
|
||||
}
|
||||
|
||||
func (b *baseBalancer) updateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {
|
||||
s := state.ConnectivityState
|
||||
if logger.V(2) {
|
||||
logger.Infof("base.baseBalancer: handle SubConn state change: %p, %v", sc, s)
|
||||
}
|
||||
oldS, ok := b.scStates[sc]
|
||||
if !ok {
|
||||
if logger.V(2) {
|
||||
logger.Infof("base.baseBalancer: got state changes for an unknown SubConn: %p, %v", sc, s)
|
||||
}
|
||||
return
|
||||
}
|
||||
if oldS == connectivity.TransientFailure &&
|
||||
(s == connectivity.Connecting || s == connectivity.Idle) {
|
||||
// Once a subconn enters TRANSIENT_FAILURE, ignore subsequent IDLE or
|
||||
// CONNECTING transitions to prevent the aggregated state from being
|
||||
// always CONNECTING when many backends exist but are all down.
|
||||
if s == connectivity.Idle {
|
||||
sc.Connect()
|
||||
}
|
||||
return
|
||||
}
|
||||
b.scStates[sc] = s
|
||||
switch s {
|
||||
case connectivity.Idle:
|
||||
sc.Connect()
|
||||
case connectivity.Shutdown:
|
||||
// When an address was removed by resolver, b called Shutdown but kept
|
||||
// the sc's state in scStates. Remove state for this sc here.
|
||||
delete(b.scStates, sc)
|
||||
case connectivity.TransientFailure:
|
||||
// Save error to be reported via picker.
|
||||
b.connErr = state.ConnectionError
|
||||
}
|
||||
|
||||
b.state = b.csEvltr.RecordTransition(oldS, s)
|
||||
|
||||
// Regenerate picker when one of the following happens:
|
||||
// - this sc entered or left ready
|
||||
// - the aggregated state of balancer is TransientFailure
|
||||
// (may need to update error message)
|
||||
if (s == connectivity.Ready) != (oldS == connectivity.Ready) ||
|
||||
b.state == connectivity.TransientFailure {
|
||||
b.regeneratePicker()
|
||||
}
|
||||
b.cc.UpdateState(balancer.State{ConnectivityState: b.state, Picker: b.picker})
|
||||
}
|
||||
|
||||
// Close is a nop because base balancer doesn't have internal state to clean up,
|
||||
// and it doesn't need to call Shutdown for the SubConns.
|
||||
func (b *baseBalancer) Close() {
|
||||
}
|
||||
|
||||
// ExitIdle is a nop because the base balancer attempts to stay connected to
|
||||
// all SubConns at all times.
|
||||
func (b *baseBalancer) ExitIdle() {
|
||||
}
|
||||
|
||||
// NewErrPicker returns a Picker that always returns err on Pick().
|
||||
func NewErrPicker(err error) balancer.Picker {
|
||||
return &errPicker{err: err}
|
||||
}
|
||||
|
||||
// NewErrPickerV2 is temporarily defined for backward compatibility reasons.
|
||||
//
|
||||
// Deprecated: use NewErrPicker instead.
|
||||
var NewErrPickerV2 = NewErrPicker
|
||||
|
||||
type errPicker struct {
|
||||
err error // Pick() always returns this err.
|
||||
}
|
||||
|
||||
func (p *errPicker) Pick(info balancer.PickInfo) (balancer.PickResult, error) {
|
||||
return balancer.PickResult{}, p.err
|
||||
}
|
||||
71
vendor/google.golang.org/grpc/balancer/base/base.go
generated
vendored
Normal file
71
vendor/google.golang.org/grpc/balancer/base/base.go
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package base defines a balancer base that can be used to build balancers with
|
||||
// different picking algorithms.
|
||||
//
|
||||
// The base balancer creates a new SubConn for each resolved address. The
|
||||
// provided picker will only be notified about READY SubConns.
|
||||
//
|
||||
// This package is the base of round_robin balancer, its purpose is to be used
|
||||
// to build round_robin like balancers with complex picking algorithms.
|
||||
// Balancers with more complicated logic should try to implement a balancer
|
||||
// builder from scratch.
|
||||
//
|
||||
// All APIs in this package are experimental.
|
||||
package base
|
||||
|
||||
import (
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
|
||||
// PickerBuilder creates balancer.Picker.
|
||||
type PickerBuilder interface {
|
||||
// Build returns a picker that will be used by gRPC to pick a SubConn.
|
||||
Build(info PickerBuildInfo) balancer.Picker
|
||||
}
|
||||
|
||||
// PickerBuildInfo contains information needed by the picker builder to
|
||||
// construct a picker.
|
||||
type PickerBuildInfo struct {
|
||||
// ReadySCs is a map from all ready SubConns to the Addresses used to
|
||||
// create them.
|
||||
ReadySCs map[balancer.SubConn]SubConnInfo
|
||||
}
|
||||
|
||||
// SubConnInfo contains information about a SubConn created by the base
|
||||
// balancer.
|
||||
type SubConnInfo struct {
|
||||
Address resolver.Address // the address used to create this SubConn
|
||||
}
|
||||
|
||||
// Config contains the config info about the base balancer builder.
|
||||
type Config struct {
|
||||
// HealthCheck indicates whether health checking should be enabled for this specific balancer.
|
||||
HealthCheck bool
|
||||
}
|
||||
|
||||
// NewBalancerBuilder returns a base balancer builder configured by the provided config.
|
||||
func NewBalancerBuilder(name string, pb PickerBuilder, config Config) balancer.Builder {
|
||||
return &baseBuilder{
|
||||
name: name,
|
||||
pickerBuilder: pb,
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
74
vendor/google.golang.org/grpc/balancer/conn_state_evaluator.go
generated
vendored
Normal file
74
vendor/google.golang.org/grpc/balancer/conn_state_evaluator.go
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2022 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package balancer
|
||||
|
||||
import "google.golang.org/grpc/connectivity"
|
||||
|
||||
// ConnectivityStateEvaluator takes the connectivity states of multiple SubConns
|
||||
// and returns one aggregated connectivity state.
|
||||
//
|
||||
// It's not thread safe.
|
||||
type ConnectivityStateEvaluator struct {
|
||||
numReady uint64 // Number of addrConns in ready state.
|
||||
numConnecting uint64 // Number of addrConns in connecting state.
|
||||
numTransientFailure uint64 // Number of addrConns in transient failure state.
|
||||
numIdle uint64 // Number of addrConns in idle state.
|
||||
}
|
||||
|
||||
// RecordTransition records state change happening in subConn and based on that
|
||||
// it evaluates what aggregated state should be.
|
||||
//
|
||||
// - If at least one SubConn in Ready, the aggregated state is Ready;
|
||||
// - Else if at least one SubConn in Connecting, the aggregated state is Connecting;
|
||||
// - Else if at least one SubConn is Idle, the aggregated state is Idle;
|
||||
// - Else if at least one SubConn is TransientFailure (or there are no SubConns), the aggregated state is Transient Failure.
|
||||
//
|
||||
// Shutdown is not considered.
|
||||
func (cse *ConnectivityStateEvaluator) RecordTransition(oldState, newState connectivity.State) connectivity.State {
|
||||
// Update counters.
|
||||
for idx, state := range []connectivity.State{oldState, newState} {
|
||||
updateVal := 2*uint64(idx) - 1 // -1 for oldState and +1 for new.
|
||||
switch state {
|
||||
case connectivity.Ready:
|
||||
cse.numReady += updateVal
|
||||
case connectivity.Connecting:
|
||||
cse.numConnecting += updateVal
|
||||
case connectivity.TransientFailure:
|
||||
cse.numTransientFailure += updateVal
|
||||
case connectivity.Idle:
|
||||
cse.numIdle += updateVal
|
||||
}
|
||||
}
|
||||
return cse.CurrentState()
|
||||
}
|
||||
|
||||
// CurrentState returns the current aggregate conn state by evaluating the counters
|
||||
func (cse *ConnectivityStateEvaluator) CurrentState() connectivity.State {
|
||||
// Evaluate.
|
||||
if cse.numReady > 0 {
|
||||
return connectivity.Ready
|
||||
}
|
||||
if cse.numConnecting > 0 {
|
||||
return connectivity.Connecting
|
||||
}
|
||||
if cse.numIdle > 0 {
|
||||
return connectivity.Idle
|
||||
}
|
||||
return connectivity.TransientFailure
|
||||
}
|
||||
957
vendor/google.golang.org/grpc/balancer/grpclb/grpc_lb_v1/load_balancer.pb.go
generated
vendored
Normal file
957
vendor/google.golang.org/grpc/balancer/grpclb/grpc_lb_v1/load_balancer.pb.go
generated
vendored
Normal file
@@ -0,0 +1,957 @@
|
||||
// Copyright 2015 The gRPC Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This file defines the GRPCLB LoadBalancing protocol.
|
||||
//
|
||||
// The canonical version of this proto can be found at
|
||||
// https://github.com/grpc/grpc-proto/blob/master/grpc/lb/v1/load_balancer.proto
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.25.2
|
||||
// source: grpc/lb/v1/load_balancer.proto
|
||||
|
||||
package grpc_lb_v1
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
durationpb "google.golang.org/protobuf/types/known/durationpb"
|
||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type LoadBalanceRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Types that are assignable to LoadBalanceRequestType:
|
||||
//
|
||||
// *LoadBalanceRequest_InitialRequest
|
||||
// *LoadBalanceRequest_ClientStats
|
||||
LoadBalanceRequestType isLoadBalanceRequest_LoadBalanceRequestType `protobuf_oneof:"load_balance_request_type"`
|
||||
}
|
||||
|
||||
func (x *LoadBalanceRequest) Reset() {
|
||||
*x = LoadBalanceRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_grpc_lb_v1_load_balancer_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *LoadBalanceRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*LoadBalanceRequest) ProtoMessage() {}
|
||||
|
||||
func (x *LoadBalanceRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_grpc_lb_v1_load_balancer_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use LoadBalanceRequest.ProtoReflect.Descriptor instead.
|
||||
func (*LoadBalanceRequest) Descriptor() ([]byte, []int) {
|
||||
return file_grpc_lb_v1_load_balancer_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (m *LoadBalanceRequest) GetLoadBalanceRequestType() isLoadBalanceRequest_LoadBalanceRequestType {
|
||||
if m != nil {
|
||||
return m.LoadBalanceRequestType
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *LoadBalanceRequest) GetInitialRequest() *InitialLoadBalanceRequest {
|
||||
if x, ok := x.GetLoadBalanceRequestType().(*LoadBalanceRequest_InitialRequest); ok {
|
||||
return x.InitialRequest
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *LoadBalanceRequest) GetClientStats() *ClientStats {
|
||||
if x, ok := x.GetLoadBalanceRequestType().(*LoadBalanceRequest_ClientStats); ok {
|
||||
return x.ClientStats
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isLoadBalanceRequest_LoadBalanceRequestType interface {
|
||||
isLoadBalanceRequest_LoadBalanceRequestType()
|
||||
}
|
||||
|
||||
type LoadBalanceRequest_InitialRequest struct {
|
||||
// This message should be sent on the first request to the load balancer.
|
||||
InitialRequest *InitialLoadBalanceRequest `protobuf:"bytes,1,opt,name=initial_request,json=initialRequest,proto3,oneof"`
|
||||
}
|
||||
|
||||
type LoadBalanceRequest_ClientStats struct {
|
||||
// The client stats should be periodically reported to the load balancer
|
||||
// based on the duration defined in the InitialLoadBalanceResponse.
|
||||
ClientStats *ClientStats `protobuf:"bytes,2,opt,name=client_stats,json=clientStats,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*LoadBalanceRequest_InitialRequest) isLoadBalanceRequest_LoadBalanceRequestType() {}
|
||||
|
||||
func (*LoadBalanceRequest_ClientStats) isLoadBalanceRequest_LoadBalanceRequestType() {}
|
||||
|
||||
type InitialLoadBalanceRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// The name of the load balanced service (e.g., service.googleapis.com). Its
|
||||
// length should be less than 256 bytes.
|
||||
// The name might include a port number. How to handle the port number is up
|
||||
// to the balancer.
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
}
|
||||
|
||||
func (x *InitialLoadBalanceRequest) Reset() {
|
||||
*x = InitialLoadBalanceRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_grpc_lb_v1_load_balancer_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *InitialLoadBalanceRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*InitialLoadBalanceRequest) ProtoMessage() {}
|
||||
|
||||
func (x *InitialLoadBalanceRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_grpc_lb_v1_load_balancer_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use InitialLoadBalanceRequest.ProtoReflect.Descriptor instead.
|
||||
func (*InitialLoadBalanceRequest) Descriptor() ([]byte, []int) {
|
||||
return file_grpc_lb_v1_load_balancer_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *InitialLoadBalanceRequest) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Contains the number of calls finished for a particular load balance token.
|
||||
type ClientStatsPerToken struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// See Server.load_balance_token.
|
||||
LoadBalanceToken string `protobuf:"bytes,1,opt,name=load_balance_token,json=loadBalanceToken,proto3" json:"load_balance_token,omitempty"`
|
||||
// The total number of RPCs that finished associated with the token.
|
||||
NumCalls int64 `protobuf:"varint,2,opt,name=num_calls,json=numCalls,proto3" json:"num_calls,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ClientStatsPerToken) Reset() {
|
||||
*x = ClientStatsPerToken{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_grpc_lb_v1_load_balancer_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ClientStatsPerToken) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ClientStatsPerToken) ProtoMessage() {}
|
||||
|
||||
func (x *ClientStatsPerToken) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_grpc_lb_v1_load_balancer_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ClientStatsPerToken.ProtoReflect.Descriptor instead.
|
||||
func (*ClientStatsPerToken) Descriptor() ([]byte, []int) {
|
||||
return file_grpc_lb_v1_load_balancer_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *ClientStatsPerToken) GetLoadBalanceToken() string {
|
||||
if x != nil {
|
||||
return x.LoadBalanceToken
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ClientStatsPerToken) GetNumCalls() int64 {
|
||||
if x != nil {
|
||||
return x.NumCalls
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Contains client level statistics that are useful to load balancing. Each
|
||||
// count except the timestamp should be reset to zero after reporting the stats.
|
||||
type ClientStats struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// The timestamp of generating the report.
|
||||
Timestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
|
||||
// The total number of RPCs that started.
|
||||
NumCallsStarted int64 `protobuf:"varint,2,opt,name=num_calls_started,json=numCallsStarted,proto3" json:"num_calls_started,omitempty"`
|
||||
// The total number of RPCs that finished.
|
||||
NumCallsFinished int64 `protobuf:"varint,3,opt,name=num_calls_finished,json=numCallsFinished,proto3" json:"num_calls_finished,omitempty"`
|
||||
// The total number of RPCs that failed to reach a server except dropped RPCs.
|
||||
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"`
|
||||
// The total number of RPCs that finished and are known to have been received
|
||||
// by a server.
|
||||
NumCallsFinishedKnownReceived int64 `protobuf:"varint,7,opt,name=num_calls_finished_known_received,json=numCallsFinishedKnownReceived,proto3" json:"num_calls_finished_known_received,omitempty"`
|
||||
// The list of dropped calls.
|
||||
CallsFinishedWithDrop []*ClientStatsPerToken `protobuf:"bytes,8,rep,name=calls_finished_with_drop,json=callsFinishedWithDrop,proto3" json:"calls_finished_with_drop,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ClientStats) Reset() {
|
||||
*x = ClientStats{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_grpc_lb_v1_load_balancer_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ClientStats) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ClientStats) ProtoMessage() {}
|
||||
|
||||
func (x *ClientStats) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_grpc_lb_v1_load_balancer_proto_msgTypes[3]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ClientStats.ProtoReflect.Descriptor instead.
|
||||
func (*ClientStats) Descriptor() ([]byte, []int) {
|
||||
return file_grpc_lb_v1_load_balancer_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *ClientStats) GetTimestamp() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.Timestamp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ClientStats) GetNumCallsStarted() int64 {
|
||||
if x != nil {
|
||||
return x.NumCallsStarted
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ClientStats) GetNumCallsFinished() int64 {
|
||||
if x != nil {
|
||||
return x.NumCallsFinished
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ClientStats) GetNumCallsFinishedWithClientFailedToSend() int64 {
|
||||
if x != nil {
|
||||
return x.NumCallsFinishedWithClientFailedToSend
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ClientStats) GetNumCallsFinishedKnownReceived() int64 {
|
||||
if x != nil {
|
||||
return x.NumCallsFinishedKnownReceived
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ClientStats) GetCallsFinishedWithDrop() []*ClientStatsPerToken {
|
||||
if x != nil {
|
||||
return x.CallsFinishedWithDrop
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type LoadBalanceResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Types that are assignable to LoadBalanceResponseType:
|
||||
//
|
||||
// *LoadBalanceResponse_InitialResponse
|
||||
// *LoadBalanceResponse_ServerList
|
||||
// *LoadBalanceResponse_FallbackResponse
|
||||
LoadBalanceResponseType isLoadBalanceResponse_LoadBalanceResponseType `protobuf_oneof:"load_balance_response_type"`
|
||||
}
|
||||
|
||||
func (x *LoadBalanceResponse) Reset() {
|
||||
*x = LoadBalanceResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_grpc_lb_v1_load_balancer_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *LoadBalanceResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*LoadBalanceResponse) ProtoMessage() {}
|
||||
|
||||
func (x *LoadBalanceResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_grpc_lb_v1_load_balancer_proto_msgTypes[4]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use LoadBalanceResponse.ProtoReflect.Descriptor instead.
|
||||
func (*LoadBalanceResponse) Descriptor() ([]byte, []int) {
|
||||
return file_grpc_lb_v1_load_balancer_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (m *LoadBalanceResponse) GetLoadBalanceResponseType() isLoadBalanceResponse_LoadBalanceResponseType {
|
||||
if m != nil {
|
||||
return m.LoadBalanceResponseType
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *LoadBalanceResponse) GetInitialResponse() *InitialLoadBalanceResponse {
|
||||
if x, ok := x.GetLoadBalanceResponseType().(*LoadBalanceResponse_InitialResponse); ok {
|
||||
return x.InitialResponse
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *LoadBalanceResponse) GetServerList() *ServerList {
|
||||
if x, ok := x.GetLoadBalanceResponseType().(*LoadBalanceResponse_ServerList); ok {
|
||||
return x.ServerList
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *LoadBalanceResponse) GetFallbackResponse() *FallbackResponse {
|
||||
if x, ok := x.GetLoadBalanceResponseType().(*LoadBalanceResponse_FallbackResponse); ok {
|
||||
return x.FallbackResponse
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isLoadBalanceResponse_LoadBalanceResponseType interface {
|
||||
isLoadBalanceResponse_LoadBalanceResponseType()
|
||||
}
|
||||
|
||||
type LoadBalanceResponse_InitialResponse struct {
|
||||
// This message should be sent on the first response to the client.
|
||||
InitialResponse *InitialLoadBalanceResponse `protobuf:"bytes,1,opt,name=initial_response,json=initialResponse,proto3,oneof"`
|
||||
}
|
||||
|
||||
type LoadBalanceResponse_ServerList struct {
|
||||
// Contains the list of servers selected by the load balancer. The client
|
||||
// should send requests to these servers in the specified order.
|
||||
ServerList *ServerList `protobuf:"bytes,2,opt,name=server_list,json=serverList,proto3,oneof"`
|
||||
}
|
||||
|
||||
type LoadBalanceResponse_FallbackResponse struct {
|
||||
// If this field is set, then the client should eagerly enter fallback
|
||||
// mode (even if there are existing, healthy connections to backends).
|
||||
FallbackResponse *FallbackResponse `protobuf:"bytes,3,opt,name=fallback_response,json=fallbackResponse,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*LoadBalanceResponse_InitialResponse) isLoadBalanceResponse_LoadBalanceResponseType() {}
|
||||
|
||||
func (*LoadBalanceResponse_ServerList) isLoadBalanceResponse_LoadBalanceResponseType() {}
|
||||
|
||||
func (*LoadBalanceResponse_FallbackResponse) isLoadBalanceResponse_LoadBalanceResponseType() {}
|
||||
|
||||
type FallbackResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
}
|
||||
|
||||
func (x *FallbackResponse) Reset() {
|
||||
*x = FallbackResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_grpc_lb_v1_load_balancer_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *FallbackResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*FallbackResponse) ProtoMessage() {}
|
||||
|
||||
func (x *FallbackResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_grpc_lb_v1_load_balancer_proto_msgTypes[5]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use FallbackResponse.ProtoReflect.Descriptor instead.
|
||||
func (*FallbackResponse) Descriptor() ([]byte, []int) {
|
||||
return file_grpc_lb_v1_load_balancer_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
type InitialLoadBalanceResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// This interval defines how often the client should send the client stats
|
||||
// to the load balancer. Stats should only be reported when the duration is
|
||||
// positive.
|
||||
ClientStatsReportInterval *durationpb.Duration `protobuf:"bytes,2,opt,name=client_stats_report_interval,json=clientStatsReportInterval,proto3" json:"client_stats_report_interval,omitempty"`
|
||||
}
|
||||
|
||||
func (x *InitialLoadBalanceResponse) Reset() {
|
||||
*x = InitialLoadBalanceResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_grpc_lb_v1_load_balancer_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *InitialLoadBalanceResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*InitialLoadBalanceResponse) ProtoMessage() {}
|
||||
|
||||
func (x *InitialLoadBalanceResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_grpc_lb_v1_load_balancer_proto_msgTypes[6]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use InitialLoadBalanceResponse.ProtoReflect.Descriptor instead.
|
||||
func (*InitialLoadBalanceResponse) Descriptor() ([]byte, []int) {
|
||||
return file_grpc_lb_v1_load_balancer_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *InitialLoadBalanceResponse) GetClientStatsReportInterval() *durationpb.Duration {
|
||||
if x != nil {
|
||||
return x.ClientStatsReportInterval
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ServerList struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Contains a list of servers selected by the load balancer. The list will
|
||||
// be updated when server resolutions change or as needed to balance load
|
||||
// across more servers. The client should consume the server list in order
|
||||
// unless instructed otherwise via the client_config.
|
||||
Servers []*Server `protobuf:"bytes,1,rep,name=servers,proto3" json:"servers,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ServerList) Reset() {
|
||||
*x = ServerList{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_grpc_lb_v1_load_balancer_proto_msgTypes[7]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ServerList) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ServerList) ProtoMessage() {}
|
||||
|
||||
func (x *ServerList) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_grpc_lb_v1_load_balancer_proto_msgTypes[7]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ServerList.ProtoReflect.Descriptor instead.
|
||||
func (*ServerList) Descriptor() ([]byte, []int) {
|
||||
return file_grpc_lb_v1_load_balancer_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
func (x *ServerList) GetServers() []*Server {
|
||||
if x != nil {
|
||||
return x.Servers
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Contains server information. When the drop field is not true, use the other
|
||||
// fields.
|
||||
type Server struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// A resolved address for the server, serialized in network-byte-order. It may
|
||||
// either be an IPv4 or IPv6 address.
|
||||
IpAddress []byte `protobuf:"bytes,1,opt,name=ip_address,json=ipAddress,proto3" json:"ip_address,omitempty"`
|
||||
// A resolved port number for the server.
|
||||
Port int32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"`
|
||||
// An opaque but printable token for load reporting. The client must include
|
||||
// the token of the picked server into the initial metadata when it starts a
|
||||
// call to that server. The token is used by the server to verify the request
|
||||
// and to allow the server to report load to the gRPC LB system. The token is
|
||||
// also used in client stats for reporting dropped calls.
|
||||
//
|
||||
// Its length can be variable but must be less than 50 bytes.
|
||||
LoadBalanceToken string `protobuf:"bytes,3,opt,name=load_balance_token,json=loadBalanceToken,proto3" json:"load_balance_token,omitempty"`
|
||||
// Indicates whether this particular request should be dropped by the client.
|
||||
// If the request is dropped, there will be a corresponding entry in
|
||||
// ClientStats.calls_finished_with_drop.
|
||||
Drop bool `protobuf:"varint,4,opt,name=drop,proto3" json:"drop,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Server) Reset() {
|
||||
*x = Server{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_grpc_lb_v1_load_balancer_proto_msgTypes[8]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Server) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Server) ProtoMessage() {}
|
||||
|
||||
func (x *Server) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_grpc_lb_v1_load_balancer_proto_msgTypes[8]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Server.ProtoReflect.Descriptor instead.
|
||||
func (*Server) Descriptor() ([]byte, []int) {
|
||||
return file_grpc_lb_v1_load_balancer_proto_rawDescGZIP(), []int{8}
|
||||
}
|
||||
|
||||
func (x *Server) GetIpAddress() []byte {
|
||||
if x != nil {
|
||||
return x.IpAddress
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Server) GetPort() int32 {
|
||||
if x != nil {
|
||||
return x.Port
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Server) GetLoadBalanceToken() string {
|
||||
if x != nil {
|
||||
return x.LoadBalanceToken
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Server) GetDrop() bool {
|
||||
if x != nil {
|
||||
return x.Drop
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var File_grpc_lb_v1_load_balancer_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_grpc_lb_v1_load_balancer_proto_rawDesc = []byte{
|
||||
0x0a, 0x1e, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x6c, 0x62, 0x2f, 0x76, 0x31, 0x2f, 0x6c, 0x6f, 0x61,
|
||||
0x64, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x12, 0x0a, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x6c, 0x62, 0x2e, 0x76, 0x31, 0x1a, 0x1e, 0x67, 0x6f,
|
||||
0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75,
|
||||
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f,
|
||||
0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69,
|
||||
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc1, 0x01,
|
||||
0x0a, 0x12, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x12, 0x50, 0x0a, 0x0f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f,
|
||||
0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e,
|
||||
0x67, 0x72, 0x70, 0x63, 0x2e, 0x6c, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x69,
|
||||
0x61, 0x6c, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
|
||||
0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67,
|
||||
0x72, 0x70, 0x63, 0x2e, 0x6c, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74,
|
||||
0x53, 0x74, 0x61, 0x74, 0x73, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53,
|
||||
0x74, 0x61, 0x74, 0x73, 0x42, 0x1b, 0x0a, 0x19, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x62, 0x61, 0x6c,
|
||||
0x61, 0x6e, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x79, 0x70,
|
||||
0x65, 0x22, 0x2f, 0x0a, 0x19, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x6f, 0x61, 0x64,
|
||||
0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12,
|
||||
0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
|
||||
0x6d, 0x65, 0x22, 0x60, 0x0a, 0x13, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74,
|
||||
0x73, 0x50, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2c, 0x0a, 0x12, 0x6c, 0x6f, 0x61,
|
||||
0x64, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e,
|
||||
0x63, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x75, 0x6d, 0x5f, 0x63,
|
||||
0x61, 0x6c, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6e, 0x75, 0x6d, 0x43,
|
||||
0x61, 0x6c, 0x6c, 0x73, 0x22, 0xb0, 0x03, 0x0a, 0x0b, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53,
|
||||
0x74, 0x61, 0x74, 0x73, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
|
||||
0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
|
||||
0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x2a,
|
||||
0x0a, 0x11, 0x6e, 0x75, 0x6d, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x5f, 0x73, 0x74, 0x61, 0x72,
|
||||
0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6e, 0x75, 0x6d, 0x43, 0x61,
|
||||
0x6c, 0x6c, 0x73, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x6e, 0x75,
|
||||
0x6d, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x5f, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x6e, 0x75, 0x6d, 0x43, 0x61, 0x6c, 0x6c, 0x73,
|
||||
0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x5d, 0x0a, 0x2d, 0x6e, 0x75, 0x6d, 0x5f,
|
||||
0x63, 0x61, 0x6c, 0x6c, 0x73, 0x5f, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x5f, 0x77,
|
||||
0x69, 0x74, 0x68, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x65,
|
||||
0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x73, 0x65, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52,
|
||||
0x26, 0x6e, 0x75, 0x6d, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65,
|
||||
0x64, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x65,
|
||||
0x64, 0x54, 0x6f, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x48, 0x0a, 0x21, 0x6e, 0x75, 0x6d, 0x5f, 0x63,
|
||||
0x61, 0x6c, 0x6c, 0x73, 0x5f, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x5f, 0x6b, 0x6e,
|
||||
0x6f, 0x77, 0x6e, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01,
|
||||
0x28, 0x03, 0x52, 0x1d, 0x6e, 0x75, 0x6d, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x46, 0x69, 0x6e, 0x69,
|
||||
0x73, 0x68, 0x65, 0x64, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
|
||||
0x64, 0x12, 0x58, 0x0a, 0x18, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x5f, 0x66, 0x69, 0x6e, 0x69, 0x73,
|
||||
0x68, 0x65, 0x64, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x64, 0x72, 0x6f, 0x70, 0x18, 0x08, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x6c, 0x62, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x50, 0x65, 0x72, 0x54,
|
||||
0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x15, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x46, 0x69, 0x6e, 0x69, 0x73,
|
||||
0x68, 0x65, 0x64, 0x57, 0x69, 0x74, 0x68, 0x44, 0x72, 0x6f, 0x70, 0x4a, 0x04, 0x08, 0x04, 0x10,
|
||||
0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0x90, 0x02, 0x0a, 0x13, 0x4c, 0x6f, 0x61, 0x64,
|
||||
0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x53, 0x0a, 0x10, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x6c, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x6f,
|
||||
0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x48, 0x00, 0x52, 0x0f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6c,
|
||||
0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x6c, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4c, 0x69, 0x73,
|
||||
0x74, 0x48, 0x00, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12,
|
||||
0x4b, 0x0a, 0x11, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x72, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x72, 0x70,
|
||||
0x63, 0x2e, 0x6c, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x10, 0x66, 0x61, 0x6c, 0x6c,
|
||||
0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x1c, 0x0a, 0x1a,
|
||||
0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x12, 0x0a, 0x10, 0x46, 0x61,
|
||||
0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7e,
|
||||
0x0a, 0x1a, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c,
|
||||
0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x1c,
|
||||
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x72, 0x65, 0x70,
|
||||
0x6f, 0x72, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x19, 0x63,
|
||||
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74,
|
||||
0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, 0x40,
|
||||
0x0a, 0x0a, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x07,
|
||||
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e,
|
||||
0x67, 0x72, 0x70, 0x63, 0x2e, 0x6c, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65,
|
||||
0x72, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04,
|
||||
0x22, 0x83, 0x01, 0x0a, 0x06, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x69,
|
||||
0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52,
|
||||
0x09, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f,
|
||||
0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x2c,
|
||||
0x0a, 0x12, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74,
|
||||
0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6c, 0x6f, 0x61, 0x64,
|
||||
0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x12, 0x0a, 0x04,
|
||||
0x64, 0x72, 0x6f, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x64, 0x72, 0x6f, 0x70,
|
||||
0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x32, 0x62, 0x0a, 0x0c, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61,
|
||||
0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0b, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63,
|
||||
0x65, 0x4c, 0x6f, 0x61, 0x64, 0x12, 0x1e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x6c, 0x62, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x6c, 0x62, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x57, 0x0a, 0x0d, 0x69, 0x6f,
|
||||
0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x6c, 0x62, 0x2e, 0x76, 0x31, 0x42, 0x11, 0x4c, 0x6f, 0x61,
|
||||
0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01,
|
||||
0x5a, 0x31, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e,
|
||||
0x6f, 0x72, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65,
|
||||
0x72, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x6c, 0x62, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6c, 0x62,
|
||||
0x5f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_grpc_lb_v1_load_balancer_proto_rawDescOnce sync.Once
|
||||
file_grpc_lb_v1_load_balancer_proto_rawDescData = file_grpc_lb_v1_load_balancer_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_grpc_lb_v1_load_balancer_proto_rawDescGZIP() []byte {
|
||||
file_grpc_lb_v1_load_balancer_proto_rawDescOnce.Do(func() {
|
||||
file_grpc_lb_v1_load_balancer_proto_rawDescData = protoimpl.X.CompressGZIP(file_grpc_lb_v1_load_balancer_proto_rawDescData)
|
||||
})
|
||||
return file_grpc_lb_v1_load_balancer_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_grpc_lb_v1_load_balancer_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
|
||||
var file_grpc_lb_v1_load_balancer_proto_goTypes = []interface{}{
|
||||
(*LoadBalanceRequest)(nil), // 0: grpc.lb.v1.LoadBalanceRequest
|
||||
(*InitialLoadBalanceRequest)(nil), // 1: grpc.lb.v1.InitialLoadBalanceRequest
|
||||
(*ClientStatsPerToken)(nil), // 2: grpc.lb.v1.ClientStatsPerToken
|
||||
(*ClientStats)(nil), // 3: grpc.lb.v1.ClientStats
|
||||
(*LoadBalanceResponse)(nil), // 4: grpc.lb.v1.LoadBalanceResponse
|
||||
(*FallbackResponse)(nil), // 5: grpc.lb.v1.FallbackResponse
|
||||
(*InitialLoadBalanceResponse)(nil), // 6: grpc.lb.v1.InitialLoadBalanceResponse
|
||||
(*ServerList)(nil), // 7: grpc.lb.v1.ServerList
|
||||
(*Server)(nil), // 8: grpc.lb.v1.Server
|
||||
(*timestamppb.Timestamp)(nil), // 9: google.protobuf.Timestamp
|
||||
(*durationpb.Duration)(nil), // 10: google.protobuf.Duration
|
||||
}
|
||||
var file_grpc_lb_v1_load_balancer_proto_depIdxs = []int32{
|
||||
1, // 0: grpc.lb.v1.LoadBalanceRequest.initial_request:type_name -> grpc.lb.v1.InitialLoadBalanceRequest
|
||||
3, // 1: grpc.lb.v1.LoadBalanceRequest.client_stats:type_name -> grpc.lb.v1.ClientStats
|
||||
9, // 2: grpc.lb.v1.ClientStats.timestamp:type_name -> google.protobuf.Timestamp
|
||||
2, // 3: grpc.lb.v1.ClientStats.calls_finished_with_drop:type_name -> grpc.lb.v1.ClientStatsPerToken
|
||||
6, // 4: grpc.lb.v1.LoadBalanceResponse.initial_response:type_name -> grpc.lb.v1.InitialLoadBalanceResponse
|
||||
7, // 5: grpc.lb.v1.LoadBalanceResponse.server_list:type_name -> grpc.lb.v1.ServerList
|
||||
5, // 6: grpc.lb.v1.LoadBalanceResponse.fallback_response:type_name -> grpc.lb.v1.FallbackResponse
|
||||
10, // 7: grpc.lb.v1.InitialLoadBalanceResponse.client_stats_report_interval:type_name -> google.protobuf.Duration
|
||||
8, // 8: grpc.lb.v1.ServerList.servers:type_name -> grpc.lb.v1.Server
|
||||
0, // 9: grpc.lb.v1.LoadBalancer.BalanceLoad:input_type -> grpc.lb.v1.LoadBalanceRequest
|
||||
4, // 10: grpc.lb.v1.LoadBalancer.BalanceLoad:output_type -> grpc.lb.v1.LoadBalanceResponse
|
||||
10, // [10:11] is the sub-list for method output_type
|
||||
9, // [9:10] is the sub-list for method input_type
|
||||
9, // [9:9] is the sub-list for extension type_name
|
||||
9, // [9:9] is the sub-list for extension extendee
|
||||
0, // [0:9] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_grpc_lb_v1_load_balancer_proto_init() }
|
||||
func file_grpc_lb_v1_load_balancer_proto_init() {
|
||||
if File_grpc_lb_v1_load_balancer_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_grpc_lb_v1_load_balancer_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*LoadBalanceRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_grpc_lb_v1_load_balancer_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*InitialLoadBalanceRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_grpc_lb_v1_load_balancer_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ClientStatsPerToken); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_grpc_lb_v1_load_balancer_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ClientStats); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_grpc_lb_v1_load_balancer_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*LoadBalanceResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_grpc_lb_v1_load_balancer_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*FallbackResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_grpc_lb_v1_load_balancer_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*InitialLoadBalanceResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_grpc_lb_v1_load_balancer_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ServerList); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_grpc_lb_v1_load_balancer_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Server); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
file_grpc_lb_v1_load_balancer_proto_msgTypes[0].OneofWrappers = []interface{}{
|
||||
(*LoadBalanceRequest_InitialRequest)(nil),
|
||||
(*LoadBalanceRequest_ClientStats)(nil),
|
||||
}
|
||||
file_grpc_lb_v1_load_balancer_proto_msgTypes[4].OneofWrappers = []interface{}{
|
||||
(*LoadBalanceResponse_InitialResponse)(nil),
|
||||
(*LoadBalanceResponse_ServerList)(nil),
|
||||
(*LoadBalanceResponse_FallbackResponse)(nil),
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_grpc_lb_v1_load_balancer_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 9,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_grpc_lb_v1_load_balancer_proto_goTypes,
|
||||
DependencyIndexes: file_grpc_lb_v1_load_balancer_proto_depIdxs,
|
||||
MessageInfos: file_grpc_lb_v1_load_balancer_proto_msgTypes,
|
||||
}.Build()
|
||||
File_grpc_lb_v1_load_balancer_proto = out.File
|
||||
file_grpc_lb_v1_load_balancer_proto_rawDesc = nil
|
||||
file_grpc_lb_v1_load_balancer_proto_goTypes = nil
|
||||
file_grpc_lb_v1_load_balancer_proto_depIdxs = nil
|
||||
}
|
||||
161
vendor/google.golang.org/grpc/balancer/grpclb/grpc_lb_v1/load_balancer_grpc.pb.go
generated
vendored
Normal file
161
vendor/google.golang.org/grpc/balancer/grpclb/grpc_lb_v1/load_balancer_grpc.pb.go
generated
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
// Copyright 2015 The gRPC Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This file defines the GRPCLB LoadBalancing protocol.
|
||||
//
|
||||
// The canonical version of this proto can be found at
|
||||
// https://github.com/grpc/grpc-proto/blob/master/grpc/lb/v1/load_balancer.proto
|
||||
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc v4.25.2
|
||||
// source: grpc/lb/v1/load_balancer.proto
|
||||
|
||||
package grpc_lb_v1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.62.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion8
|
||||
|
||||
const (
|
||||
LoadBalancer_BalanceLoad_FullMethodName = "/grpc.lb.v1.LoadBalancer/BalanceLoad"
|
||||
)
|
||||
|
||||
// LoadBalancerClient is the client API for LoadBalancer service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type LoadBalancerClient interface {
|
||||
// Bidirectional rpc to get a list of servers.
|
||||
BalanceLoad(ctx context.Context, opts ...grpc.CallOption) (LoadBalancer_BalanceLoadClient, error)
|
||||
}
|
||||
|
||||
type loadBalancerClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewLoadBalancerClient(cc grpc.ClientConnInterface) LoadBalancerClient {
|
||||
return &loadBalancerClient{cc}
|
||||
}
|
||||
|
||||
func (c *loadBalancerClient) BalanceLoad(ctx context.Context, opts ...grpc.CallOption) (LoadBalancer_BalanceLoadClient, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &LoadBalancer_ServiceDesc.Streams[0], LoadBalancer_BalanceLoad_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &loadBalancerBalanceLoadClient{ClientStream: stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type LoadBalancer_BalanceLoadClient interface {
|
||||
Send(*LoadBalanceRequest) error
|
||||
Recv() (*LoadBalanceResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type loadBalancerBalanceLoadClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *loadBalancerBalanceLoadClient) Send(m *LoadBalanceRequest) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *loadBalancerBalanceLoadClient) Recv() (*LoadBalanceResponse, error) {
|
||||
m := new(LoadBalanceResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// LoadBalancerServer is the server API for LoadBalancer service.
|
||||
// All implementations should embed UnimplementedLoadBalancerServer
|
||||
// for forward compatibility
|
||||
type LoadBalancerServer interface {
|
||||
// Bidirectional rpc to get a list of servers.
|
||||
BalanceLoad(LoadBalancer_BalanceLoadServer) error
|
||||
}
|
||||
|
||||
// UnimplementedLoadBalancerServer should be embedded to have forward compatible implementations.
|
||||
type UnimplementedLoadBalancerServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedLoadBalancerServer) BalanceLoad(LoadBalancer_BalanceLoadServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method BalanceLoad not implemented")
|
||||
}
|
||||
|
||||
// UnsafeLoadBalancerServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to LoadBalancerServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeLoadBalancerServer interface {
|
||||
mustEmbedUnimplementedLoadBalancerServer()
|
||||
}
|
||||
|
||||
func RegisterLoadBalancerServer(s grpc.ServiceRegistrar, srv LoadBalancerServer) {
|
||||
s.RegisterService(&LoadBalancer_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _LoadBalancer_BalanceLoad_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(LoadBalancerServer).BalanceLoad(&loadBalancerBalanceLoadServer{ServerStream: stream})
|
||||
}
|
||||
|
||||
type LoadBalancer_BalanceLoadServer interface {
|
||||
Send(*LoadBalanceResponse) error
|
||||
Recv() (*LoadBalanceRequest, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type loadBalancerBalanceLoadServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *loadBalancerBalanceLoadServer) Send(m *LoadBalanceResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *loadBalancerBalanceLoadServer) Recv() (*LoadBalanceRequest, error) {
|
||||
m := new(LoadBalanceRequest)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// LoadBalancer_ServiceDesc is the grpc.ServiceDesc for LoadBalancer service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var LoadBalancer_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "grpc.lb.v1.LoadBalancer",
|
||||
HandlerType: (*LoadBalancerServer)(nil),
|
||||
Methods: []grpc.MethodDesc{},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "BalanceLoad",
|
||||
Handler: _LoadBalancer_BalanceLoad_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "grpc/lb/v1/load_balancer.proto",
|
||||
}
|
||||
535
vendor/google.golang.org/grpc/balancer/grpclb/grpclb.go
generated
vendored
Normal file
535
vendor/google.golang.org/grpc/balancer/grpclb/grpclb.go
generated
vendored
Normal file
@@ -0,0 +1,535 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2016 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package grpclb defines a grpclb balancer.
|
||||
//
|
||||
// To install grpclb balancer, import this package as:
|
||||
//
|
||||
// import _ "google.golang.org/grpc/balancer/grpclb"
|
||||
package grpclb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/balancer/base"
|
||||
grpclbstate "google.golang.org/grpc/balancer/grpclb/state"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/internal"
|
||||
"google.golang.org/grpc/internal/backoff"
|
||||
internalgrpclog "google.golang.org/grpc/internal/grpclog"
|
||||
"google.golang.org/grpc/internal/pretty"
|
||||
"google.golang.org/grpc/internal/resolver/dns"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"google.golang.org/grpc/resolver/manual"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
|
||||
lbpb "google.golang.org/grpc/balancer/grpclb/grpc_lb_v1"
|
||||
)
|
||||
|
||||
const (
|
||||
lbTokenKey = "lb-token"
|
||||
defaultFallbackTimeout = 10 * time.Second
|
||||
grpclbName = "grpclb"
|
||||
)
|
||||
|
||||
var errServerTerminatedConnection = errors.New("grpclb: failed to recv server list: server terminated connection")
|
||||
var logger = grpclog.Component("grpclb")
|
||||
|
||||
func convertDuration(d *durationpb.Duration) time.Duration {
|
||||
if d == nil {
|
||||
return 0
|
||||
}
|
||||
return time.Duration(d.Seconds)*time.Second + time.Duration(d.Nanos)*time.Nanosecond
|
||||
}
|
||||
|
||||
// Client API for LoadBalancer service.
|
||||
// Mostly copied from generated pb.go file.
|
||||
// To avoid circular dependency.
|
||||
type loadBalancerClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func (c *loadBalancerClient) BalanceLoad(ctx context.Context, opts ...grpc.CallOption) (*balanceLoadClientStream, error) {
|
||||
desc := &grpc.StreamDesc{
|
||||
StreamName: "BalanceLoad",
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
}
|
||||
stream, err := c.cc.NewStream(ctx, desc, "/grpc.lb.v1.LoadBalancer/BalanceLoad", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &balanceLoadClientStream{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type balanceLoadClientStream struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *balanceLoadClientStream) Send(m *lbpb.LoadBalanceRequest) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *balanceLoadClientStream) Recv() (*lbpb.LoadBalanceResponse, error) {
|
||||
m := new(lbpb.LoadBalanceResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
balancer.Register(newLBBuilder())
|
||||
dns.EnableSRVLookups = true
|
||||
}
|
||||
|
||||
// newLBBuilder creates a builder for grpclb.
|
||||
func newLBBuilder() balancer.Builder {
|
||||
return newLBBuilderWithFallbackTimeout(defaultFallbackTimeout)
|
||||
}
|
||||
|
||||
// newLBBuilderWithFallbackTimeout creates a grpclb builder with the given
|
||||
// fallbackTimeout. If no response is received from the remote balancer within
|
||||
// fallbackTimeout, the backend addresses from the resolved address list will be
|
||||
// used.
|
||||
//
|
||||
// Only call this function when a non-default fallback timeout is needed.
|
||||
func newLBBuilderWithFallbackTimeout(fallbackTimeout time.Duration) balancer.Builder {
|
||||
return &lbBuilder{
|
||||
fallbackTimeout: fallbackTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
type lbBuilder struct {
|
||||
fallbackTimeout time.Duration
|
||||
}
|
||||
|
||||
func (b *lbBuilder) Name() string {
|
||||
return grpclbName
|
||||
}
|
||||
|
||||
func (b *lbBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer {
|
||||
// This generates a manual resolver builder with a fixed scheme. This
|
||||
// scheme will be used to dial to remote LB, so we can send filtered
|
||||
// address updates to remote LB ClientConn using this manual resolver.
|
||||
mr := manual.NewBuilderWithScheme("grpclb-internal")
|
||||
// ResolveNow() on this manual resolver is forwarded to the parent
|
||||
// ClientConn, so when grpclb client loses contact with the remote balancer,
|
||||
// the parent ClientConn's resolver will re-resolve.
|
||||
mr.ResolveNowCallback = cc.ResolveNow
|
||||
|
||||
lb := &lbBalancer{
|
||||
cc: newLBCacheClientConn(cc),
|
||||
dialTarget: opt.Target.Endpoint(),
|
||||
target: opt.Target.Endpoint(),
|
||||
opt: opt,
|
||||
fallbackTimeout: b.fallbackTimeout,
|
||||
doneCh: make(chan struct{}),
|
||||
|
||||
manualResolver: mr,
|
||||
subConns: make(map[resolver.Address]balancer.SubConn),
|
||||
scStates: make(map[balancer.SubConn]connectivity.State),
|
||||
picker: base.NewErrPicker(balancer.ErrNoSubConnAvailable),
|
||||
clientStats: newRPCStats(),
|
||||
backoff: backoff.DefaultExponential, // TODO: make backoff configurable.
|
||||
}
|
||||
lb.logger = internalgrpclog.NewPrefixLogger(logger, fmt.Sprintf("[grpclb %p] ", lb))
|
||||
|
||||
var err error
|
||||
if opt.CredsBundle != nil {
|
||||
lb.grpclbClientConnCreds, err = opt.CredsBundle.NewWithMode(internal.CredsBundleModeBalancer)
|
||||
if err != nil {
|
||||
lb.logger.Warningf("Failed to create credentials used for connecting to grpclb: %v", err)
|
||||
}
|
||||
lb.grpclbBackendCreds, err = opt.CredsBundle.NewWithMode(internal.CredsBundleModeBackendFromBalancer)
|
||||
if err != nil {
|
||||
lb.logger.Warningf("Failed to create credentials used for connecting to backends returned by grpclb: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return lb
|
||||
}
|
||||
|
||||
type lbBalancer struct {
|
||||
cc *lbCacheClientConn
|
||||
dialTarget string // user's dial target
|
||||
target string // same as dialTarget unless overridden in service config
|
||||
opt balancer.BuildOptions
|
||||
logger *internalgrpclog.PrefixLogger
|
||||
|
||||
usePickFirst bool
|
||||
|
||||
// grpclbClientConnCreds is the creds bundle to be used to connect to grpclb
|
||||
// servers. If it's nil, use the TransportCredentials from BuildOptions
|
||||
// instead.
|
||||
grpclbClientConnCreds credentials.Bundle
|
||||
// grpclbBackendCreds is the creds bundle to be used for addresses that are
|
||||
// returned by grpclb server. If it's nil, don't set anything when creating
|
||||
// SubConns.
|
||||
grpclbBackendCreds credentials.Bundle
|
||||
|
||||
fallbackTimeout time.Duration
|
||||
doneCh chan struct{}
|
||||
|
||||
// manualResolver is used in the remote LB ClientConn inside grpclb. When
|
||||
// resolved address updates are received by grpclb, filtered updates will be
|
||||
// send to remote LB ClientConn through this resolver.
|
||||
manualResolver *manual.Resolver
|
||||
// The ClientConn to talk to the remote balancer.
|
||||
ccRemoteLB *remoteBalancerCCWrapper
|
||||
// backoff for calling remote balancer.
|
||||
backoff backoff.Strategy
|
||||
|
||||
// Support client side load reporting. Each picker gets a reference to this,
|
||||
// and will update its content.
|
||||
clientStats *rpcStats
|
||||
|
||||
mu sync.Mutex // guards everything following.
|
||||
// The full server list including drops, used to check if the newly received
|
||||
// serverList contains anything new. Each generate picker will also have
|
||||
// reference to this list to do the first layer pick.
|
||||
fullServerList []*lbpb.Server
|
||||
// Backend addresses. It's kept so the addresses are available when
|
||||
// switching between round_robin and pickfirst.
|
||||
backendAddrs []resolver.Address
|
||||
// All backends addresses, with metadata set to nil. This list contains all
|
||||
// backend addresses in the same order and with the same duplicates as in
|
||||
// serverlist. When generating picker, a SubConn slice with the same order
|
||||
// but with only READY SCs will be gerenated.
|
||||
backendAddrsWithoutMetadata []resolver.Address
|
||||
// Roundrobin functionalities.
|
||||
state connectivity.State
|
||||
subConns map[resolver.Address]balancer.SubConn // Used to new/shutdown SubConn.
|
||||
scStates map[balancer.SubConn]connectivity.State // Used to filter READY SubConns.
|
||||
picker balancer.Picker
|
||||
// Support fallback to resolved backend addresses if there's no response
|
||||
// from remote balancer within fallbackTimeout.
|
||||
remoteBalancerConnected bool
|
||||
serverListReceived bool
|
||||
inFallback bool
|
||||
// resolvedBackendAddrs is resolvedAddrs minus remote balancers. It's set
|
||||
// when resolved address updates are received, and read in the goroutine
|
||||
// handling fallback.
|
||||
resolvedBackendAddrs []resolver.Address
|
||||
connErr error // the last connection error
|
||||
}
|
||||
|
||||
// regeneratePicker takes a snapshot of the balancer, and generates a picker from
|
||||
// it. The picker
|
||||
// - always returns ErrTransientFailure if the balancer is in TransientFailure,
|
||||
// - does two layer roundrobin pick otherwise.
|
||||
//
|
||||
// Caller must hold lb.mu.
|
||||
func (lb *lbBalancer) regeneratePicker(resetDrop bool) {
|
||||
if lb.state == connectivity.TransientFailure {
|
||||
lb.picker = base.NewErrPicker(fmt.Errorf("all SubConns are in TransientFailure, last connection error: %v", lb.connErr))
|
||||
return
|
||||
}
|
||||
|
||||
if lb.state == connectivity.Connecting {
|
||||
lb.picker = base.NewErrPicker(balancer.ErrNoSubConnAvailable)
|
||||
return
|
||||
}
|
||||
|
||||
var readySCs []balancer.SubConn
|
||||
if lb.usePickFirst {
|
||||
for _, sc := range lb.subConns {
|
||||
readySCs = append(readySCs, sc)
|
||||
break
|
||||
}
|
||||
} else {
|
||||
for _, a := range lb.backendAddrsWithoutMetadata {
|
||||
if sc, ok := lb.subConns[a]; ok {
|
||||
if st, ok := lb.scStates[sc]; ok && st == connectivity.Ready {
|
||||
readySCs = append(readySCs, sc)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(readySCs) <= 0 {
|
||||
// If there's no ready SubConns, always re-pick. This is to avoid drops
|
||||
// unless at least one SubConn is ready. Otherwise we may drop more
|
||||
// often than want because of drops + re-picks(which become re-drops).
|
||||
//
|
||||
// This doesn't seem to be necessary after the connecting check above.
|
||||
// Kept for safety.
|
||||
lb.picker = base.NewErrPicker(balancer.ErrNoSubConnAvailable)
|
||||
return
|
||||
}
|
||||
if lb.inFallback {
|
||||
lb.picker = newRRPicker(readySCs)
|
||||
return
|
||||
}
|
||||
if resetDrop {
|
||||
lb.picker = newLBPicker(lb.fullServerList, readySCs, lb.clientStats)
|
||||
return
|
||||
}
|
||||
prevLBPicker, ok := lb.picker.(*lbPicker)
|
||||
if !ok {
|
||||
lb.picker = newLBPicker(lb.fullServerList, readySCs, lb.clientStats)
|
||||
return
|
||||
}
|
||||
prevLBPicker.updateReadySCs(readySCs)
|
||||
}
|
||||
|
||||
// aggregateSubConnStats calculate the aggregated state of SubConns in
|
||||
// lb.SubConns. These SubConns are subconns in use (when switching between
|
||||
// fallback and grpclb). lb.scState contains states for all SubConns, including
|
||||
// those in cache (SubConns are cached for 10 seconds after shutdown).
|
||||
//
|
||||
// The aggregated state is:
|
||||
// - If at least one SubConn in Ready, the aggregated state is Ready;
|
||||
// - Else if at least one SubConn in Connecting or IDLE, the aggregated state is Connecting;
|
||||
// - It's OK to consider IDLE as Connecting. SubConns never stay in IDLE,
|
||||
// they start to connect immediately. But there's a race between the overall
|
||||
// state is reported, and when the new SubConn state arrives. And SubConns
|
||||
// never go back to IDLE.
|
||||
// - Else the aggregated state is TransientFailure.
|
||||
func (lb *lbBalancer) aggregateSubConnStates() connectivity.State {
|
||||
var numConnecting uint64
|
||||
|
||||
for _, sc := range lb.subConns {
|
||||
if state, ok := lb.scStates[sc]; ok {
|
||||
switch state {
|
||||
case connectivity.Ready:
|
||||
return connectivity.Ready
|
||||
case connectivity.Connecting, connectivity.Idle:
|
||||
numConnecting++
|
||||
}
|
||||
}
|
||||
}
|
||||
if numConnecting > 0 {
|
||||
return connectivity.Connecting
|
||||
}
|
||||
return connectivity.TransientFailure
|
||||
}
|
||||
|
||||
// UpdateSubConnState is unused; NewSubConn's options always specifies
|
||||
// updateSubConnState as the listener.
|
||||
func (lb *lbBalancer) UpdateSubConnState(sc balancer.SubConn, scs balancer.SubConnState) {
|
||||
lb.logger.Errorf("UpdateSubConnState(%v, %+v) called unexpectedly", sc, scs)
|
||||
}
|
||||
|
||||
func (lb *lbBalancer) updateSubConnState(sc balancer.SubConn, scs balancer.SubConnState) {
|
||||
s := scs.ConnectivityState
|
||||
if lb.logger.V(2) {
|
||||
lb.logger.Infof("SubConn state change: %p, %v", sc, s)
|
||||
}
|
||||
lb.mu.Lock()
|
||||
defer lb.mu.Unlock()
|
||||
|
||||
oldS, ok := lb.scStates[sc]
|
||||
if !ok {
|
||||
if lb.logger.V(2) {
|
||||
lb.logger.Infof("Received state change for an unknown SubConn: %p, %v", sc, s)
|
||||
}
|
||||
return
|
||||
}
|
||||
lb.scStates[sc] = s
|
||||
switch s {
|
||||
case connectivity.Idle:
|
||||
sc.Connect()
|
||||
case connectivity.Shutdown:
|
||||
// When an address was removed by resolver, b called Shutdown but kept
|
||||
// the sc's state in scStates. Remove state for this sc here.
|
||||
delete(lb.scStates, sc)
|
||||
case connectivity.TransientFailure:
|
||||
lb.connErr = scs.ConnectionError
|
||||
}
|
||||
// Force regenerate picker if
|
||||
// - this sc became ready from not-ready
|
||||
// - this sc became not-ready from ready
|
||||
lb.updateStateAndPicker((oldS == connectivity.Ready) != (s == connectivity.Ready), false)
|
||||
|
||||
// Enter fallback when the aggregated state is not Ready and the connection
|
||||
// to remote balancer is lost.
|
||||
if lb.state != connectivity.Ready {
|
||||
if !lb.inFallback && !lb.remoteBalancerConnected {
|
||||
// Enter fallback.
|
||||
lb.refreshSubConns(lb.resolvedBackendAddrs, true, lb.usePickFirst)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// updateStateAndPicker re-calculate the aggregated state, and regenerate picker
|
||||
// if overall state is changed.
|
||||
//
|
||||
// If forceRegeneratePicker is true, picker will be regenerated.
|
||||
func (lb *lbBalancer) updateStateAndPicker(forceRegeneratePicker bool, resetDrop bool) {
|
||||
oldAggrState := lb.state
|
||||
lb.state = lb.aggregateSubConnStates()
|
||||
// Regenerate picker when one of the following happens:
|
||||
// - caller wants to regenerate
|
||||
// - the aggregated state changed
|
||||
if forceRegeneratePicker || (lb.state != oldAggrState) {
|
||||
lb.regeneratePicker(resetDrop)
|
||||
}
|
||||
var cc balancer.ClientConn = lb.cc
|
||||
if lb.usePickFirst {
|
||||
// Bypass the caching layer that would wrap the picker.
|
||||
cc = lb.cc.ClientConn
|
||||
}
|
||||
|
||||
cc.UpdateState(balancer.State{ConnectivityState: lb.state, Picker: lb.picker})
|
||||
}
|
||||
|
||||
// fallbackToBackendsAfter blocks for fallbackTimeout and falls back to use
|
||||
// resolved backends (backends received from resolver, not from remote balancer)
|
||||
// if no connection to remote balancers was successful.
|
||||
func (lb *lbBalancer) fallbackToBackendsAfter(fallbackTimeout time.Duration) {
|
||||
timer := time.NewTimer(fallbackTimeout)
|
||||
defer timer.Stop()
|
||||
select {
|
||||
case <-timer.C:
|
||||
case <-lb.doneCh:
|
||||
return
|
||||
}
|
||||
lb.mu.Lock()
|
||||
if lb.inFallback || lb.serverListReceived {
|
||||
lb.mu.Unlock()
|
||||
return
|
||||
}
|
||||
// Enter fallback.
|
||||
lb.refreshSubConns(lb.resolvedBackendAddrs, true, lb.usePickFirst)
|
||||
lb.mu.Unlock()
|
||||
}
|
||||
|
||||
func (lb *lbBalancer) handleServiceConfig(gc *grpclbServiceConfig) {
|
||||
lb.mu.Lock()
|
||||
defer lb.mu.Unlock()
|
||||
|
||||
// grpclb uses the user's dial target to populate the `Name` field of the
|
||||
// `InitialLoadBalanceRequest` message sent to the remote balancer. But when
|
||||
// grpclb is used a child policy in the context of RLS, we want the `Name`
|
||||
// field to be populated with the value received from the RLS server. To
|
||||
// support this use case, an optional "target_name" field has been added to
|
||||
// the grpclb LB policy's config. If specified, it overrides the name of
|
||||
// the target to be sent to the remote balancer; if not, the target to be
|
||||
// sent to the balancer will continue to be obtained from the target URI
|
||||
// passed to the gRPC client channel. Whenever that target to be sent to the
|
||||
// balancer is updated, we need to restart the stream to the balancer as
|
||||
// this target is sent in the first message on the stream.
|
||||
if gc != nil {
|
||||
target := lb.dialTarget
|
||||
if gc.ServiceName != "" {
|
||||
target = gc.ServiceName
|
||||
}
|
||||
if target != lb.target {
|
||||
lb.target = target
|
||||
if lb.ccRemoteLB != nil {
|
||||
lb.ccRemoteLB.cancelRemoteBalancerCall()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newUsePickFirst := childIsPickFirst(gc)
|
||||
if lb.usePickFirst == newUsePickFirst {
|
||||
return
|
||||
}
|
||||
if lb.logger.V(2) {
|
||||
lb.logger.Infof("Switching mode. Is pick_first used for backends? %v", newUsePickFirst)
|
||||
}
|
||||
lb.refreshSubConns(lb.backendAddrs, lb.inFallback, newUsePickFirst)
|
||||
}
|
||||
|
||||
func (lb *lbBalancer) ResolverError(error) {
|
||||
// Ignore resolver errors. GRPCLB is not selected unless the resolver
|
||||
// works at least once.
|
||||
}
|
||||
|
||||
func (lb *lbBalancer) UpdateClientConnState(ccs balancer.ClientConnState) error {
|
||||
if lb.logger.V(2) {
|
||||
lb.logger.Infof("UpdateClientConnState: %s", pretty.ToJSON(ccs))
|
||||
}
|
||||
gc, _ := ccs.BalancerConfig.(*grpclbServiceConfig)
|
||||
lb.handleServiceConfig(gc)
|
||||
|
||||
backendAddrs := ccs.ResolverState.Addresses
|
||||
|
||||
var remoteBalancerAddrs []resolver.Address
|
||||
if sd := grpclbstate.Get(ccs.ResolverState); sd != nil {
|
||||
// Override any balancer addresses provided via
|
||||
// ccs.ResolverState.Addresses.
|
||||
remoteBalancerAddrs = sd.BalancerAddresses
|
||||
}
|
||||
|
||||
if len(backendAddrs)+len(remoteBalancerAddrs) == 0 {
|
||||
// There should be at least one address, either grpclb server or
|
||||
// fallback. Empty address is not valid.
|
||||
return balancer.ErrBadResolverState
|
||||
}
|
||||
|
||||
if len(remoteBalancerAddrs) == 0 {
|
||||
if lb.ccRemoteLB != nil {
|
||||
lb.ccRemoteLB.close()
|
||||
lb.ccRemoteLB = nil
|
||||
}
|
||||
} else if lb.ccRemoteLB == nil {
|
||||
// First time receiving resolved addresses, create a cc to remote
|
||||
// balancers.
|
||||
if err := lb.newRemoteBalancerCCWrapper(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Start the fallback goroutine.
|
||||
go lb.fallbackToBackendsAfter(lb.fallbackTimeout)
|
||||
}
|
||||
|
||||
if lb.ccRemoteLB != nil {
|
||||
// cc to remote balancers uses lb.manualResolver. Send the updated remote
|
||||
// balancer addresses to it through manualResolver.
|
||||
lb.manualResolver.UpdateState(resolver.State{Addresses: remoteBalancerAddrs})
|
||||
}
|
||||
|
||||
lb.mu.Lock()
|
||||
lb.resolvedBackendAddrs = backendAddrs
|
||||
if len(remoteBalancerAddrs) == 0 || lb.inFallback {
|
||||
// If there's no remote balancer address in ClientConn update, grpclb
|
||||
// enters fallback mode immediately.
|
||||
//
|
||||
// If a new update is received while grpclb is in fallback, update the
|
||||
// list of backends being used to the new fallback backends.
|
||||
lb.refreshSubConns(lb.resolvedBackendAddrs, true, lb.usePickFirst)
|
||||
}
|
||||
lb.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lb *lbBalancer) Close() {
|
||||
select {
|
||||
case <-lb.doneCh:
|
||||
return
|
||||
default:
|
||||
}
|
||||
close(lb.doneCh)
|
||||
if lb.ccRemoteLB != nil {
|
||||
lb.ccRemoteLB.close()
|
||||
}
|
||||
lb.cc.close()
|
||||
}
|
||||
|
||||
func (lb *lbBalancer) ExitIdle() {}
|
||||
67
vendor/google.golang.org/grpc/balancer/grpclb/grpclb_config.go
generated
vendored
Normal file
67
vendor/google.golang.org/grpc/balancer/grpclb/grpclb_config.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2019 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpclb
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/balancer/roundrobin"
|
||||
"google.golang.org/grpc/serviceconfig"
|
||||
)
|
||||
|
||||
const (
|
||||
roundRobinName = roundrobin.Name
|
||||
pickFirstName = grpc.PickFirstBalancerName
|
||||
)
|
||||
|
||||
type grpclbServiceConfig struct {
|
||||
serviceconfig.LoadBalancingConfig
|
||||
ChildPolicy *[]map[string]json.RawMessage
|
||||
ServiceName string
|
||||
}
|
||||
|
||||
func (b *lbBuilder) ParseConfig(lbConfig json.RawMessage) (serviceconfig.LoadBalancingConfig, error) {
|
||||
ret := &grpclbServiceConfig{}
|
||||
if err := json.Unmarshal(lbConfig, ret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func childIsPickFirst(sc *grpclbServiceConfig) bool {
|
||||
if sc == nil {
|
||||
return false
|
||||
}
|
||||
childConfigs := sc.ChildPolicy
|
||||
if childConfigs == nil {
|
||||
return false
|
||||
}
|
||||
for _, childC := range *childConfigs {
|
||||
// If round_robin exists before pick_first, return false
|
||||
if _, ok := childC[roundRobinName]; ok {
|
||||
return false
|
||||
}
|
||||
// If pick_first is before round_robin, return true
|
||||
if _, ok := childC[pickFirstName]; ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
193
vendor/google.golang.org/grpc/balancer/grpclb/grpclb_picker.go
generated
vendored
Normal file
193
vendor/google.golang.org/grpc/balancer/grpclb/grpclb_picker.go
generated
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpclb
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
lbpb "google.golang.org/grpc/balancer/grpclb/grpc_lb_v1"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/internal/grpcrand"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// rpcStats is same as lbpb.ClientStats, except that numCallsDropped is a map
|
||||
// instead of a slice.
|
||||
type rpcStats struct {
|
||||
// Only access the following fields atomically.
|
||||
numCallsStarted int64
|
||||
numCallsFinished int64
|
||||
numCallsFinishedWithClientFailedToSend int64
|
||||
numCallsFinishedKnownReceived int64
|
||||
|
||||
mu sync.Mutex
|
||||
// map load_balance_token -> num_calls_dropped
|
||||
numCallsDropped map[string]int64
|
||||
}
|
||||
|
||||
func newRPCStats() *rpcStats {
|
||||
return &rpcStats{
|
||||
numCallsDropped: make(map[string]int64),
|
||||
}
|
||||
}
|
||||
|
||||
func isZeroStats(stats *lbpb.ClientStats) bool {
|
||||
return len(stats.CallsFinishedWithDrop) == 0 &&
|
||||
stats.NumCallsStarted == 0 &&
|
||||
stats.NumCallsFinished == 0 &&
|
||||
stats.NumCallsFinishedWithClientFailedToSend == 0 &&
|
||||
stats.NumCallsFinishedKnownReceived == 0
|
||||
}
|
||||
|
||||
// toClientStats converts rpcStats to lbpb.ClientStats, and clears rpcStats.
|
||||
func (s *rpcStats) toClientStats() *lbpb.ClientStats {
|
||||
stats := &lbpb.ClientStats{
|
||||
NumCallsStarted: atomic.SwapInt64(&s.numCallsStarted, 0),
|
||||
NumCallsFinished: atomic.SwapInt64(&s.numCallsFinished, 0),
|
||||
NumCallsFinishedWithClientFailedToSend: atomic.SwapInt64(&s.numCallsFinishedWithClientFailedToSend, 0),
|
||||
NumCallsFinishedKnownReceived: atomic.SwapInt64(&s.numCallsFinishedKnownReceived, 0),
|
||||
}
|
||||
s.mu.Lock()
|
||||
dropped := s.numCallsDropped
|
||||
s.numCallsDropped = make(map[string]int64)
|
||||
s.mu.Unlock()
|
||||
for token, count := range dropped {
|
||||
stats.CallsFinishedWithDrop = append(stats.CallsFinishedWithDrop, &lbpb.ClientStatsPerToken{
|
||||
LoadBalanceToken: token,
|
||||
NumCalls: count,
|
||||
})
|
||||
}
|
||||
return stats
|
||||
}
|
||||
|
||||
func (s *rpcStats) drop(token string) {
|
||||
atomic.AddInt64(&s.numCallsStarted, 1)
|
||||
s.mu.Lock()
|
||||
s.numCallsDropped[token]++
|
||||
s.mu.Unlock()
|
||||
atomic.AddInt64(&s.numCallsFinished, 1)
|
||||
}
|
||||
|
||||
func (s *rpcStats) failedToSend() {
|
||||
atomic.AddInt64(&s.numCallsStarted, 1)
|
||||
atomic.AddInt64(&s.numCallsFinishedWithClientFailedToSend, 1)
|
||||
atomic.AddInt64(&s.numCallsFinished, 1)
|
||||
}
|
||||
|
||||
func (s *rpcStats) knownReceived() {
|
||||
atomic.AddInt64(&s.numCallsStarted, 1)
|
||||
atomic.AddInt64(&s.numCallsFinishedKnownReceived, 1)
|
||||
atomic.AddInt64(&s.numCallsFinished, 1)
|
||||
}
|
||||
|
||||
// rrPicker does roundrobin on subConns. It's typically used when there's no
|
||||
// response from remote balancer, and grpclb falls back to the resolved
|
||||
// backends.
|
||||
//
|
||||
// It guaranteed that len(subConns) > 0.
|
||||
type rrPicker struct {
|
||||
mu sync.Mutex
|
||||
subConns []balancer.SubConn // The subConns that were READY when taking the snapshot.
|
||||
subConnsNext int
|
||||
}
|
||||
|
||||
func newRRPicker(readySCs []balancer.SubConn) *rrPicker {
|
||||
return &rrPicker{
|
||||
subConns: readySCs,
|
||||
subConnsNext: grpcrand.Intn(len(readySCs)),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *rrPicker) Pick(balancer.PickInfo) (balancer.PickResult, error) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
sc := p.subConns[p.subConnsNext]
|
||||
p.subConnsNext = (p.subConnsNext + 1) % len(p.subConns)
|
||||
return balancer.PickResult{SubConn: sc}, nil
|
||||
}
|
||||
|
||||
// lbPicker does two layers of picks:
|
||||
//
|
||||
// First layer: roundrobin on all servers in serverList, including drops and backends.
|
||||
// - If it picks a drop, the RPC will fail as being dropped.
|
||||
// - If it picks a backend, do a second layer pick to pick the real backend.
|
||||
//
|
||||
// Second layer: roundrobin on all READY backends.
|
||||
//
|
||||
// It's guaranteed that len(serverList) > 0.
|
||||
type lbPicker struct {
|
||||
mu sync.Mutex
|
||||
serverList []*lbpb.Server
|
||||
serverListNext int
|
||||
subConns []balancer.SubConn // The subConns that were READY when taking the snapshot.
|
||||
subConnsNext int
|
||||
|
||||
stats *rpcStats
|
||||
}
|
||||
|
||||
func newLBPicker(serverList []*lbpb.Server, readySCs []balancer.SubConn, stats *rpcStats) *lbPicker {
|
||||
return &lbPicker{
|
||||
serverList: serverList,
|
||||
subConns: readySCs,
|
||||
subConnsNext: grpcrand.Intn(len(readySCs)),
|
||||
stats: stats,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *lbPicker) Pick(balancer.PickInfo) (balancer.PickResult, error) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
// Layer one roundrobin on serverList.
|
||||
s := p.serverList[p.serverListNext]
|
||||
p.serverListNext = (p.serverListNext + 1) % len(p.serverList)
|
||||
|
||||
// If it's a drop, return an error and fail the RPC.
|
||||
if s.Drop {
|
||||
p.stats.drop(s.LoadBalanceToken)
|
||||
return balancer.PickResult{}, status.Errorf(codes.Unavailable, "request dropped by grpclb")
|
||||
}
|
||||
|
||||
// If not a drop but there's no ready subConns.
|
||||
if len(p.subConns) <= 0 {
|
||||
return balancer.PickResult{}, balancer.ErrNoSubConnAvailable
|
||||
}
|
||||
|
||||
// Return the next ready subConn in the list, also collect rpc stats.
|
||||
sc := p.subConns[p.subConnsNext]
|
||||
p.subConnsNext = (p.subConnsNext + 1) % len(p.subConns)
|
||||
done := func(info balancer.DoneInfo) {
|
||||
if !info.BytesSent {
|
||||
p.stats.failedToSend()
|
||||
} else if info.BytesReceived {
|
||||
p.stats.knownReceived()
|
||||
}
|
||||
}
|
||||
return balancer.PickResult{SubConn: sc, Done: done}, nil
|
||||
}
|
||||
|
||||
func (p *lbPicker) updateReadySCs(readySCs []balancer.SubConn) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
p.subConns = readySCs
|
||||
p.subConnsNext = p.subConnsNext % len(readySCs)
|
||||
}
|
||||
458
vendor/google.golang.org/grpc/balancer/grpclb/grpclb_remote_balancer.go
generated
vendored
Normal file
458
vendor/google.golang.org/grpc/balancer/grpclb/grpclb_remote_balancer.go
generated
vendored
Normal file
@@ -0,0 +1,458 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpclb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/internal/backoff"
|
||||
imetadata "google.golang.org/grpc/internal/metadata"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
lbpb "google.golang.org/grpc/balancer/grpclb/grpc_lb_v1"
|
||||
)
|
||||
|
||||
func serverListEqual(a, b []*lbpb.Server) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < len(a); i++ {
|
||||
if !proto.Equal(a[i], b[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// processServerList updates balancer's internal state, create/remove SubConns
|
||||
// and regenerates picker using the received serverList.
|
||||
func (lb *lbBalancer) processServerList(l *lbpb.ServerList) {
|
||||
if lb.logger.V(2) {
|
||||
lb.logger.Infof("Processing server list: %#v", l)
|
||||
}
|
||||
lb.mu.Lock()
|
||||
defer lb.mu.Unlock()
|
||||
|
||||
// Set serverListReceived to true so fallback will not take effect if it has
|
||||
// not hit timeout.
|
||||
lb.serverListReceived = true
|
||||
|
||||
// If the new server list == old server list, do nothing.
|
||||
if serverListEqual(lb.fullServerList, l.Servers) {
|
||||
if lb.logger.V(2) {
|
||||
lb.logger.Infof("Ignoring new server list as it is the same as the previous one")
|
||||
}
|
||||
return
|
||||
}
|
||||
lb.fullServerList = l.Servers
|
||||
|
||||
var backendAddrs []resolver.Address
|
||||
for i, s := range l.Servers {
|
||||
if s.Drop {
|
||||
continue
|
||||
}
|
||||
|
||||
md := metadata.Pairs(lbTokenKey, s.LoadBalanceToken)
|
||||
ip := net.IP(s.IpAddress)
|
||||
ipStr := ip.String()
|
||||
if ip.To4() == nil {
|
||||
// Add square brackets to ipv6 addresses, otherwise net.Dial() and
|
||||
// net.SplitHostPort() will return too many colons error.
|
||||
ipStr = fmt.Sprintf("[%s]", ipStr)
|
||||
}
|
||||
addr := imetadata.Set(resolver.Address{Addr: fmt.Sprintf("%s:%d", ipStr, s.Port)}, md)
|
||||
if lb.logger.V(2) {
|
||||
lb.logger.Infof("Server list entry:|%d|, ipStr:|%s|, port:|%d|, load balancer token:|%v|", i, ipStr, s.Port, s.LoadBalanceToken)
|
||||
}
|
||||
backendAddrs = append(backendAddrs, addr)
|
||||
}
|
||||
|
||||
// Call refreshSubConns to create/remove SubConns. If we are in fallback,
|
||||
// this is also exiting fallback.
|
||||
lb.refreshSubConns(backendAddrs, false, lb.usePickFirst)
|
||||
}
|
||||
|
||||
// refreshSubConns creates/removes SubConns with backendAddrs, and refreshes
|
||||
// balancer state and picker.
|
||||
//
|
||||
// Caller must hold lb.mu.
|
||||
func (lb *lbBalancer) refreshSubConns(backendAddrs []resolver.Address, fallback bool, pickFirst bool) {
|
||||
opts := balancer.NewSubConnOptions{}
|
||||
if !fallback {
|
||||
opts.CredsBundle = lb.grpclbBackendCreds
|
||||
}
|
||||
|
||||
lb.backendAddrs = backendAddrs
|
||||
lb.backendAddrsWithoutMetadata = nil
|
||||
|
||||
fallbackModeChanged := lb.inFallback != fallback
|
||||
lb.inFallback = fallback
|
||||
if fallbackModeChanged && lb.inFallback {
|
||||
// Clear previous received list when entering fallback, so if the server
|
||||
// comes back and sends the same list again, the new addresses will be
|
||||
// used.
|
||||
lb.fullServerList = nil
|
||||
}
|
||||
|
||||
balancingPolicyChanged := lb.usePickFirst != pickFirst
|
||||
lb.usePickFirst = pickFirst
|
||||
|
||||
if fallbackModeChanged || balancingPolicyChanged {
|
||||
// Remove all SubConns when switching balancing policy or switching
|
||||
// fallback mode.
|
||||
//
|
||||
// For fallback mode switching with pickfirst, we want to recreate the
|
||||
// SubConn because the creds could be different.
|
||||
for a, sc := range lb.subConns {
|
||||
sc.Shutdown()
|
||||
delete(lb.subConns, a)
|
||||
}
|
||||
}
|
||||
|
||||
if lb.usePickFirst {
|
||||
var (
|
||||
scKey resolver.Address
|
||||
sc balancer.SubConn
|
||||
)
|
||||
for scKey, sc = range lb.subConns {
|
||||
break
|
||||
}
|
||||
if sc != nil {
|
||||
if len(backendAddrs) == 0 {
|
||||
sc.Shutdown()
|
||||
delete(lb.subConns, scKey)
|
||||
return
|
||||
}
|
||||
lb.cc.ClientConn.UpdateAddresses(sc, backendAddrs)
|
||||
sc.Connect()
|
||||
return
|
||||
}
|
||||
opts.StateListener = func(scs balancer.SubConnState) { lb.updateSubConnState(sc, scs) }
|
||||
// This bypasses the cc wrapper with SubConn cache.
|
||||
sc, err := lb.cc.ClientConn.NewSubConn(backendAddrs, opts)
|
||||
if err != nil {
|
||||
lb.logger.Warningf("Failed to create new SubConn: %v", err)
|
||||
return
|
||||
}
|
||||
sc.Connect()
|
||||
lb.subConns[backendAddrs[0]] = sc
|
||||
lb.scStates[sc] = connectivity.Idle
|
||||
return
|
||||
}
|
||||
|
||||
// addrsSet is the set converted from backendAddrsWithoutMetadata, it's used to quick
|
||||
// lookup for an address.
|
||||
addrsSet := make(map[resolver.Address]struct{})
|
||||
// Create new SubConns.
|
||||
for _, addr := range backendAddrs {
|
||||
addrWithoutAttrs := addr
|
||||
addrWithoutAttrs.Attributes = nil
|
||||
addrsSet[addrWithoutAttrs] = struct{}{}
|
||||
lb.backendAddrsWithoutMetadata = append(lb.backendAddrsWithoutMetadata, addrWithoutAttrs)
|
||||
|
||||
if _, ok := lb.subConns[addrWithoutAttrs]; !ok {
|
||||
// Use addrWithMD to create the SubConn.
|
||||
var sc balancer.SubConn
|
||||
opts.StateListener = func(scs balancer.SubConnState) { lb.updateSubConnState(sc, scs) }
|
||||
sc, err := lb.cc.NewSubConn([]resolver.Address{addr}, opts)
|
||||
if err != nil {
|
||||
lb.logger.Warningf("Failed to create new SubConn: %v", err)
|
||||
continue
|
||||
}
|
||||
lb.subConns[addrWithoutAttrs] = sc // Use the addr without MD as key for the map.
|
||||
if _, ok := lb.scStates[sc]; !ok {
|
||||
// Only set state of new sc to IDLE. The state could already be
|
||||
// READY for cached SubConns.
|
||||
lb.scStates[sc] = connectivity.Idle
|
||||
}
|
||||
sc.Connect()
|
||||
}
|
||||
}
|
||||
|
||||
for a, sc := range lb.subConns {
|
||||
// a was removed by resolver.
|
||||
if _, ok := addrsSet[a]; !ok {
|
||||
sc.Shutdown()
|
||||
delete(lb.subConns, a)
|
||||
// Keep the state of this sc in b.scStates until sc's state becomes Shutdown.
|
||||
// The entry will be deleted in UpdateSubConnState.
|
||||
}
|
||||
}
|
||||
|
||||
// Regenerate and update picker after refreshing subconns because with
|
||||
// cache, even if SubConn was newed/removed, there might be no state
|
||||
// changes (the subconn will be kept in cache, not actually
|
||||
// newed/removed).
|
||||
lb.updateStateAndPicker(true, true)
|
||||
}
|
||||
|
||||
type remoteBalancerCCWrapper struct {
|
||||
cc *grpc.ClientConn
|
||||
lb *lbBalancer
|
||||
backoff backoff.Strategy
|
||||
done chan struct{}
|
||||
|
||||
streamMu sync.Mutex
|
||||
streamCancel func()
|
||||
|
||||
// waitgroup to wait for all goroutines to exit.
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
func (lb *lbBalancer) newRemoteBalancerCCWrapper() error {
|
||||
var dopts []grpc.DialOption
|
||||
if creds := lb.opt.DialCreds; creds != nil {
|
||||
dopts = append(dopts, grpc.WithTransportCredentials(creds))
|
||||
} else if bundle := lb.grpclbClientConnCreds; bundle != nil {
|
||||
dopts = append(dopts, grpc.WithCredentialsBundle(bundle))
|
||||
} else {
|
||||
dopts = append(dopts, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
}
|
||||
if lb.opt.Dialer != nil {
|
||||
dopts = append(dopts, grpc.WithContextDialer(lb.opt.Dialer))
|
||||
}
|
||||
if lb.opt.CustomUserAgent != "" {
|
||||
dopts = append(dopts, grpc.WithUserAgent(lb.opt.CustomUserAgent))
|
||||
}
|
||||
// Explicitly set pickfirst as the balancer.
|
||||
dopts = append(dopts, grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy":"pick_first"}`))
|
||||
dopts = append(dopts, grpc.WithResolvers(lb.manualResolver))
|
||||
dopts = append(dopts, grpc.WithChannelzParentID(lb.opt.ChannelzParent))
|
||||
|
||||
// Enable Keepalive for grpclb client.
|
||||
dopts = append(dopts, grpc.WithKeepaliveParams(keepalive.ClientParameters{
|
||||
Time: 20 * time.Second,
|
||||
Timeout: 10 * time.Second,
|
||||
PermitWithoutStream: true,
|
||||
}))
|
||||
|
||||
// The dial target is not important.
|
||||
//
|
||||
// The grpclb server addresses will set field ServerName, and creds will
|
||||
// receive ServerName as authority.
|
||||
target := lb.manualResolver.Scheme() + ":///grpclb.subClientConn"
|
||||
cc, err := grpc.Dial(target, dopts...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("grpc.Dial(%s): %v", target, err)
|
||||
}
|
||||
ccw := &remoteBalancerCCWrapper{
|
||||
cc: cc,
|
||||
lb: lb,
|
||||
backoff: lb.backoff,
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
lb.ccRemoteLB = ccw
|
||||
ccw.wg.Add(1)
|
||||
go ccw.watchRemoteBalancer()
|
||||
return nil
|
||||
}
|
||||
|
||||
// close closed the ClientConn to remote balancer, and waits until all
|
||||
// goroutines to finish.
|
||||
func (ccw *remoteBalancerCCWrapper) close() {
|
||||
close(ccw.done)
|
||||
ccw.cc.Close()
|
||||
ccw.wg.Wait()
|
||||
}
|
||||
|
||||
func (ccw *remoteBalancerCCWrapper) readServerList(s *balanceLoadClientStream) error {
|
||||
for {
|
||||
reply, err := s.Recv()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return errServerTerminatedConnection
|
||||
}
|
||||
return fmt.Errorf("grpclb: failed to recv server list: %v", err)
|
||||
}
|
||||
if serverList := reply.GetServerList(); serverList != nil {
|
||||
ccw.lb.processServerList(serverList)
|
||||
}
|
||||
if reply.GetFallbackResponse() != nil {
|
||||
// Eagerly enter fallback
|
||||
ccw.lb.mu.Lock()
|
||||
ccw.lb.refreshSubConns(ccw.lb.resolvedBackendAddrs, true, ccw.lb.usePickFirst)
|
||||
ccw.lb.mu.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ccw *remoteBalancerCCWrapper) sendLoadReport(s *balanceLoadClientStream, interval time.Duration) {
|
||||
ticker := time.NewTicker(interval)
|
||||
defer ticker.Stop()
|
||||
lastZero := false
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
case <-s.Context().Done():
|
||||
return
|
||||
}
|
||||
stats := ccw.lb.clientStats.toClientStats()
|
||||
zero := isZeroStats(stats)
|
||||
if zero && lastZero {
|
||||
// Quash redundant empty load reports.
|
||||
continue
|
||||
}
|
||||
lastZero = zero
|
||||
t := time.Now()
|
||||
stats.Timestamp = ×tamppb.Timestamp{
|
||||
Seconds: t.Unix(),
|
||||
Nanos: int32(t.Nanosecond()),
|
||||
}
|
||||
if err := s.Send(&lbpb.LoadBalanceRequest{
|
||||
LoadBalanceRequestType: &lbpb.LoadBalanceRequest_ClientStats{
|
||||
ClientStats: stats,
|
||||
},
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ccw *remoteBalancerCCWrapper) callRemoteBalancer(ctx context.Context) (backoff bool, _ error) {
|
||||
lbClient := &loadBalancerClient{cc: ccw.cc}
|
||||
stream, err := lbClient.BalanceLoad(ctx, grpc.WaitForReady(true))
|
||||
if err != nil {
|
||||
return true, fmt.Errorf("grpclb: failed to perform RPC to the remote balancer: %v", err)
|
||||
}
|
||||
ccw.lb.mu.Lock()
|
||||
ccw.lb.remoteBalancerConnected = true
|
||||
ccw.lb.mu.Unlock()
|
||||
|
||||
// grpclb handshake on the stream.
|
||||
initReq := &lbpb.LoadBalanceRequest{
|
||||
LoadBalanceRequestType: &lbpb.LoadBalanceRequest_InitialRequest{
|
||||
InitialRequest: &lbpb.InitialLoadBalanceRequest{
|
||||
Name: ccw.lb.target,
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := stream.Send(initReq); err != nil {
|
||||
return true, fmt.Errorf("grpclb: failed to send init request: %v", err)
|
||||
}
|
||||
reply, err := stream.Recv()
|
||||
if err != nil {
|
||||
return true, fmt.Errorf("grpclb: failed to recv init response: %v", err)
|
||||
}
|
||||
initResp := reply.GetInitialResponse()
|
||||
if initResp == nil {
|
||||
return true, fmt.Errorf("grpclb: reply from remote balancer did not include initial response")
|
||||
}
|
||||
|
||||
ccw.wg.Add(1)
|
||||
go func() {
|
||||
defer ccw.wg.Done()
|
||||
if d := convertDuration(initResp.ClientStatsReportInterval); d > 0 {
|
||||
ccw.sendLoadReport(stream, d)
|
||||
}
|
||||
}()
|
||||
// No backoff if init req/resp handshake was successful.
|
||||
return false, ccw.readServerList(stream)
|
||||
}
|
||||
|
||||
// cancelRemoteBalancerCall cancels the context used by the stream to the remote
|
||||
// balancer. watchRemoteBalancer() takes care of restarting this call after the
|
||||
// stream fails.
|
||||
func (ccw *remoteBalancerCCWrapper) cancelRemoteBalancerCall() {
|
||||
ccw.streamMu.Lock()
|
||||
if ccw.streamCancel != nil {
|
||||
ccw.streamCancel()
|
||||
ccw.streamCancel = nil
|
||||
}
|
||||
ccw.streamMu.Unlock()
|
||||
}
|
||||
|
||||
func (ccw *remoteBalancerCCWrapper) watchRemoteBalancer() {
|
||||
defer func() {
|
||||
ccw.wg.Done()
|
||||
ccw.streamMu.Lock()
|
||||
if ccw.streamCancel != nil {
|
||||
// This is to make sure that we don't leak the context when we are
|
||||
// directly returning from inside of the below `for` loop.
|
||||
ccw.streamCancel()
|
||||
ccw.streamCancel = nil
|
||||
}
|
||||
ccw.streamMu.Unlock()
|
||||
}()
|
||||
|
||||
var retryCount int
|
||||
var ctx context.Context
|
||||
for {
|
||||
ccw.streamMu.Lock()
|
||||
if ccw.streamCancel != nil {
|
||||
ccw.streamCancel()
|
||||
ccw.streamCancel = nil
|
||||
}
|
||||
ctx, ccw.streamCancel = context.WithCancel(context.Background())
|
||||
ccw.streamMu.Unlock()
|
||||
|
||||
doBackoff, err := ccw.callRemoteBalancer(ctx)
|
||||
select {
|
||||
case <-ccw.done:
|
||||
return
|
||||
default:
|
||||
if err != nil {
|
||||
if err == errServerTerminatedConnection {
|
||||
ccw.lb.logger.Infof("Call to remote balancer failed: %v", err)
|
||||
} else {
|
||||
ccw.lb.logger.Warningf("Call to remote balancer failed: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Trigger a re-resolve when the stream errors.
|
||||
ccw.lb.cc.ClientConn.ResolveNow(resolver.ResolveNowOptions{})
|
||||
|
||||
ccw.lb.mu.Lock()
|
||||
ccw.lb.remoteBalancerConnected = false
|
||||
ccw.lb.fullServerList = nil
|
||||
// Enter fallback when connection to remote balancer is lost, and the
|
||||
// aggregated state is not Ready.
|
||||
if !ccw.lb.inFallback && ccw.lb.state != connectivity.Ready {
|
||||
// Entering fallback.
|
||||
ccw.lb.refreshSubConns(ccw.lb.resolvedBackendAddrs, true, ccw.lb.usePickFirst)
|
||||
}
|
||||
ccw.lb.mu.Unlock()
|
||||
|
||||
if !doBackoff {
|
||||
retryCount = 0
|
||||
continue
|
||||
}
|
||||
|
||||
timer := time.NewTimer(ccw.backoff.Backoff(retryCount)) // Copy backoff
|
||||
select {
|
||||
case <-timer.C:
|
||||
case <-ccw.done:
|
||||
timer.Stop()
|
||||
return
|
||||
}
|
||||
retryCount++
|
||||
}
|
||||
}
|
||||
173
vendor/google.golang.org/grpc/balancer/grpclb/grpclb_util.go
generated
vendored
Normal file
173
vendor/google.golang.org/grpc/balancer/grpclb/grpclb_util.go
generated
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2016 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpclb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
|
||||
const subConnCacheTime = time.Second * 10
|
||||
|
||||
// lbCacheClientConn is a wrapper balancer.ClientConn with a SubConn cache.
|
||||
// SubConns will be kept in cache for subConnCacheTime before being shut down.
|
||||
//
|
||||
// Its NewSubconn and SubConn.Shutdown methods are updated to do cache first.
|
||||
type lbCacheClientConn struct {
|
||||
balancer.ClientConn
|
||||
|
||||
timeout time.Duration
|
||||
|
||||
mu sync.Mutex
|
||||
// subConnCache only keeps subConns that are being deleted.
|
||||
subConnCache map[resolver.Address]*subConnCacheEntry
|
||||
subConnToAddr map[balancer.SubConn]resolver.Address
|
||||
}
|
||||
|
||||
type subConnCacheEntry struct {
|
||||
sc balancer.SubConn
|
||||
|
||||
cancel func()
|
||||
abortDeleting bool
|
||||
}
|
||||
|
||||
func newLBCacheClientConn(cc balancer.ClientConn) *lbCacheClientConn {
|
||||
return &lbCacheClientConn{
|
||||
ClientConn: cc,
|
||||
timeout: subConnCacheTime,
|
||||
subConnCache: make(map[resolver.Address]*subConnCacheEntry),
|
||||
subConnToAddr: make(map[balancer.SubConn]resolver.Address),
|
||||
}
|
||||
}
|
||||
|
||||
func (ccc *lbCacheClientConn) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
|
||||
if len(addrs) != 1 {
|
||||
return nil, fmt.Errorf("grpclb calling NewSubConn with addrs of length %v", len(addrs))
|
||||
}
|
||||
addrWithoutAttrs := addrs[0]
|
||||
addrWithoutAttrs.Attributes = nil
|
||||
|
||||
ccc.mu.Lock()
|
||||
defer ccc.mu.Unlock()
|
||||
if entry, ok := ccc.subConnCache[addrWithoutAttrs]; ok {
|
||||
// If entry is in subConnCache, the SubConn was being deleted.
|
||||
// cancel function will never be nil.
|
||||
entry.cancel()
|
||||
delete(ccc.subConnCache, addrWithoutAttrs)
|
||||
return entry.sc, nil
|
||||
}
|
||||
|
||||
scNew, err := ccc.ClientConn.NewSubConn(addrs, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
scNew = &lbCacheSubConn{SubConn: scNew, ccc: ccc}
|
||||
|
||||
ccc.subConnToAddr[scNew] = addrWithoutAttrs
|
||||
return scNew, nil
|
||||
}
|
||||
|
||||
func (ccc *lbCacheClientConn) RemoveSubConn(sc balancer.SubConn) {
|
||||
logger.Errorf("RemoveSubConn(%v) called unexpectedly", sc)
|
||||
}
|
||||
|
||||
type lbCacheSubConn struct {
|
||||
balancer.SubConn
|
||||
ccc *lbCacheClientConn
|
||||
}
|
||||
|
||||
func (sc *lbCacheSubConn) Shutdown() {
|
||||
ccc := sc.ccc
|
||||
ccc.mu.Lock()
|
||||
defer ccc.mu.Unlock()
|
||||
addr, ok := ccc.subConnToAddr[sc]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
if entry, ok := ccc.subConnCache[addr]; ok {
|
||||
if entry.sc != sc {
|
||||
// This could happen if NewSubConn was called multiple times for
|
||||
// the same address, and those SubConns are all shut down. We
|
||||
// remove sc immediately here.
|
||||
delete(ccc.subConnToAddr, sc)
|
||||
sc.SubConn.Shutdown()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
entry := &subConnCacheEntry{
|
||||
sc: sc,
|
||||
}
|
||||
ccc.subConnCache[addr] = entry
|
||||
|
||||
timer := time.AfterFunc(ccc.timeout, func() {
|
||||
ccc.mu.Lock()
|
||||
defer ccc.mu.Unlock()
|
||||
if entry.abortDeleting {
|
||||
return
|
||||
}
|
||||
sc.SubConn.Shutdown()
|
||||
delete(ccc.subConnToAddr, sc)
|
||||
delete(ccc.subConnCache, addr)
|
||||
})
|
||||
entry.cancel = func() {
|
||||
if !timer.Stop() {
|
||||
// If stop was not successful, the timer has fired (this can only
|
||||
// happen in a race). But the deleting function is blocked on ccc.mu
|
||||
// because the mutex was held by the caller of this function.
|
||||
//
|
||||
// Set abortDeleting to true to abort the deleting function. When
|
||||
// the lock is released, the deleting function will acquire the
|
||||
// lock, check the value of abortDeleting and return.
|
||||
entry.abortDeleting = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ccc *lbCacheClientConn) UpdateState(s balancer.State) {
|
||||
s.Picker = &lbCachePicker{Picker: s.Picker}
|
||||
ccc.ClientConn.UpdateState(s)
|
||||
}
|
||||
|
||||
func (ccc *lbCacheClientConn) close() {
|
||||
ccc.mu.Lock()
|
||||
defer ccc.mu.Unlock()
|
||||
// Only cancel all existing timers. There's no need to shut down SubConns.
|
||||
for _, entry := range ccc.subConnCache {
|
||||
entry.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
type lbCachePicker struct {
|
||||
balancer.Picker
|
||||
}
|
||||
|
||||
func (cp *lbCachePicker) Pick(i balancer.PickInfo) (balancer.PickResult, error) {
|
||||
res, err := cp.Picker.Pick(i)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
res.SubConn = res.SubConn.(*lbCacheSubConn).SubConn
|
||||
return res, nil
|
||||
}
|
||||
51
vendor/google.golang.org/grpc/balancer/grpclb/state/state.go
generated
vendored
Normal file
51
vendor/google.golang.org/grpc/balancer/grpclb/state/state.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package state declares grpclb types to be set by resolvers wishing to pass
|
||||
// information to grpclb via resolver.State Attributes.
|
||||
package state
|
||||
|
||||
import (
|
||||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
|
||||
// keyType is the key to use for storing State in Attributes.
|
||||
type keyType string
|
||||
|
||||
const key = keyType("grpc.grpclb.state")
|
||||
|
||||
// State contains gRPCLB-relevant data passed from the name resolver.
|
||||
type State struct {
|
||||
// BalancerAddresses contains the remote load balancer address(es). If
|
||||
// set, overrides any resolver-provided addresses with Type of GRPCLB.
|
||||
BalancerAddresses []resolver.Address
|
||||
}
|
||||
|
||||
// Set returns a copy of the provided state with attributes containing s. s's
|
||||
// data should not be mutated after calling Set.
|
||||
func Set(state resolver.State, s *State) resolver.State {
|
||||
state.Attributes = state.Attributes.WithValue(key, s)
|
||||
return state
|
||||
}
|
||||
|
||||
// Get returns the grpclb State in the resolver.State, or nil if not present.
|
||||
// The returned data should not be mutated.
|
||||
func Get(state resolver.State) *State {
|
||||
s, _ := state.Attributes.Value(key).(*State)
|
||||
return s
|
||||
}
|
||||
81
vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
generated
vendored
Normal file
81
vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package roundrobin defines a roundrobin balancer. Roundrobin balancer is
|
||||
// installed as one of the default balancers in gRPC, users don't need to
|
||||
// explicitly install this balancer.
|
||||
package roundrobin
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/balancer/base"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/internal/grpcrand"
|
||||
)
|
||||
|
||||
// Name is the name of round_robin balancer.
|
||||
const Name = "round_robin"
|
||||
|
||||
var logger = grpclog.Component("roundrobin")
|
||||
|
||||
// newBuilder creates a new roundrobin balancer builder.
|
||||
func newBuilder() balancer.Builder {
|
||||
return base.NewBalancerBuilder(Name, &rrPickerBuilder{}, base.Config{HealthCheck: true})
|
||||
}
|
||||
|
||||
func init() {
|
||||
balancer.Register(newBuilder())
|
||||
}
|
||||
|
||||
type rrPickerBuilder struct{}
|
||||
|
||||
func (*rrPickerBuilder) Build(info base.PickerBuildInfo) balancer.Picker {
|
||||
logger.Infof("roundrobinPicker: Build called with info: %v", info)
|
||||
if len(info.ReadySCs) == 0 {
|
||||
return base.NewErrPicker(balancer.ErrNoSubConnAvailable)
|
||||
}
|
||||
scs := make([]balancer.SubConn, 0, len(info.ReadySCs))
|
||||
for sc := range info.ReadySCs {
|
||||
scs = append(scs, sc)
|
||||
}
|
||||
return &rrPicker{
|
||||
subConns: scs,
|
||||
// Start at a random index, as the same RR balancer rebuilds a new
|
||||
// picker when SubConn states change, and we don't want to apply excess
|
||||
// load to the first server in the list.
|
||||
next: uint32(grpcrand.Intn(len(scs))),
|
||||
}
|
||||
}
|
||||
|
||||
type rrPicker struct {
|
||||
// subConns is the snapshot of the roundrobin balancer when this picker was
|
||||
// created. The slice is immutable. Each Get() will do a round robin
|
||||
// selection from it and return the selected SubConn.
|
||||
subConns []balancer.SubConn
|
||||
next uint32
|
||||
}
|
||||
|
||||
func (p *rrPicker) Pick(balancer.PickInfo) (balancer.PickResult, error) {
|
||||
subConnsLen := uint32(len(p.subConns))
|
||||
nextIndex := atomic.AddUint32(&p.next, 1)
|
||||
|
||||
sc := p.subConns[nextIndex%subConnsLen]
|
||||
return balancer.PickResult{SubConn: sc}, nil
|
||||
}
|
||||
337
vendor/google.golang.org/grpc/balancer_wrapper.go
generated
vendored
Normal file
337
vendor/google.golang.org/grpc/balancer_wrapper.go
generated
vendored
Normal file
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/internal/balancer/gracefulswitch"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
"google.golang.org/grpc/internal/grpcsync"
|
||||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
|
||||
// ccBalancerWrapper sits between the ClientConn and the Balancer.
|
||||
//
|
||||
// ccBalancerWrapper implements methods corresponding to the ones on the
|
||||
// balancer.Balancer interface. The ClientConn is free to call these methods
|
||||
// concurrently and the ccBalancerWrapper ensures that calls from the ClientConn
|
||||
// to the Balancer happen in order by performing them in the serializer, without
|
||||
// any mutexes held.
|
||||
//
|
||||
// ccBalancerWrapper also implements the balancer.ClientConn interface and is
|
||||
// passed to the Balancer implementations. It invokes unexported methods on the
|
||||
// ClientConn to handle these calls from the Balancer.
|
||||
//
|
||||
// It uses the gracefulswitch.Balancer internally to ensure that balancer
|
||||
// switches happen in a graceful manner.
|
||||
type ccBalancerWrapper struct {
|
||||
// The following fields are initialized when the wrapper is created and are
|
||||
// read-only afterwards, and therefore can be accessed without a mutex.
|
||||
cc *ClientConn
|
||||
opts balancer.BuildOptions
|
||||
serializer *grpcsync.CallbackSerializer
|
||||
serializerCancel context.CancelFunc
|
||||
|
||||
// The following fields are only accessed within the serializer or during
|
||||
// initialization.
|
||||
curBalancerName string
|
||||
balancer *gracefulswitch.Balancer
|
||||
|
||||
// The following field is protected by mu. Caller must take cc.mu before
|
||||
// taking mu.
|
||||
mu sync.Mutex
|
||||
closed bool
|
||||
}
|
||||
|
||||
// newCCBalancerWrapper creates a new balancer wrapper in idle state. The
|
||||
// underlying balancer is not created until the updateClientConnState() method
|
||||
// is invoked.
|
||||
func newCCBalancerWrapper(cc *ClientConn) *ccBalancerWrapper {
|
||||
ctx, cancel := context.WithCancel(cc.ctx)
|
||||
ccb := &ccBalancerWrapper{
|
||||
cc: cc,
|
||||
opts: balancer.BuildOptions{
|
||||
DialCreds: cc.dopts.copts.TransportCredentials,
|
||||
CredsBundle: cc.dopts.copts.CredsBundle,
|
||||
Dialer: cc.dopts.copts.Dialer,
|
||||
Authority: cc.authority,
|
||||
CustomUserAgent: cc.dopts.copts.UserAgent,
|
||||
ChannelzParent: cc.channelz,
|
||||
Target: cc.parsedTarget,
|
||||
},
|
||||
serializer: grpcsync.NewCallbackSerializer(ctx),
|
||||
serializerCancel: cancel,
|
||||
}
|
||||
ccb.balancer = gracefulswitch.NewBalancer(ccb, ccb.opts)
|
||||
return ccb
|
||||
}
|
||||
|
||||
// updateClientConnState is invoked by grpc to push a ClientConnState update to
|
||||
// the underlying balancer. This is always executed from the serializer, so
|
||||
// it is safe to call into the balancer here.
|
||||
func (ccb *ccBalancerWrapper) updateClientConnState(ccs *balancer.ClientConnState) error {
|
||||
errCh := make(chan error)
|
||||
ok := ccb.serializer.Schedule(func(ctx context.Context) {
|
||||
defer close(errCh)
|
||||
if ctx.Err() != nil || ccb.balancer == nil {
|
||||
return
|
||||
}
|
||||
name := gracefulswitch.ChildName(ccs.BalancerConfig)
|
||||
if ccb.curBalancerName != name {
|
||||
ccb.curBalancerName = name
|
||||
channelz.Infof(logger, ccb.cc.channelz, "Channel switches to new LB policy %q", name)
|
||||
}
|
||||
err := ccb.balancer.UpdateClientConnState(*ccs)
|
||||
if logger.V(2) && err != nil {
|
||||
logger.Infof("error from balancer.UpdateClientConnState: %v", err)
|
||||
}
|
||||
errCh <- err
|
||||
})
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
// resolverError is invoked by grpc to push a resolver error to the underlying
|
||||
// balancer. The call to the balancer is executed from the serializer.
|
||||
func (ccb *ccBalancerWrapper) resolverError(err error) {
|
||||
ccb.serializer.Schedule(func(ctx context.Context) {
|
||||
if ctx.Err() != nil || ccb.balancer == nil {
|
||||
return
|
||||
}
|
||||
ccb.balancer.ResolverError(err)
|
||||
})
|
||||
}
|
||||
|
||||
// close initiates async shutdown of the wrapper. cc.mu must be held when
|
||||
// calling this function. To determine the wrapper has finished shutting down,
|
||||
// the channel should block on ccb.serializer.Done() without cc.mu held.
|
||||
func (ccb *ccBalancerWrapper) close() {
|
||||
ccb.mu.Lock()
|
||||
ccb.closed = true
|
||||
ccb.mu.Unlock()
|
||||
channelz.Info(logger, ccb.cc.channelz, "ccBalancerWrapper: closing")
|
||||
ccb.serializer.Schedule(func(context.Context) {
|
||||
if ccb.balancer == nil {
|
||||
return
|
||||
}
|
||||
ccb.balancer.Close()
|
||||
ccb.balancer = nil
|
||||
})
|
||||
ccb.serializerCancel()
|
||||
}
|
||||
|
||||
// exitIdle invokes the balancer's exitIdle method in the serializer.
|
||||
func (ccb *ccBalancerWrapper) exitIdle() {
|
||||
ccb.serializer.Schedule(func(ctx context.Context) {
|
||||
if ctx.Err() != nil || ccb.balancer == nil {
|
||||
return
|
||||
}
|
||||
ccb.balancer.ExitIdle()
|
||||
})
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
|
||||
ccb.cc.mu.Lock()
|
||||
defer ccb.cc.mu.Unlock()
|
||||
|
||||
ccb.mu.Lock()
|
||||
if ccb.closed {
|
||||
ccb.mu.Unlock()
|
||||
return nil, fmt.Errorf("balancer is being closed; no new SubConns allowed")
|
||||
}
|
||||
ccb.mu.Unlock()
|
||||
|
||||
if len(addrs) == 0 {
|
||||
return nil, fmt.Errorf("grpc: cannot create SubConn with empty address list")
|
||||
}
|
||||
ac, err := ccb.cc.newAddrConnLocked(addrs, opts)
|
||||
if err != nil {
|
||||
channelz.Warningf(logger, ccb.cc.channelz, "acBalancerWrapper: NewSubConn: failed to newAddrConn: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
acbw := &acBalancerWrapper{
|
||||
ccb: ccb,
|
||||
ac: ac,
|
||||
producers: make(map[balancer.ProducerBuilder]*refCountedProducer),
|
||||
stateListener: opts.StateListener,
|
||||
}
|
||||
ac.acbw = acbw
|
||||
return acbw, nil
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) {
|
||||
// The graceful switch balancer will never call this.
|
||||
logger.Errorf("ccb RemoveSubConn(%v) called unexpectedly, sc")
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resolver.Address) {
|
||||
acbw, ok := sc.(*acBalancerWrapper)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
acbw.UpdateAddresses(addrs)
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) UpdateState(s balancer.State) {
|
||||
ccb.cc.mu.Lock()
|
||||
defer ccb.cc.mu.Unlock()
|
||||
|
||||
ccb.mu.Lock()
|
||||
if ccb.closed {
|
||||
ccb.mu.Unlock()
|
||||
return
|
||||
}
|
||||
ccb.mu.Unlock()
|
||||
// Update picker before updating state. Even though the ordering here does
|
||||
// not matter, it can lead to multiple calls of Pick in the common start-up
|
||||
// case where we wait for ready and then perform an RPC. If the picker is
|
||||
// updated later, we could call the "connecting" picker when the state is
|
||||
// updated, and then call the "ready" picker after the picker gets updated.
|
||||
|
||||
// Note that there is no need to check if the balancer wrapper was closed,
|
||||
// as we know the graceful switch LB policy will not call cc if it has been
|
||||
// closed.
|
||||
ccb.cc.pickerWrapper.updatePicker(s.Picker)
|
||||
ccb.cc.csMgr.updateState(s.ConnectivityState)
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) ResolveNow(o resolver.ResolveNowOptions) {
|
||||
ccb.cc.mu.RLock()
|
||||
defer ccb.cc.mu.RUnlock()
|
||||
|
||||
ccb.mu.Lock()
|
||||
if ccb.closed {
|
||||
ccb.mu.Unlock()
|
||||
return
|
||||
}
|
||||
ccb.mu.Unlock()
|
||||
ccb.cc.resolveNowLocked(o)
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) Target() string {
|
||||
return ccb.cc.target
|
||||
}
|
||||
|
||||
// acBalancerWrapper is a wrapper on top of ac for balancers.
|
||||
// It implements balancer.SubConn interface.
|
||||
type acBalancerWrapper struct {
|
||||
ac *addrConn // read-only
|
||||
ccb *ccBalancerWrapper // read-only
|
||||
stateListener func(balancer.SubConnState)
|
||||
|
||||
mu sync.Mutex
|
||||
producers map[balancer.ProducerBuilder]*refCountedProducer
|
||||
}
|
||||
|
||||
// updateState is invoked by grpc to push a subConn state update to the
|
||||
// underlying balancer.
|
||||
func (acbw *acBalancerWrapper) updateState(s connectivity.State, err error) {
|
||||
acbw.ccb.serializer.Schedule(func(ctx context.Context) {
|
||||
if ctx.Err() != nil || acbw.ccb.balancer == nil {
|
||||
return
|
||||
}
|
||||
// Even though it is optional for balancers, gracefulswitch ensures
|
||||
// opts.StateListener is set, so this cannot ever be nil.
|
||||
// TODO: delete this comment when UpdateSubConnState is removed.
|
||||
acbw.stateListener(balancer.SubConnState{ConnectivityState: s, ConnectionError: err})
|
||||
})
|
||||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) String() string {
|
||||
return fmt.Sprintf("SubConn(id:%d)", acbw.ac.channelz.ID)
|
||||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
|
||||
acbw.ac.updateAddrs(addrs)
|
||||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) Connect() {
|
||||
go acbw.ac.connect()
|
||||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) Shutdown() {
|
||||
acbw.ccb.cc.removeAddrConn(acbw.ac, errConnDrain)
|
||||
}
|
||||
|
||||
// NewStream begins a streaming RPC on the addrConn. If the addrConn is not
|
||||
// ready, blocks until it is or ctx expires. Returns an error when the context
|
||||
// expires or the addrConn is shut down.
|
||||
func (acbw *acBalancerWrapper) NewStream(ctx context.Context, desc *StreamDesc, method string, opts ...CallOption) (ClientStream, error) {
|
||||
transport, err := acbw.ac.getTransport(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newNonRetryClientStream(ctx, desc, method, transport, acbw.ac, opts...)
|
||||
}
|
||||
|
||||
// Invoke performs a unary RPC. If the addrConn is not ready, returns
|
||||
// errSubConnNotReady.
|
||||
func (acbw *acBalancerWrapper) Invoke(ctx context.Context, method string, args any, reply any, opts ...CallOption) error {
|
||||
cs, err := acbw.NewStream(ctx, unaryStreamDesc, method, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cs.SendMsg(args); err != nil {
|
||||
return err
|
||||
}
|
||||
return cs.RecvMsg(reply)
|
||||
}
|
||||
|
||||
type refCountedProducer struct {
|
||||
producer balancer.Producer
|
||||
refs int // number of current refs to the producer
|
||||
close func() // underlying producer's close function
|
||||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) GetOrBuildProducer(pb balancer.ProducerBuilder) (balancer.Producer, func()) {
|
||||
acbw.mu.Lock()
|
||||
defer acbw.mu.Unlock()
|
||||
|
||||
// Look up existing producer from this builder.
|
||||
pData := acbw.producers[pb]
|
||||
if pData == nil {
|
||||
// Not found; create a new one and add it to the producers map.
|
||||
p, close := pb.Build(acbw)
|
||||
pData = &refCountedProducer{producer: p, close: close}
|
||||
acbw.producers[pb] = pData
|
||||
}
|
||||
// Account for this new reference.
|
||||
pData.refs++
|
||||
|
||||
// Return a cleanup function wrapped in a OnceFunc to remove this reference
|
||||
// and delete the refCountedProducer from the map if the total reference
|
||||
// count goes to zero.
|
||||
unref := func() {
|
||||
acbw.mu.Lock()
|
||||
pData.refs--
|
||||
if pData.refs == 0 {
|
||||
defer pData.close() // Run outside the acbw mutex
|
||||
delete(acbw.producers, pb)
|
||||
}
|
||||
acbw.mu.Unlock()
|
||||
}
|
||||
return pData.producer, grpcsync.OnceFunc(unref)
|
||||
}
|
||||
1183
vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go
generated
vendored
Normal file
1183
vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
74
vendor/google.golang.org/grpc/call.go
generated
vendored
Normal file
74
vendor/google.golang.org/grpc/call.go
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2014 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// Invoke sends the RPC request on the wire and returns after response is
|
||||
// received. This is typically called by generated code.
|
||||
//
|
||||
// All errors returned by Invoke are compatible with the status package.
|
||||
func (cc *ClientConn) Invoke(ctx context.Context, method string, args, reply any, opts ...CallOption) error {
|
||||
// allow interceptor to see all applicable call options, which means those
|
||||
// configured as defaults from dial option as well as per-call options
|
||||
opts = combine(cc.dopts.callOptions, opts)
|
||||
|
||||
if cc.dopts.unaryInt != nil {
|
||||
return cc.dopts.unaryInt(ctx, method, args, reply, cc, invoke, opts...)
|
||||
}
|
||||
return invoke(ctx, method, args, reply, cc, opts...)
|
||||
}
|
||||
|
||||
func combine(o1 []CallOption, o2 []CallOption) []CallOption {
|
||||
// we don't use append because o1 could have extra capacity whose
|
||||
// elements would be overwritten, which could cause inadvertent
|
||||
// sharing (and race conditions) between concurrent calls
|
||||
if len(o1) == 0 {
|
||||
return o2
|
||||
} else if len(o2) == 0 {
|
||||
return o1
|
||||
}
|
||||
ret := make([]CallOption, len(o1)+len(o2))
|
||||
copy(ret, o1)
|
||||
copy(ret[len(o1):], o2)
|
||||
return ret
|
||||
}
|
||||
|
||||
// Invoke sends the RPC request on the wire and returns after response is
|
||||
// received. This is typically called by generated code.
|
||||
//
|
||||
// DEPRECATED: Use ClientConn.Invoke instead.
|
||||
func Invoke(ctx context.Context, method string, args, reply any, cc *ClientConn, opts ...CallOption) error {
|
||||
return cc.Invoke(ctx, method, args, reply, opts...)
|
||||
}
|
||||
|
||||
var unaryStreamDesc = &StreamDesc{ServerStreams: false, ClientStreams: false}
|
||||
|
||||
func invoke(ctx context.Context, method string, req, reply any, cc *ClientConn, opts ...CallOption) error {
|
||||
cs, err := newClientStream(ctx, unaryStreamDesc, cc, method, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cs.SendMsg(req); err != nil {
|
||||
return err
|
||||
}
|
||||
return cs.RecvMsg(reply)
|
||||
}
|
||||
36
vendor/google.golang.org/grpc/channelz/channelz.go
generated
vendored
Normal file
36
vendor/google.golang.org/grpc/channelz/channelz.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package channelz exports internals of the channelz implementation as required
|
||||
// by other gRPC packages.
|
||||
//
|
||||
// The implementation of the channelz spec as defined in
|
||||
// https://github.com/grpc/proposal/blob/master/A14-channelz.md, is provided by
|
||||
// the `internal/channelz` package.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: All APIs in this package are experimental and may be removed in a
|
||||
// later release.
|
||||
package channelz
|
||||
|
||||
import "google.golang.org/grpc/internal/channelz"
|
||||
|
||||
// Identifier is an opaque identifier which uniquely identifies an entity in the
|
||||
// channelz database.
|
||||
type Identifier = channelz.Identifier
|
||||
1843
vendor/google.golang.org/grpc/clientconn.go
generated
vendored
Normal file
1843
vendor/google.golang.org/grpc/clientconn.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
50
vendor/google.golang.org/grpc/codec.go
generated
vendored
Normal file
50
vendor/google.golang.org/grpc/codec.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2014 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"google.golang.org/grpc/encoding"
|
||||
_ "google.golang.org/grpc/encoding/proto" // to register the Codec for "proto"
|
||||
)
|
||||
|
||||
// baseCodec contains the functionality of both Codec and encoding.Codec, but
|
||||
// omits the name/string, which vary between the two and are not needed for
|
||||
// anything besides the registry in the encoding package.
|
||||
type baseCodec interface {
|
||||
Marshal(v any) ([]byte, error)
|
||||
Unmarshal(data []byte, v any) error
|
||||
}
|
||||
|
||||
var _ baseCodec = Codec(nil)
|
||||
var _ baseCodec = encoding.Codec(nil)
|
||||
|
||||
// Codec defines the interface gRPC uses to encode and decode messages.
|
||||
// Note that implementations of this interface must be thread safe;
|
||||
// a Codec's methods can be called from concurrent goroutines.
|
||||
//
|
||||
// Deprecated: use encoding.Codec instead.
|
||||
type Codec interface {
|
||||
// Marshal returns the wire format of v.
|
||||
Marshal(v any) ([]byte, error)
|
||||
// Unmarshal parses the wire format into v.
|
||||
Unmarshal(data []byte, v any) error
|
||||
// String returns the name of the Codec implementation. This is unused by
|
||||
// gRPC.
|
||||
String() string
|
||||
}
|
||||
111
vendor/google.golang.org/grpc/codes/code_string.go
generated
vendored
Normal file
111
vendor/google.golang.org/grpc/codes/code_string.go
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package codes
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"google.golang.org/grpc/internal"
|
||||
)
|
||||
|
||||
func init() {
|
||||
internal.CanonicalString = canonicalString
|
||||
}
|
||||
|
||||
func (c Code) String() string {
|
||||
switch c {
|
||||
case OK:
|
||||
return "OK"
|
||||
case Canceled:
|
||||
return "Canceled"
|
||||
case Unknown:
|
||||
return "Unknown"
|
||||
case InvalidArgument:
|
||||
return "InvalidArgument"
|
||||
case DeadlineExceeded:
|
||||
return "DeadlineExceeded"
|
||||
case NotFound:
|
||||
return "NotFound"
|
||||
case AlreadyExists:
|
||||
return "AlreadyExists"
|
||||
case PermissionDenied:
|
||||
return "PermissionDenied"
|
||||
case ResourceExhausted:
|
||||
return "ResourceExhausted"
|
||||
case FailedPrecondition:
|
||||
return "FailedPrecondition"
|
||||
case Aborted:
|
||||
return "Aborted"
|
||||
case OutOfRange:
|
||||
return "OutOfRange"
|
||||
case Unimplemented:
|
||||
return "Unimplemented"
|
||||
case Internal:
|
||||
return "Internal"
|
||||
case Unavailable:
|
||||
return "Unavailable"
|
||||
case DataLoss:
|
||||
return "DataLoss"
|
||||
case Unauthenticated:
|
||||
return "Unauthenticated"
|
||||
default:
|
||||
return "Code(" + strconv.FormatInt(int64(c), 10) + ")"
|
||||
}
|
||||
}
|
||||
|
||||
func canonicalString(c Code) string {
|
||||
switch c {
|
||||
case OK:
|
||||
return "OK"
|
||||
case Canceled:
|
||||
return "CANCELLED"
|
||||
case Unknown:
|
||||
return "UNKNOWN"
|
||||
case InvalidArgument:
|
||||
return "INVALID_ARGUMENT"
|
||||
case DeadlineExceeded:
|
||||
return "DEADLINE_EXCEEDED"
|
||||
case NotFound:
|
||||
return "NOT_FOUND"
|
||||
case AlreadyExists:
|
||||
return "ALREADY_EXISTS"
|
||||
case PermissionDenied:
|
||||
return "PERMISSION_DENIED"
|
||||
case ResourceExhausted:
|
||||
return "RESOURCE_EXHAUSTED"
|
||||
case FailedPrecondition:
|
||||
return "FAILED_PRECONDITION"
|
||||
case Aborted:
|
||||
return "ABORTED"
|
||||
case OutOfRange:
|
||||
return "OUT_OF_RANGE"
|
||||
case Unimplemented:
|
||||
return "UNIMPLEMENTED"
|
||||
case Internal:
|
||||
return "INTERNAL"
|
||||
case Unavailable:
|
||||
return "UNAVAILABLE"
|
||||
case DataLoss:
|
||||
return "DATA_LOSS"
|
||||
case Unauthenticated:
|
||||
return "UNAUTHENTICATED"
|
||||
default:
|
||||
return "CODE(" + strconv.FormatInt(int64(c), 10) + ")"
|
||||
}
|
||||
}
|
||||
250
vendor/google.golang.org/grpc/codes/codes.go
generated
vendored
Normal file
250
vendor/google.golang.org/grpc/codes/codes.go
generated
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2014 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package codes defines the canonical error codes used by gRPC. It is
|
||||
// consistent across various languages.
|
||||
package codes // import "google.golang.org/grpc/codes"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// A Code is a status code defined according to the [gRPC documentation].
|
||||
//
|
||||
// Only the codes defined as consts in this package are valid codes. Do not use
|
||||
// other code values. Behavior of other codes is implementation-specific and
|
||||
// interoperability between implementations is not guaranteed.
|
||||
//
|
||||
// [gRPC documentation]: https://github.com/grpc/grpc/blob/master/doc/statuscodes.md
|
||||
type Code uint32
|
||||
|
||||
const (
|
||||
// OK is returned on success.
|
||||
OK Code = 0
|
||||
|
||||
// Canceled indicates the operation was canceled (typically by the caller).
|
||||
//
|
||||
// The gRPC framework will generate this error code when cancellation
|
||||
// is requested.
|
||||
Canceled Code = 1
|
||||
|
||||
// Unknown error. An example of where this error may be returned is
|
||||
// if a Status value received from another address space belongs to
|
||||
// an error-space that is not known in this address space. Also
|
||||
// errors raised by APIs that do not return enough error information
|
||||
// may be converted to this error.
|
||||
//
|
||||
// The gRPC framework will generate this error code in the above two
|
||||
// mentioned cases.
|
||||
Unknown Code = 2
|
||||
|
||||
// InvalidArgument indicates client specified an invalid argument.
|
||||
// Note that this differs from FailedPrecondition. It indicates arguments
|
||||
// that are problematic regardless of the state of the system
|
||||
// (e.g., a malformed file name).
|
||||
//
|
||||
// This error code will not be generated by the gRPC framework.
|
||||
InvalidArgument Code = 3
|
||||
|
||||
// DeadlineExceeded means operation expired before completion.
|
||||
// For operations that change the state of the system, this error may be
|
||||
// returned even if the operation has completed successfully. For
|
||||
// example, a successful response from a server could have been delayed
|
||||
// long enough for the deadline to expire.
|
||||
//
|
||||
// The gRPC framework will generate this error code when the deadline is
|
||||
// exceeded.
|
||||
DeadlineExceeded Code = 4
|
||||
|
||||
// NotFound means some requested entity (e.g., file or directory) was
|
||||
// not found.
|
||||
//
|
||||
// This error code will not be generated by the gRPC framework.
|
||||
NotFound Code = 5
|
||||
|
||||
// AlreadyExists means an attempt to create an entity failed because one
|
||||
// already exists.
|
||||
//
|
||||
// This error code will not be generated by the gRPC framework.
|
||||
AlreadyExists Code = 6
|
||||
|
||||
// PermissionDenied indicates the caller does not have permission to
|
||||
// execute the specified operation. It must not be used for rejections
|
||||
// caused by exhausting some resource (use ResourceExhausted
|
||||
// instead for those errors). It must not be
|
||||
// used if the caller cannot be identified (use Unauthenticated
|
||||
// instead for those errors).
|
||||
//
|
||||
// This error code will not be generated by the gRPC core framework,
|
||||
// but expect authentication middleware to use it.
|
||||
PermissionDenied Code = 7
|
||||
|
||||
// ResourceExhausted indicates some resource has been exhausted, perhaps
|
||||
// a per-user quota, or perhaps the entire file system is out of space.
|
||||
//
|
||||
// This error code will be generated by the gRPC framework in
|
||||
// out-of-memory and server overload situations, or when a message is
|
||||
// larger than the configured maximum size.
|
||||
ResourceExhausted Code = 8
|
||||
|
||||
// FailedPrecondition indicates operation was rejected because the
|
||||
// system is not in a state required for the operation's execution.
|
||||
// For example, directory to be deleted may be non-empty, an rmdir
|
||||
// operation is applied to a non-directory, etc.
|
||||
//
|
||||
// A litmus test that may help a service implementor in deciding
|
||||
// between FailedPrecondition, Aborted, and Unavailable:
|
||||
// (a) Use Unavailable if the client can retry just the failing call.
|
||||
// (b) Use Aborted if the client should retry at a higher-level
|
||||
// (e.g., restarting a read-modify-write sequence).
|
||||
// (c) Use FailedPrecondition if the client should not retry until
|
||||
// the system state has been explicitly fixed. E.g., if an "rmdir"
|
||||
// fails because the directory is non-empty, FailedPrecondition
|
||||
// should be returned since the client should not retry unless
|
||||
// they have first fixed up the directory by deleting files from it.
|
||||
// (d) Use FailedPrecondition if the client performs conditional
|
||||
// REST Get/Update/Delete on a resource and the resource on the
|
||||
// server does not match the condition. E.g., conflicting
|
||||
// read-modify-write on the same resource.
|
||||
//
|
||||
// This error code will not be generated by the gRPC framework.
|
||||
FailedPrecondition Code = 9
|
||||
|
||||
// Aborted indicates the operation was aborted, typically due to a
|
||||
// concurrency issue like sequencer check failures, transaction aborts,
|
||||
// etc.
|
||||
//
|
||||
// See litmus test above for deciding between FailedPrecondition,
|
||||
// Aborted, and Unavailable.
|
||||
//
|
||||
// This error code will not be generated by the gRPC framework.
|
||||
Aborted Code = 10
|
||||
|
||||
// OutOfRange means operation was attempted past the valid range.
|
||||
// E.g., seeking or reading past end of file.
|
||||
//
|
||||
// Unlike InvalidArgument, this error indicates a problem that may
|
||||
// be fixed if the system state changes. For example, a 32-bit file
|
||||
// system will generate InvalidArgument if asked to read at an
|
||||
// offset that is not in the range [0,2^32-1], but it will generate
|
||||
// OutOfRange if asked to read from an offset past the current
|
||||
// file size.
|
||||
//
|
||||
// There is a fair bit of overlap between FailedPrecondition and
|
||||
// OutOfRange. We recommend using OutOfRange (the more specific
|
||||
// error) when it applies so that callers who are iterating through
|
||||
// a space can easily look for an OutOfRange error to detect when
|
||||
// they are done.
|
||||
//
|
||||
// This error code will not be generated by the gRPC framework.
|
||||
OutOfRange Code = 11
|
||||
|
||||
// Unimplemented indicates operation is not implemented or not
|
||||
// supported/enabled in this service.
|
||||
//
|
||||
// This error code will be generated by the gRPC framework. Most
|
||||
// commonly, you will see this error code when a method implementation
|
||||
// is missing on the server. It can also be generated for unknown
|
||||
// compression algorithms or a disagreement as to whether an RPC should
|
||||
// be streaming.
|
||||
Unimplemented Code = 12
|
||||
|
||||
// Internal errors. Means some invariants expected by underlying
|
||||
// system has been broken. If you see one of these errors,
|
||||
// something is very broken.
|
||||
//
|
||||
// This error code will be generated by the gRPC framework in several
|
||||
// internal error conditions.
|
||||
Internal Code = 13
|
||||
|
||||
// Unavailable indicates the service is currently unavailable.
|
||||
// This is a most likely a transient condition and may be corrected
|
||||
// by retrying with a backoff. Note that it is not always safe to retry
|
||||
// non-idempotent operations.
|
||||
//
|
||||
// See litmus test above for deciding between FailedPrecondition,
|
||||
// Aborted, and Unavailable.
|
||||
//
|
||||
// This error code will be generated by the gRPC framework during
|
||||
// abrupt shutdown of a server process or network connection.
|
||||
Unavailable Code = 14
|
||||
|
||||
// DataLoss indicates unrecoverable data loss or corruption.
|
||||
//
|
||||
// This error code will not be generated by the gRPC framework.
|
||||
DataLoss Code = 15
|
||||
|
||||
// Unauthenticated indicates the request does not have valid
|
||||
// authentication credentials for the operation.
|
||||
//
|
||||
// The gRPC framework will generate this error code when the
|
||||
// authentication metadata is invalid or a Credentials callback fails,
|
||||
// but also expect authentication middleware to generate it.
|
||||
Unauthenticated Code = 16
|
||||
|
||||
_maxCode = 17
|
||||
)
|
||||
|
||||
var strToCode = map[string]Code{
|
||||
`"OK"`: OK,
|
||||
`"CANCELLED"`:/* [sic] */ Canceled,
|
||||
`"UNKNOWN"`: Unknown,
|
||||
`"INVALID_ARGUMENT"`: InvalidArgument,
|
||||
`"DEADLINE_EXCEEDED"`: DeadlineExceeded,
|
||||
`"NOT_FOUND"`: NotFound,
|
||||
`"ALREADY_EXISTS"`: AlreadyExists,
|
||||
`"PERMISSION_DENIED"`: PermissionDenied,
|
||||
`"RESOURCE_EXHAUSTED"`: ResourceExhausted,
|
||||
`"FAILED_PRECONDITION"`: FailedPrecondition,
|
||||
`"ABORTED"`: Aborted,
|
||||
`"OUT_OF_RANGE"`: OutOfRange,
|
||||
`"UNIMPLEMENTED"`: Unimplemented,
|
||||
`"INTERNAL"`: Internal,
|
||||
`"UNAVAILABLE"`: Unavailable,
|
||||
`"DATA_LOSS"`: DataLoss,
|
||||
`"UNAUTHENTICATED"`: Unauthenticated,
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals b into the Code.
|
||||
func (c *Code) UnmarshalJSON(b []byte) error {
|
||||
// From json.Unmarshaler: By convention, to approximate the behavior of
|
||||
// Unmarshal itself, Unmarshalers implement UnmarshalJSON([]byte("null")) as
|
||||
// a no-op.
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
if c == nil {
|
||||
return fmt.Errorf("nil receiver passed to UnmarshalJSON")
|
||||
}
|
||||
|
||||
if ci, err := strconv.ParseUint(string(b), 10, 32); err == nil {
|
||||
if ci >= _maxCode {
|
||||
return fmt.Errorf("invalid code: %d", ci)
|
||||
}
|
||||
|
||||
*c = Code(ci)
|
||||
return nil
|
||||
}
|
||||
|
||||
if jc, ok := strToCode[string(b)]; ok {
|
||||
*c = jc
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("invalid code: %q", string(b))
|
||||
}
|
||||
94
vendor/google.golang.org/grpc/connectivity/connectivity.go
generated
vendored
Normal file
94
vendor/google.golang.org/grpc/connectivity/connectivity.go
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package connectivity defines connectivity semantics.
|
||||
// For details, see https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md.
|
||||
package connectivity
|
||||
|
||||
import (
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
var logger = grpclog.Component("core")
|
||||
|
||||
// State indicates the state of connectivity.
|
||||
// It can be the state of a ClientConn or SubConn.
|
||||
type State int
|
||||
|
||||
func (s State) String() string {
|
||||
switch s {
|
||||
case Idle:
|
||||
return "IDLE"
|
||||
case Connecting:
|
||||
return "CONNECTING"
|
||||
case Ready:
|
||||
return "READY"
|
||||
case TransientFailure:
|
||||
return "TRANSIENT_FAILURE"
|
||||
case Shutdown:
|
||||
return "SHUTDOWN"
|
||||
default:
|
||||
logger.Errorf("unknown connectivity state: %d", s)
|
||||
return "INVALID_STATE"
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
// Idle indicates the ClientConn is idle.
|
||||
Idle State = iota
|
||||
// Connecting indicates the ClientConn is connecting.
|
||||
Connecting
|
||||
// Ready indicates the ClientConn is ready for work.
|
||||
Ready
|
||||
// TransientFailure indicates the ClientConn has seen a failure but expects to recover.
|
||||
TransientFailure
|
||||
// Shutdown indicates the ClientConn has started shutting down.
|
||||
Shutdown
|
||||
)
|
||||
|
||||
// ServingMode indicates the current mode of operation of the server.
|
||||
//
|
||||
// Only xDS enabled gRPC servers currently report their serving mode.
|
||||
type ServingMode int
|
||||
|
||||
const (
|
||||
// ServingModeStarting indicates that the server is starting up.
|
||||
ServingModeStarting ServingMode = iota
|
||||
// ServingModeServing indicates that the server contains all required
|
||||
// configuration and is serving RPCs.
|
||||
ServingModeServing
|
||||
// ServingModeNotServing indicates that the server is not accepting new
|
||||
// connections. Existing connections will be closed gracefully, allowing
|
||||
// in-progress RPCs to complete. A server enters this mode when it does not
|
||||
// contain the required configuration to serve RPCs.
|
||||
ServingModeNotServing
|
||||
)
|
||||
|
||||
func (s ServingMode) String() string {
|
||||
switch s {
|
||||
case ServingModeStarting:
|
||||
return "STARTING"
|
||||
case ServingModeServing:
|
||||
return "SERVING"
|
||||
case ServingModeNotServing:
|
||||
return "NOT_SERVING"
|
||||
default:
|
||||
logger.Errorf("unknown serving mode: %d", s)
|
||||
return "INVALID_MODE"
|
||||
}
|
||||
}
|
||||
332
vendor/google.golang.org/grpc/credentials/alts/alts.go
generated
vendored
Normal file
332
vendor/google.golang.org/grpc/credentials/alts/alts.go
generated
vendored
Normal file
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package alts implements the ALTS credential support by gRPC library, which
|
||||
// encapsulates all the state needed by a client to authenticate with a server
|
||||
// using ALTS and make various assertions, e.g., about the client's identity,
|
||||
// role, or whether it is authorized to make a particular call.
|
||||
// This package is experimental.
|
||||
package alts
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/credentials"
|
||||
core "google.golang.org/grpc/credentials/alts/internal"
|
||||
"google.golang.org/grpc/credentials/alts/internal/handshaker"
|
||||
"google.golang.org/grpc/credentials/alts/internal/handshaker/service"
|
||||
altspb "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/internal/googlecloud"
|
||||
)
|
||||
|
||||
const (
|
||||
// hypervisorHandshakerServiceAddress represents the default ALTS gRPC
|
||||
// handshaker service address in the hypervisor.
|
||||
hypervisorHandshakerServiceAddress = "dns:///metadata.google.internal.:8080"
|
||||
// defaultTimeout specifies the server handshake timeout.
|
||||
defaultTimeout = 30.0 * time.Second
|
||||
// The following constants specify the minimum and maximum acceptable
|
||||
// protocol versions.
|
||||
protocolVersionMaxMajor = 2
|
||||
protocolVersionMaxMinor = 1
|
||||
protocolVersionMinMajor = 2
|
||||
protocolVersionMinMinor = 1
|
||||
)
|
||||
|
||||
var (
|
||||
vmOnGCP bool
|
||||
once sync.Once
|
||||
maxRPCVersion = &altspb.RpcProtocolVersions_Version{
|
||||
Major: protocolVersionMaxMajor,
|
||||
Minor: protocolVersionMaxMinor,
|
||||
}
|
||||
minRPCVersion = &altspb.RpcProtocolVersions_Version{
|
||||
Major: protocolVersionMinMajor,
|
||||
Minor: protocolVersionMinMinor,
|
||||
}
|
||||
// ErrUntrustedPlatform is returned from ClientHandshake and
|
||||
// ServerHandshake is running on a platform where the trustworthiness of
|
||||
// the handshaker service is not guaranteed.
|
||||
ErrUntrustedPlatform = errors.New("ALTS: untrusted platform. ALTS is only supported on GCP")
|
||||
logger = grpclog.Component("alts")
|
||||
)
|
||||
|
||||
// AuthInfo exposes security information from the ALTS handshake to the
|
||||
// application. This interface is to be implemented by ALTS. Users should not
|
||||
// need a brand new implementation of this interface. For situations like
|
||||
// testing, any new implementation should embed this interface. This allows
|
||||
// ALTS to add new methods to this interface.
|
||||
type AuthInfo interface {
|
||||
// ApplicationProtocol returns application protocol negotiated for the
|
||||
// ALTS connection.
|
||||
ApplicationProtocol() string
|
||||
// RecordProtocol returns the record protocol negotiated for the ALTS
|
||||
// connection.
|
||||
RecordProtocol() string
|
||||
// SecurityLevel returns the security level of the created ALTS secure
|
||||
// channel.
|
||||
SecurityLevel() altspb.SecurityLevel
|
||||
// PeerServiceAccount returns the peer service account.
|
||||
PeerServiceAccount() string
|
||||
// LocalServiceAccount returns the local service account.
|
||||
LocalServiceAccount() string
|
||||
// PeerRPCVersions returns the RPC version supported by the peer.
|
||||
PeerRPCVersions() *altspb.RpcProtocolVersions
|
||||
}
|
||||
|
||||
// ClientOptions contains the client-side options of an ALTS channel. These
|
||||
// options will be passed to the underlying ALTS handshaker.
|
||||
type ClientOptions struct {
|
||||
// TargetServiceAccounts contains a list of expected target service
|
||||
// accounts.
|
||||
TargetServiceAccounts []string
|
||||
// HandshakerServiceAddress represents the ALTS handshaker gRPC service
|
||||
// address to connect to.
|
||||
HandshakerServiceAddress string
|
||||
}
|
||||
|
||||
// DefaultClientOptions creates a new ClientOptions object with the default
|
||||
// values.
|
||||
func DefaultClientOptions() *ClientOptions {
|
||||
return &ClientOptions{
|
||||
HandshakerServiceAddress: hypervisorHandshakerServiceAddress,
|
||||
}
|
||||
}
|
||||
|
||||
// ServerOptions contains the server-side options of an ALTS channel. These
|
||||
// options will be passed to the underlying ALTS handshaker.
|
||||
type ServerOptions struct {
|
||||
// HandshakerServiceAddress represents the ALTS handshaker gRPC service
|
||||
// address to connect to.
|
||||
HandshakerServiceAddress string
|
||||
}
|
||||
|
||||
// DefaultServerOptions creates a new ServerOptions object with the default
|
||||
// values.
|
||||
func DefaultServerOptions() *ServerOptions {
|
||||
return &ServerOptions{
|
||||
HandshakerServiceAddress: hypervisorHandshakerServiceAddress,
|
||||
}
|
||||
}
|
||||
|
||||
// altsTC is the credentials required for authenticating a connection using ALTS.
|
||||
// It implements credentials.TransportCredentials interface.
|
||||
type altsTC struct {
|
||||
info *credentials.ProtocolInfo
|
||||
side core.Side
|
||||
accounts []string
|
||||
hsAddress string
|
||||
}
|
||||
|
||||
// NewClientCreds constructs a client-side ALTS TransportCredentials object.
|
||||
func NewClientCreds(opts *ClientOptions) credentials.TransportCredentials {
|
||||
return newALTS(core.ClientSide, opts.TargetServiceAccounts, opts.HandshakerServiceAddress)
|
||||
}
|
||||
|
||||
// NewServerCreds constructs a server-side ALTS TransportCredentials object.
|
||||
func NewServerCreds(opts *ServerOptions) credentials.TransportCredentials {
|
||||
return newALTS(core.ServerSide, nil, opts.HandshakerServiceAddress)
|
||||
}
|
||||
|
||||
func newALTS(side core.Side, accounts []string, hsAddress string) credentials.TransportCredentials {
|
||||
once.Do(func() {
|
||||
vmOnGCP = googlecloud.OnGCE()
|
||||
})
|
||||
if hsAddress == "" {
|
||||
hsAddress = hypervisorHandshakerServiceAddress
|
||||
}
|
||||
return &altsTC{
|
||||
info: &credentials.ProtocolInfo{
|
||||
SecurityProtocol: "alts",
|
||||
SecurityVersion: "1.0",
|
||||
},
|
||||
side: side,
|
||||
accounts: accounts,
|
||||
hsAddress: hsAddress,
|
||||
}
|
||||
}
|
||||
|
||||
// ClientHandshake implements the client side handshake protocol.
|
||||
func (g *altsTC) ClientHandshake(ctx context.Context, addr string, rawConn net.Conn) (_ net.Conn, _ credentials.AuthInfo, err error) {
|
||||
if !vmOnGCP {
|
||||
return nil, nil, ErrUntrustedPlatform
|
||||
}
|
||||
|
||||
// Connecting to ALTS handshaker service.
|
||||
hsConn, err := service.Dial(g.hsAddress)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// Do not close hsConn since it is shared with other handshakes.
|
||||
|
||||
// Possible context leak:
|
||||
// The cancel function for the child context we create will only be
|
||||
// called a non-nil error is returned.
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithCancel(ctx)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
cancel()
|
||||
}
|
||||
}()
|
||||
|
||||
opts := handshaker.DefaultClientHandshakerOptions()
|
||||
opts.TargetName = addr
|
||||
opts.TargetServiceAccounts = g.accounts
|
||||
opts.RPCVersions = &altspb.RpcProtocolVersions{
|
||||
MaxRpcVersion: maxRPCVersion,
|
||||
MinRpcVersion: minRPCVersion,
|
||||
}
|
||||
chs, err := handshaker.NewClientHandshaker(ctx, hsConn, rawConn, opts)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
chs.Close()
|
||||
}
|
||||
}()
|
||||
secConn, authInfo, err := chs.ClientHandshake(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
altsAuthInfo, ok := authInfo.(AuthInfo)
|
||||
if !ok {
|
||||
return nil, nil, errors.New("client-side auth info is not of type alts.AuthInfo")
|
||||
}
|
||||
match, _ := checkRPCVersions(opts.RPCVersions, altsAuthInfo.PeerRPCVersions())
|
||||
if !match {
|
||||
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())
|
||||
}
|
||||
return secConn, authInfo, nil
|
||||
}
|
||||
|
||||
// ServerHandshake implements the server side ALTS handshaker.
|
||||
func (g *altsTC) ServerHandshake(rawConn net.Conn) (_ net.Conn, _ credentials.AuthInfo, err error) {
|
||||
if !vmOnGCP {
|
||||
return nil, nil, ErrUntrustedPlatform
|
||||
}
|
||||
// Connecting to ALTS handshaker service.
|
||||
hsConn, err := service.Dial(g.hsAddress)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// Do not close hsConn since it's shared with other handshakes.
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
|
||||
defer cancel()
|
||||
opts := handshaker.DefaultServerHandshakerOptions()
|
||||
opts.RPCVersions = &altspb.RpcProtocolVersions{
|
||||
MaxRpcVersion: maxRPCVersion,
|
||||
MinRpcVersion: minRPCVersion,
|
||||
}
|
||||
shs, err := handshaker.NewServerHandshaker(ctx, hsConn, rawConn, opts)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
shs.Close()
|
||||
}
|
||||
}()
|
||||
secConn, authInfo, err := shs.ServerHandshake(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
altsAuthInfo, ok := authInfo.(AuthInfo)
|
||||
if !ok {
|
||||
return nil, nil, errors.New("server-side auth info is not of type alts.AuthInfo")
|
||||
}
|
||||
match, _ := checkRPCVersions(opts.RPCVersions, altsAuthInfo.PeerRPCVersions())
|
||||
if !match {
|
||||
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())
|
||||
}
|
||||
return secConn, authInfo, nil
|
||||
}
|
||||
|
||||
func (g *altsTC) Info() credentials.ProtocolInfo {
|
||||
return *g.info
|
||||
}
|
||||
|
||||
func (g *altsTC) Clone() credentials.TransportCredentials {
|
||||
info := *g.info
|
||||
var accounts []string
|
||||
if g.accounts != nil {
|
||||
accounts = make([]string, len(g.accounts))
|
||||
copy(accounts, g.accounts)
|
||||
}
|
||||
return &altsTC{
|
||||
info: &info,
|
||||
side: g.side,
|
||||
hsAddress: g.hsAddress,
|
||||
accounts: accounts,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *altsTC) OverrideServerName(serverNameOverride string) error {
|
||||
g.info.ServerName = serverNameOverride
|
||||
return nil
|
||||
}
|
||||
|
||||
// compareRPCVersion returns 0 if v1 == v2, 1 if v1 > v2 and -1 if v1 < v2.
|
||||
func compareRPCVersions(v1, v2 *altspb.RpcProtocolVersions_Version) int {
|
||||
switch {
|
||||
case v1.GetMajor() > v2.GetMajor(),
|
||||
v1.GetMajor() == v2.GetMajor() && v1.GetMinor() > v2.GetMinor():
|
||||
return 1
|
||||
case v1.GetMajor() < v2.GetMajor(),
|
||||
v1.GetMajor() == v2.GetMajor() && v1.GetMinor() < v2.GetMinor():
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// checkRPCVersions performs a version check between local and peer rpc protocol
|
||||
// versions. This function returns true if the check passes which means both
|
||||
// parties agreed on a common rpc protocol to use, and false otherwise. The
|
||||
// function also returns the highest common RPC protocol version both parties
|
||||
// agreed on.
|
||||
func checkRPCVersions(local, peer *altspb.RpcProtocolVersions) (bool, *altspb.RpcProtocolVersions_Version) {
|
||||
if local == nil || peer == nil {
|
||||
logger.Error("invalid checkRPCVersions argument, either local or peer is nil.")
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// maxCommonVersion is MIN(local.max, peer.max).
|
||||
maxCommonVersion := local.GetMaxRpcVersion()
|
||||
if compareRPCVersions(local.GetMaxRpcVersion(), peer.GetMaxRpcVersion()) > 0 {
|
||||
maxCommonVersion = peer.GetMaxRpcVersion()
|
||||
}
|
||||
|
||||
// minCommonVersion is MAX(local.min, peer.min).
|
||||
minCommonVersion := peer.GetMinRpcVersion()
|
||||
if compareRPCVersions(local.GetMinRpcVersion(), peer.GetMinRpcVersion()) > 0 {
|
||||
minCommonVersion = local.GetMinRpcVersion()
|
||||
}
|
||||
|
||||
if compareRPCVersions(maxCommonVersion, minCommonVersion) < 0 {
|
||||
return false, nil
|
||||
}
|
||||
return true, maxCommonVersion
|
||||
}
|
||||
95
vendor/google.golang.org/grpc/credentials/alts/internal/authinfo/authinfo.go
generated
vendored
Normal file
95
vendor/google.golang.org/grpc/credentials/alts/internal/authinfo/authinfo.go
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package authinfo provide authentication information returned by handshakers.
|
||||
package authinfo
|
||||
|
||||
import (
|
||||
"google.golang.org/grpc/credentials"
|
||||
altspb "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
|
||||
)
|
||||
|
||||
var _ credentials.AuthInfo = (*altsAuthInfo)(nil)
|
||||
|
||||
// altsAuthInfo exposes security information from the ALTS handshake to the
|
||||
// application. altsAuthInfo is immutable and implements credentials.AuthInfo.
|
||||
type altsAuthInfo struct {
|
||||
p *altspb.AltsContext
|
||||
credentials.CommonAuthInfo
|
||||
}
|
||||
|
||||
// New returns a new altsAuthInfo object given handshaker results.
|
||||
func New(result *altspb.HandshakerResult) credentials.AuthInfo {
|
||||
return newAuthInfo(result)
|
||||
}
|
||||
|
||||
func newAuthInfo(result *altspb.HandshakerResult) *altsAuthInfo {
|
||||
return &altsAuthInfo{
|
||||
p: &altspb.AltsContext{
|
||||
ApplicationProtocol: result.GetApplicationProtocol(),
|
||||
RecordProtocol: result.GetRecordProtocol(),
|
||||
// TODO: assign security level from result.
|
||||
SecurityLevel: altspb.SecurityLevel_INTEGRITY_AND_PRIVACY,
|
||||
PeerServiceAccount: result.GetPeerIdentity().GetServiceAccount(),
|
||||
LocalServiceAccount: result.GetLocalIdentity().GetServiceAccount(),
|
||||
PeerRpcVersions: result.GetPeerRpcVersions(),
|
||||
PeerAttributes: result.GetPeerIdentity().GetAttributes(),
|
||||
},
|
||||
CommonAuthInfo: credentials.CommonAuthInfo{SecurityLevel: credentials.PrivacyAndIntegrity},
|
||||
}
|
||||
}
|
||||
|
||||
// AuthType identifies the context as providing ALTS authentication information.
|
||||
func (s *altsAuthInfo) AuthType() string {
|
||||
return "alts"
|
||||
}
|
||||
|
||||
// ApplicationProtocol returns the context's application protocol.
|
||||
func (s *altsAuthInfo) ApplicationProtocol() string {
|
||||
return s.p.GetApplicationProtocol()
|
||||
}
|
||||
|
||||
// RecordProtocol returns the context's record protocol.
|
||||
func (s *altsAuthInfo) RecordProtocol() string {
|
||||
return s.p.GetRecordProtocol()
|
||||
}
|
||||
|
||||
// SecurityLevel returns the context's security level.
|
||||
func (s *altsAuthInfo) SecurityLevel() altspb.SecurityLevel {
|
||||
return s.p.GetSecurityLevel()
|
||||
}
|
||||
|
||||
// PeerServiceAccount returns the context's peer service account.
|
||||
func (s *altsAuthInfo) PeerServiceAccount() string {
|
||||
return s.p.GetPeerServiceAccount()
|
||||
}
|
||||
|
||||
// LocalServiceAccount returns the context's local service account.
|
||||
func (s *altsAuthInfo) LocalServiceAccount() string {
|
||||
return s.p.GetLocalServiceAccount()
|
||||
}
|
||||
|
||||
// PeerRPCVersions returns the context's peer RPC versions.
|
||||
func (s *altsAuthInfo) PeerRPCVersions() *altspb.RpcProtocolVersions {
|
||||
return s.p.GetPeerRpcVersions()
|
||||
}
|
||||
|
||||
// PeerAttributes returns the context's peer attributes.
|
||||
func (s *altsAuthInfo) PeerAttributes() map[string]string {
|
||||
return s.p.GetPeerAttributes()
|
||||
}
|
||||
67
vendor/google.golang.org/grpc/credentials/alts/internal/common.go
generated
vendored
Normal file
67
vendor/google.golang.org/grpc/credentials/alts/internal/common.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package internal contains common core functionality for ALTS.
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"google.golang.org/grpc/credentials"
|
||||
)
|
||||
|
||||
const (
|
||||
// ClientSide identifies the client in this communication.
|
||||
ClientSide Side = iota
|
||||
// ServerSide identifies the server in this communication.
|
||||
ServerSide
|
||||
)
|
||||
|
||||
// PeerNotRespondingError is returned when a peer server is not responding
|
||||
// after a channel has been established. It is treated as a temporary connection
|
||||
// error and re-connection to the server should be attempted.
|
||||
var PeerNotRespondingError = &peerNotRespondingError{}
|
||||
|
||||
// Side identifies the party's role: client or server.
|
||||
type Side int
|
||||
|
||||
type peerNotRespondingError struct{}
|
||||
|
||||
// Return an error message for the purpose of logging.
|
||||
func (e *peerNotRespondingError) Error() string {
|
||||
return "peer server is not responding and re-connection should be attempted."
|
||||
}
|
||||
|
||||
// Temporary indicates if this connection error is temporary or fatal.
|
||||
func (e *peerNotRespondingError) Temporary() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Handshaker defines a ALTS handshaker interface.
|
||||
type Handshaker interface {
|
||||
// ClientHandshake starts and completes a client-side handshaking and
|
||||
// returns a secure connection and corresponding auth information.
|
||||
ClientHandshake(ctx context.Context) (net.Conn, credentials.AuthInfo, error)
|
||||
// ServerHandshake starts and completes a server-side handshaking and
|
||||
// returns a secure connection and corresponding auth information.
|
||||
ServerHandshake(ctx context.Context) (net.Conn, credentials.AuthInfo, error)
|
||||
// Close terminates the Handshaker. It should be called when the caller
|
||||
// obtains the secure connection.
|
||||
Close()
|
||||
}
|
||||
131
vendor/google.golang.org/grpc/credentials/alts/internal/conn/aeadrekey.go
generated
vendored
Normal file
131
vendor/google.golang.org/grpc/credentials/alts/internal/conn/aeadrekey.go
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package conn
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// rekeyAEAD holds the necessary information for an AEAD based on
|
||||
// AES-GCM that performs nonce-based key derivation and XORs the
|
||||
// nonce with a random mask.
|
||||
type rekeyAEAD struct {
|
||||
kdfKey []byte
|
||||
kdfCounter []byte
|
||||
nonceMask []byte
|
||||
nonceBuf []byte
|
||||
gcmAEAD cipher.AEAD
|
||||
}
|
||||
|
||||
// KeySizeError signals that the given key does not have the correct size.
|
||||
type KeySizeError int
|
||||
|
||||
func (k KeySizeError) Error() string {
|
||||
return "alts/conn: invalid key size " + strconv.Itoa(int(k))
|
||||
}
|
||||
|
||||
// newRekeyAEAD creates a new instance of aes128gcm with rekeying.
|
||||
// The key argument should be 44 bytes, the first 32 bytes are used as a key
|
||||
// for HKDF-expand and the remainining 12 bytes are used as a random mask for
|
||||
// the counter.
|
||||
func newRekeyAEAD(key []byte) (*rekeyAEAD, error) {
|
||||
k := len(key)
|
||||
if k != kdfKeyLen+nonceLen {
|
||||
return nil, KeySizeError(k)
|
||||
}
|
||||
return &rekeyAEAD{
|
||||
kdfKey: key[:kdfKeyLen],
|
||||
kdfCounter: make([]byte, kdfCounterLen),
|
||||
nonceMask: key[kdfKeyLen:],
|
||||
nonceBuf: make([]byte, nonceLen),
|
||||
gcmAEAD: nil,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Seal rekeys if nonce[2:8] is different than in the last call, masks the nonce,
|
||||
// and calls Seal for aes128gcm.
|
||||
func (s *rekeyAEAD) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
|
||||
if err := s.rekeyIfRequired(nonce); err != nil {
|
||||
panic(fmt.Sprintf("Rekeying failed with: %s", err.Error()))
|
||||
}
|
||||
maskNonce(s.nonceBuf, nonce, s.nonceMask)
|
||||
return s.gcmAEAD.Seal(dst, s.nonceBuf, plaintext, additionalData)
|
||||
}
|
||||
|
||||
// Open rekeys if nonce[2:8] is different than in the last call, masks the nonce,
|
||||
// and calls Open for aes128gcm.
|
||||
func (s *rekeyAEAD) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
|
||||
if err := s.rekeyIfRequired(nonce); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
maskNonce(s.nonceBuf, nonce, s.nonceMask)
|
||||
return s.gcmAEAD.Open(dst, s.nonceBuf, ciphertext, additionalData)
|
||||
}
|
||||
|
||||
// rekeyIfRequired creates a new aes128gcm AEAD if the existing AEAD is nil
|
||||
// or cannot be used with given nonce.
|
||||
func (s *rekeyAEAD) rekeyIfRequired(nonce []byte) error {
|
||||
newKdfCounter := nonce[kdfCounterOffset : kdfCounterOffset+kdfCounterLen]
|
||||
if s.gcmAEAD != nil && bytes.Equal(newKdfCounter, s.kdfCounter) {
|
||||
return nil
|
||||
}
|
||||
copy(s.kdfCounter, newKdfCounter)
|
||||
a, err := aes.NewCipher(hkdfExpand(s.kdfKey, s.kdfCounter))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.gcmAEAD, err = cipher.NewGCM(a)
|
||||
return err
|
||||
}
|
||||
|
||||
// maskNonce XORs the given nonce with the mask and stores the result in dst.
|
||||
func maskNonce(dst, nonce, mask []byte) {
|
||||
nonce1 := binary.LittleEndian.Uint64(nonce[:sizeUint64])
|
||||
nonce2 := binary.LittleEndian.Uint32(nonce[sizeUint64:])
|
||||
mask1 := binary.LittleEndian.Uint64(mask[:sizeUint64])
|
||||
mask2 := binary.LittleEndian.Uint32(mask[sizeUint64:])
|
||||
binary.LittleEndian.PutUint64(dst[:sizeUint64], nonce1^mask1)
|
||||
binary.LittleEndian.PutUint32(dst[sizeUint64:], nonce2^mask2)
|
||||
}
|
||||
|
||||
// NonceSize returns the required nonce size.
|
||||
func (s *rekeyAEAD) NonceSize() int {
|
||||
return s.gcmAEAD.NonceSize()
|
||||
}
|
||||
|
||||
// Overhead returns the ciphertext overhead.
|
||||
func (s *rekeyAEAD) Overhead() int {
|
||||
return s.gcmAEAD.Overhead()
|
||||
}
|
||||
|
||||
// hkdfExpand computes the first 16 bytes of the HKDF-expand function
|
||||
// defined in RFC5869.
|
||||
func hkdfExpand(key, info []byte) []byte {
|
||||
mac := hmac.New(sha256.New, key)
|
||||
mac.Write(info)
|
||||
mac.Write([]byte{0x01}[:])
|
||||
return mac.Sum(nil)[:aeadKeyLen]
|
||||
}
|
||||
105
vendor/google.golang.org/grpc/credentials/alts/internal/conn/aes128gcm.go
generated
vendored
Normal file
105
vendor/google.golang.org/grpc/credentials/alts/internal/conn/aes128gcm.go
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package conn
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
|
||||
core "google.golang.org/grpc/credentials/alts/internal"
|
||||
)
|
||||
|
||||
const (
|
||||
// Overflow length n in bytes, never encrypt more than 2^(n*8) frames (in
|
||||
// each direction).
|
||||
overflowLenAES128GCM = 5
|
||||
)
|
||||
|
||||
// aes128gcm is the struct that holds necessary information for ALTS record.
|
||||
// The counter value is NOT included in the payload during the encryption and
|
||||
// decryption operations.
|
||||
type aes128gcm struct {
|
||||
// inCounter is used in ALTS record to check that incoming counters are
|
||||
// as expected, since ALTS record guarantees that messages are unwrapped
|
||||
// in the same order that the peer wrapped them.
|
||||
inCounter Counter
|
||||
outCounter Counter
|
||||
aead cipher.AEAD
|
||||
}
|
||||
|
||||
// NewAES128GCM creates an instance that uses aes128gcm for ALTS record.
|
||||
func NewAES128GCM(side core.Side, key []byte) (ALTSRecordCrypto, error) {
|
||||
c, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a, err := cipher.NewGCM(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &aes128gcm{
|
||||
inCounter: NewInCounter(side, overflowLenAES128GCM),
|
||||
outCounter: NewOutCounter(side, overflowLenAES128GCM),
|
||||
aead: a,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Encrypt is the encryption function. dst can contain bytes at the beginning of
|
||||
// the ciphertext that will not be encrypted but will be authenticated. If dst
|
||||
// has enough capacity to hold these bytes, the ciphertext and the tag, no
|
||||
// allocation and copy operations will be performed. dst and plaintext do not
|
||||
// overlap.
|
||||
func (s *aes128gcm) Encrypt(dst, plaintext []byte) ([]byte, error) {
|
||||
// If we need to allocate an output buffer, we want to include space for
|
||||
// GCM tag to avoid forcing ALTS record to reallocate as well.
|
||||
dlen := len(dst)
|
||||
dst, out := SliceForAppend(dst, len(plaintext)+GcmTagSize)
|
||||
seq, err := s.outCounter.Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data := out[:len(plaintext)]
|
||||
copy(data, plaintext) // data may alias plaintext
|
||||
|
||||
// Seal appends the ciphertext and the tag to its first argument and
|
||||
// returns the updated slice. However, SliceForAppend above ensures that
|
||||
// dst has enough capacity to avoid a reallocation and copy due to the
|
||||
// append.
|
||||
dst = s.aead.Seal(dst[:dlen], seq, data, nil)
|
||||
s.outCounter.Inc()
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
func (s *aes128gcm) EncryptionOverhead() int {
|
||||
return GcmTagSize
|
||||
}
|
||||
|
||||
func (s *aes128gcm) Decrypt(dst, ciphertext []byte) ([]byte, error) {
|
||||
seq, err := s.inCounter.Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// If dst is equal to ciphertext[:0], ciphertext storage is reused.
|
||||
plaintext, err := s.aead.Open(dst, seq, ciphertext, nil)
|
||||
if err != nil {
|
||||
return nil, ErrAuth
|
||||
}
|
||||
s.inCounter.Inc()
|
||||
return plaintext, nil
|
||||
}
|
||||
116
vendor/google.golang.org/grpc/credentials/alts/internal/conn/aes128gcmrekey.go
generated
vendored
Normal file
116
vendor/google.golang.org/grpc/credentials/alts/internal/conn/aes128gcmrekey.go
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package conn
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
|
||||
core "google.golang.org/grpc/credentials/alts/internal"
|
||||
)
|
||||
|
||||
const (
|
||||
// Overflow length n in bytes, never encrypt more than 2^(n*8) frames (in
|
||||
// each direction).
|
||||
overflowLenAES128GCMRekey = 8
|
||||
nonceLen = 12
|
||||
aeadKeyLen = 16
|
||||
kdfKeyLen = 32
|
||||
kdfCounterOffset = 2
|
||||
kdfCounterLen = 6
|
||||
sizeUint64 = 8
|
||||
)
|
||||
|
||||
// aes128gcmRekey is the struct that holds necessary information for ALTS record.
|
||||
// The counter value is NOT included in the payload during the encryption and
|
||||
// decryption operations.
|
||||
type aes128gcmRekey struct {
|
||||
// inCounter is used in ALTS record to check that incoming counters are
|
||||
// as expected, since ALTS record guarantees that messages are unwrapped
|
||||
// in the same order that the peer wrapped them.
|
||||
inCounter Counter
|
||||
outCounter Counter
|
||||
inAEAD cipher.AEAD
|
||||
outAEAD cipher.AEAD
|
||||
}
|
||||
|
||||
// NewAES128GCMRekey creates an instance that uses aes128gcm with rekeying
|
||||
// for ALTS record. The key argument should be 44 bytes, the first 32 bytes
|
||||
// are used as a key for HKDF-expand and the remainining 12 bytes are used
|
||||
// as a random mask for the counter.
|
||||
func NewAES128GCMRekey(side core.Side, key []byte) (ALTSRecordCrypto, error) {
|
||||
inCounter := NewInCounter(side, overflowLenAES128GCMRekey)
|
||||
outCounter := NewOutCounter(side, overflowLenAES128GCMRekey)
|
||||
inAEAD, err := newRekeyAEAD(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
outAEAD, err := newRekeyAEAD(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &aes128gcmRekey{
|
||||
inCounter,
|
||||
outCounter,
|
||||
inAEAD,
|
||||
outAEAD,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Encrypt is the encryption function. dst can contain bytes at the beginning of
|
||||
// the ciphertext that will not be encrypted but will be authenticated. If dst
|
||||
// has enough capacity to hold these bytes, the ciphertext and the tag, no
|
||||
// allocation and copy operations will be performed. dst and plaintext do not
|
||||
// overlap.
|
||||
func (s *aes128gcmRekey) Encrypt(dst, plaintext []byte) ([]byte, error) {
|
||||
// If we need to allocate an output buffer, we want to include space for
|
||||
// GCM tag to avoid forcing ALTS record to reallocate as well.
|
||||
dlen := len(dst)
|
||||
dst, out := SliceForAppend(dst, len(plaintext)+GcmTagSize)
|
||||
seq, err := s.outCounter.Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data := out[:len(plaintext)]
|
||||
copy(data, plaintext) // data may alias plaintext
|
||||
|
||||
// Seal appends the ciphertext and the tag to its first argument and
|
||||
// returns the updated slice. However, SliceForAppend above ensures that
|
||||
// dst has enough capacity to avoid a reallocation and copy due to the
|
||||
// append.
|
||||
dst = s.outAEAD.Seal(dst[:dlen], seq, data, nil)
|
||||
s.outCounter.Inc()
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
func (s *aes128gcmRekey) EncryptionOverhead() int {
|
||||
return GcmTagSize
|
||||
}
|
||||
|
||||
func (s *aes128gcmRekey) Decrypt(dst, ciphertext []byte) ([]byte, error) {
|
||||
seq, err := s.inCounter.Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
plaintext, err := s.inAEAD.Open(dst, seq, ciphertext, nil)
|
||||
if err != nil {
|
||||
return nil, ErrAuth
|
||||
}
|
||||
s.inCounter.Inc()
|
||||
return plaintext, nil
|
||||
}
|
||||
70
vendor/google.golang.org/grpc/credentials/alts/internal/conn/common.go
generated
vendored
Normal file
70
vendor/google.golang.org/grpc/credentials/alts/internal/conn/common.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package conn
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
// GcmTagSize is the GCM tag size is the difference in length between
|
||||
// plaintext and ciphertext. From crypto/cipher/gcm.go in Go crypto
|
||||
// library.
|
||||
GcmTagSize = 16
|
||||
)
|
||||
|
||||
// ErrAuth occurs on authentication failure.
|
||||
var ErrAuth = errors.New("message authentication failed")
|
||||
|
||||
// SliceForAppend takes a slice and a requested number of bytes. It returns a
|
||||
// slice with the contents of the given slice followed by that many bytes and a
|
||||
// second slice that aliases into it and contains only the extra bytes. If the
|
||||
// original slice has sufficient capacity then no allocation is performed.
|
||||
func SliceForAppend(in []byte, n int) (head, tail []byte) {
|
||||
if total := len(in) + n; cap(in) >= total {
|
||||
head = in[:total]
|
||||
} else {
|
||||
head = make([]byte, total)
|
||||
copy(head, in)
|
||||
}
|
||||
tail = head[len(in):]
|
||||
return head, tail
|
||||
}
|
||||
|
||||
// ParseFramedMsg parse the provided buffer and returns a frame of the format
|
||||
// msgLength+msg and any remaining bytes in that buffer.
|
||||
func ParseFramedMsg(b []byte, maxLen uint32) ([]byte, []byte, error) {
|
||||
// If the size field is not complete, return the provided buffer as
|
||||
// remaining buffer.
|
||||
if len(b) < MsgLenFieldSize {
|
||||
return nil, b, nil
|
||||
}
|
||||
msgLenField := b[:MsgLenFieldSize]
|
||||
length := binary.LittleEndian.Uint32(msgLenField)
|
||||
if length > maxLen {
|
||||
return nil, nil, fmt.Errorf("received the frame length %d larger than the limit %d", length, maxLen)
|
||||
}
|
||||
if len(b) < int(length)+4 { // account for the first 4 msg length bytes.
|
||||
// Frame is not complete yet.
|
||||
return nil, b, nil
|
||||
}
|
||||
return b[:MsgLenFieldSize+length], b[MsgLenFieldSize+length:], nil
|
||||
}
|
||||
62
vendor/google.golang.org/grpc/credentials/alts/internal/conn/counter.go
generated
vendored
Normal file
62
vendor/google.golang.org/grpc/credentials/alts/internal/conn/counter.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package conn
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
const counterLen = 12
|
||||
|
||||
var (
|
||||
errInvalidCounter = errors.New("invalid counter")
|
||||
)
|
||||
|
||||
// Counter is a 96-bit, little-endian counter.
|
||||
type Counter struct {
|
||||
value [counterLen]byte
|
||||
invalid bool
|
||||
overflowLen int
|
||||
}
|
||||
|
||||
// Value returns the current value of the counter as a byte slice.
|
||||
func (c *Counter) Value() ([]byte, error) {
|
||||
if c.invalid {
|
||||
return nil, errInvalidCounter
|
||||
}
|
||||
return c.value[:], nil
|
||||
}
|
||||
|
||||
// Inc increments the counter and checks for overflow.
|
||||
func (c *Counter) Inc() {
|
||||
// If the counter is already invalid, there is no need to increase it.
|
||||
if c.invalid {
|
||||
return
|
||||
}
|
||||
i := 0
|
||||
for ; i < c.overflowLen; i++ {
|
||||
c.value[i]++
|
||||
if c.value[i] != 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if i == c.overflowLen {
|
||||
c.invalid = true
|
||||
}
|
||||
}
|
||||
275
vendor/google.golang.org/grpc/credentials/alts/internal/conn/record.go
generated
vendored
Normal file
275
vendor/google.golang.org/grpc/credentials/alts/internal/conn/record.go
generated
vendored
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package conn contains an implementation of a secure channel created by gRPC
|
||||
// handshakers.
|
||||
package conn
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
|
||||
core "google.golang.org/grpc/credentials/alts/internal"
|
||||
)
|
||||
|
||||
// ALTSRecordCrypto is the interface for gRPC ALTS record protocol.
|
||||
type ALTSRecordCrypto interface {
|
||||
// Encrypt encrypts the plaintext and computes the tag (if any) of dst
|
||||
// and plaintext. dst and plaintext may fully overlap or not at all.
|
||||
Encrypt(dst, plaintext []byte) ([]byte, error)
|
||||
// EncryptionOverhead returns the tag size (if any) in bytes.
|
||||
EncryptionOverhead() int
|
||||
// Decrypt decrypts ciphertext and verify the tag (if any). dst and
|
||||
// ciphertext may alias exactly or not at all. To reuse ciphertext's
|
||||
// storage for the decrypted output, use ciphertext[:0] as dst.
|
||||
Decrypt(dst, ciphertext []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
// ALTSRecordFunc is a function type for factory functions that create
|
||||
// ALTSRecordCrypto instances.
|
||||
type ALTSRecordFunc func(s core.Side, keyData []byte) (ALTSRecordCrypto, error)
|
||||
|
||||
const (
|
||||
// MsgLenFieldSize is the byte size of the frame length field of a
|
||||
// framed message.
|
||||
MsgLenFieldSize = 4
|
||||
// The byte size of the message type field of a framed message.
|
||||
msgTypeFieldSize = 4
|
||||
// The bytes size limit for a ALTS record message.
|
||||
altsRecordLengthLimit = 1024 * 1024 // 1 MiB
|
||||
// The default bytes size of a ALTS record message.
|
||||
altsRecordDefaultLength = 4 * 1024 // 4KiB
|
||||
// Message type value included in ALTS record framing.
|
||||
altsRecordMsgType = uint32(0x06)
|
||||
// The initial write buffer size.
|
||||
altsWriteBufferInitialSize = 32 * 1024 // 32KiB
|
||||
// The maximum write buffer size. This *must* be multiple of
|
||||
// altsRecordDefaultLength.
|
||||
altsWriteBufferMaxSize = 512 * 1024 // 512KiB
|
||||
)
|
||||
|
||||
var (
|
||||
protocols = make(map[string]ALTSRecordFunc)
|
||||
)
|
||||
|
||||
// RegisterProtocol register a ALTS record encryption protocol.
|
||||
func RegisterProtocol(protocol string, f ALTSRecordFunc) error {
|
||||
if _, ok := protocols[protocol]; ok {
|
||||
return fmt.Errorf("protocol %v is already registered", protocol)
|
||||
}
|
||||
protocols[protocol] = f
|
||||
return nil
|
||||
}
|
||||
|
||||
// conn represents a secured connection. It implements the net.Conn interface.
|
||||
type conn struct {
|
||||
net.Conn
|
||||
crypto ALTSRecordCrypto
|
||||
// buf holds data that has been read from the connection and decrypted,
|
||||
// but has not yet been returned by Read.
|
||||
buf []byte
|
||||
payloadLengthLimit int
|
||||
// protected holds data read from the network but have not yet been
|
||||
// decrypted. This data might not compose a complete frame.
|
||||
protected []byte
|
||||
// writeBuf is a buffer used to contain encrypted frames before being
|
||||
// written to the network.
|
||||
writeBuf []byte
|
||||
// nextFrame stores the next frame (in protected buffer) info.
|
||||
nextFrame []byte
|
||||
// overhead is the calculated overhead of each frame.
|
||||
overhead int
|
||||
}
|
||||
|
||||
// NewConn creates a new secure channel instance given the other party role and
|
||||
// handshaking result.
|
||||
func NewConn(c net.Conn, side core.Side, recordProtocol string, key []byte, protected []byte) (net.Conn, error) {
|
||||
newCrypto := protocols[recordProtocol]
|
||||
if newCrypto == nil {
|
||||
return nil, fmt.Errorf("negotiated unknown next_protocol %q", recordProtocol)
|
||||
}
|
||||
crypto, err := newCrypto(side, key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("protocol %q: %v", recordProtocol, err)
|
||||
}
|
||||
overhead := MsgLenFieldSize + msgTypeFieldSize + crypto.EncryptionOverhead()
|
||||
payloadLengthLimit := altsRecordDefaultLength - overhead
|
||||
var protectedBuf []byte
|
||||
if protected == nil {
|
||||
// We pre-allocate protected to be of size
|
||||
// 2*altsRecordDefaultLength-1 during initialization. We only
|
||||
// read from the network into protected when protected does not
|
||||
// contain a complete frame, which is at most
|
||||
// altsRecordDefaultLength-1 (bytes). And we read at most
|
||||
// altsRecordDefaultLength (bytes) data into protected at one
|
||||
// time. Therefore, 2*altsRecordDefaultLength-1 is large enough
|
||||
// to buffer data read from the network.
|
||||
protectedBuf = make([]byte, 0, 2*altsRecordDefaultLength-1)
|
||||
} else {
|
||||
protectedBuf = make([]byte, len(protected))
|
||||
copy(protectedBuf, protected)
|
||||
}
|
||||
|
||||
altsConn := &conn{
|
||||
Conn: c,
|
||||
crypto: crypto,
|
||||
payloadLengthLimit: payloadLengthLimit,
|
||||
protected: protectedBuf,
|
||||
writeBuf: make([]byte, altsWriteBufferInitialSize),
|
||||
nextFrame: protectedBuf,
|
||||
overhead: overhead,
|
||||
}
|
||||
return altsConn, nil
|
||||
}
|
||||
|
||||
// Read reads and decrypts a frame from the underlying connection, and copies the
|
||||
// decrypted payload into b. If the size of the payload is greater than len(b),
|
||||
// Read retains the remaining bytes in an internal buffer, and subsequent calls
|
||||
// to Read will read from this buffer until it is exhausted.
|
||||
func (p *conn) Read(b []byte) (n int, err error) {
|
||||
if len(p.buf) == 0 {
|
||||
var framedMsg []byte
|
||||
framedMsg, p.nextFrame, err = ParseFramedMsg(p.nextFrame, altsRecordLengthLimit)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
// Check whether the next frame to be decrypted has been
|
||||
// completely received yet.
|
||||
if len(framedMsg) == 0 {
|
||||
copy(p.protected, p.nextFrame)
|
||||
p.protected = p.protected[:len(p.nextFrame)]
|
||||
// Always copy next incomplete frame to the beginning of
|
||||
// the protected buffer and reset nextFrame to it.
|
||||
p.nextFrame = p.protected
|
||||
}
|
||||
// Check whether a complete frame has been received yet.
|
||||
for len(framedMsg) == 0 {
|
||||
if len(p.protected) == cap(p.protected) {
|
||||
tmp := make([]byte, len(p.protected), cap(p.protected)+altsRecordDefaultLength)
|
||||
copy(tmp, p.protected)
|
||||
p.protected = tmp
|
||||
}
|
||||
n, err = p.Conn.Read(p.protected[len(p.protected):min(cap(p.protected), len(p.protected)+altsRecordDefaultLength)])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
p.protected = p.protected[:len(p.protected)+n]
|
||||
framedMsg, p.nextFrame, err = ParseFramedMsg(p.protected, altsRecordLengthLimit)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
// Now we have a complete frame, decrypted it.
|
||||
msg := framedMsg[MsgLenFieldSize:]
|
||||
msgType := binary.LittleEndian.Uint32(msg[:msgTypeFieldSize])
|
||||
if msgType&0xff != altsRecordMsgType {
|
||||
return 0, fmt.Errorf("received frame with incorrect message type %v, expected lower byte %v",
|
||||
msgType, altsRecordMsgType)
|
||||
}
|
||||
ciphertext := msg[msgTypeFieldSize:]
|
||||
|
||||
// Decrypt requires that if the dst and ciphertext alias, they
|
||||
// must alias exactly. Code here used to use msg[:0], but msg
|
||||
// starts MsgLenFieldSize+msgTypeFieldSize bytes earlier than
|
||||
// ciphertext, so they alias inexactly. Using ciphertext[:0]
|
||||
// arranges the appropriate aliasing without needing to copy
|
||||
// ciphertext or use a separate destination buffer. For more info
|
||||
// check: https://golang.org/pkg/crypto/cipher/#AEAD.
|
||||
p.buf, err = p.crypto.Decrypt(ciphertext[:0], ciphertext)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
n = copy(b, p.buf)
|
||||
p.buf = p.buf[n:]
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// Write encrypts, frames, and writes bytes from b to the underlying connection.
|
||||
func (p *conn) Write(b []byte) (n int, err error) {
|
||||
n = len(b)
|
||||
// Calculate the output buffer size with framing and encryption overhead.
|
||||
numOfFrames := int(math.Ceil(float64(len(b)) / float64(p.payloadLengthLimit)))
|
||||
size := len(b) + numOfFrames*p.overhead
|
||||
// If writeBuf is too small, increase its size up to the maximum size.
|
||||
partialBSize := len(b)
|
||||
if size > altsWriteBufferMaxSize {
|
||||
size = altsWriteBufferMaxSize
|
||||
const numOfFramesInMaxWriteBuf = altsWriteBufferMaxSize / altsRecordDefaultLength
|
||||
partialBSize = numOfFramesInMaxWriteBuf * p.payloadLengthLimit
|
||||
}
|
||||
if len(p.writeBuf) < size {
|
||||
p.writeBuf = make([]byte, size)
|
||||
}
|
||||
|
||||
for partialBStart := 0; partialBStart < len(b); partialBStart += partialBSize {
|
||||
partialBEnd := partialBStart + partialBSize
|
||||
if partialBEnd > len(b) {
|
||||
partialBEnd = len(b)
|
||||
}
|
||||
partialB := b[partialBStart:partialBEnd]
|
||||
writeBufIndex := 0
|
||||
for len(partialB) > 0 {
|
||||
payloadLen := len(partialB)
|
||||
if payloadLen > p.payloadLengthLimit {
|
||||
payloadLen = p.payloadLengthLimit
|
||||
}
|
||||
buf := partialB[:payloadLen]
|
||||
partialB = partialB[payloadLen:]
|
||||
|
||||
// Write buffer contains: length, type, payload, and tag
|
||||
// if any.
|
||||
|
||||
// 1. Fill in type field.
|
||||
msg := p.writeBuf[writeBufIndex+MsgLenFieldSize:]
|
||||
binary.LittleEndian.PutUint32(msg, altsRecordMsgType)
|
||||
|
||||
// 2. Encrypt the payload and create a tag if any.
|
||||
msg, err = p.crypto.Encrypt(msg[:msgTypeFieldSize], buf)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
|
||||
// 3. Fill in the size field.
|
||||
binary.LittleEndian.PutUint32(p.writeBuf[writeBufIndex:], uint32(len(msg)))
|
||||
|
||||
// 4. Increase writeBufIndex.
|
||||
writeBufIndex += len(buf) + p.overhead
|
||||
}
|
||||
nn, err := p.Conn.Write(p.writeBuf[:writeBufIndex])
|
||||
if err != nil {
|
||||
// We need to calculate the actual data size that was
|
||||
// written. This means we need to remove header,
|
||||
// encryption overheads, and any partially-written
|
||||
// frame data.
|
||||
numOfWrittenFrames := int(math.Floor(float64(nn) / float64(altsRecordDefaultLength)))
|
||||
return partialBStart + numOfWrittenFrames*p.payloadLengthLimit, err
|
||||
}
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
63
vendor/google.golang.org/grpc/credentials/alts/internal/conn/utils.go
generated
vendored
Normal file
63
vendor/google.golang.org/grpc/credentials/alts/internal/conn/utils.go
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package conn
|
||||
|
||||
import core "google.golang.org/grpc/credentials/alts/internal"
|
||||
|
||||
// NewOutCounter returns an outgoing counter initialized to the starting sequence
|
||||
// number for the client/server side of a connection.
|
||||
func NewOutCounter(s core.Side, overflowLen int) (c Counter) {
|
||||
c.overflowLen = overflowLen
|
||||
if s == core.ServerSide {
|
||||
// Server counters in ALTS record have the little-endian high bit
|
||||
// set.
|
||||
c.value[counterLen-1] = 0x80
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// NewInCounter returns an incoming counter initialized to the starting sequence
|
||||
// number for the client/server side of a connection. This is used in ALTS record
|
||||
// to check that incoming counters are as expected, since ALTS record guarantees
|
||||
// that messages are unwrapped in the same order that the peer wrapped them.
|
||||
func NewInCounter(s core.Side, overflowLen int) (c Counter) {
|
||||
c.overflowLen = overflowLen
|
||||
if s == core.ClientSide {
|
||||
// Server counters in ALTS record have the little-endian high bit
|
||||
// set.
|
||||
c.value[counterLen-1] = 0x80
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// CounterFromValue creates a new counter given an initial value.
|
||||
func CounterFromValue(value []byte, overflowLen int) (c Counter) {
|
||||
c.overflowLen = overflowLen
|
||||
copy(c.value[:], value)
|
||||
return
|
||||
}
|
||||
|
||||
// CounterSide returns the connection side (client/server) a sequence counter is
|
||||
// associated with.
|
||||
func CounterSide(c []byte) core.Side {
|
||||
if c[counterLen-1]&0x80 == 0x80 {
|
||||
return core.ServerSide
|
||||
}
|
||||
return core.ClientSide
|
||||
}
|
||||
373
vendor/google.golang.org/grpc/credentials/alts/internal/handshaker/handshaker.go
generated
vendored
Normal file
373
vendor/google.golang.org/grpc/credentials/alts/internal/handshaker/handshaker.go
generated
vendored
Normal file
@@ -0,0 +1,373 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package handshaker provides ALTS handshaking functionality for GCP.
|
||||
package handshaker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sync/semaphore"
|
||||
grpc "google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
core "google.golang.org/grpc/credentials/alts/internal"
|
||||
"google.golang.org/grpc/credentials/alts/internal/authinfo"
|
||||
"google.golang.org/grpc/credentials/alts/internal/conn"
|
||||
altsgrpc "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
|
||||
altspb "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
|
||||
"google.golang.org/grpc/internal/envconfig"
|
||||
)
|
||||
|
||||
const (
|
||||
// The maximum byte size of receive frames.
|
||||
frameLimit = 64 * 1024 // 64 KB
|
||||
rekeyRecordProtocolName = "ALTSRP_GCM_AES128_REKEY"
|
||||
)
|
||||
|
||||
var (
|
||||
hsProtocol = altspb.HandshakeProtocol_ALTS
|
||||
appProtocols = []string{"grpc"}
|
||||
recordProtocols = []string{rekeyRecordProtocolName}
|
||||
keyLength = map[string]int{
|
||||
rekeyRecordProtocolName: 44,
|
||||
}
|
||||
altsRecordFuncs = map[string]conn.ALTSRecordFunc{
|
||||
// ALTS handshaker protocols.
|
||||
rekeyRecordProtocolName: func(s core.Side, keyData []byte) (conn.ALTSRecordCrypto, error) {
|
||||
return conn.NewAES128GCMRekey(s, keyData)
|
||||
},
|
||||
}
|
||||
// control number of concurrent created (but not closed) handshakes.
|
||||
clientHandshakes = semaphore.NewWeighted(int64(envconfig.ALTSMaxConcurrentHandshakes))
|
||||
serverHandshakes = semaphore.NewWeighted(int64(envconfig.ALTSMaxConcurrentHandshakes))
|
||||
// errOutOfBound occurs when the handshake service returns a consumed
|
||||
// bytes value larger than the buffer that was passed to it originally.
|
||||
errOutOfBound = errors.New("handshaker service consumed bytes value is out-of-bound")
|
||||
)
|
||||
|
||||
func init() {
|
||||
for protocol, f := range altsRecordFuncs {
|
||||
if err := conn.RegisterProtocol(protocol, f); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ClientHandshakerOptions contains the client handshaker options that can
|
||||
// provided by the caller.
|
||||
type ClientHandshakerOptions struct {
|
||||
// ClientIdentity is the handshaker client local identity.
|
||||
ClientIdentity *altspb.Identity
|
||||
// TargetName is the server service account name for secure name
|
||||
// checking.
|
||||
TargetName string
|
||||
// TargetServiceAccounts contains a list of expected target service
|
||||
// accounts. One of these accounts should match one of the accounts in
|
||||
// the handshaker results. Otherwise, the handshake fails.
|
||||
TargetServiceAccounts []string
|
||||
// RPCVersions specifies the gRPC versions accepted by the client.
|
||||
RPCVersions *altspb.RpcProtocolVersions
|
||||
}
|
||||
|
||||
// ServerHandshakerOptions contains the server handshaker options that can
|
||||
// provided by the caller.
|
||||
type ServerHandshakerOptions struct {
|
||||
// RPCVersions specifies the gRPC versions accepted by the server.
|
||||
RPCVersions *altspb.RpcProtocolVersions
|
||||
}
|
||||
|
||||
// DefaultClientHandshakerOptions returns the default client handshaker options.
|
||||
func DefaultClientHandshakerOptions() *ClientHandshakerOptions {
|
||||
return &ClientHandshakerOptions{}
|
||||
}
|
||||
|
||||
// DefaultServerHandshakerOptions returns the default client handshaker options.
|
||||
func DefaultServerHandshakerOptions() *ServerHandshakerOptions {
|
||||
return &ServerHandshakerOptions{}
|
||||
}
|
||||
|
||||
// altsHandshaker is used to complete an ALTS handshake between client and
|
||||
// server. This handshaker talks to the ALTS handshaker service in the metadata
|
||||
// server.
|
||||
type altsHandshaker struct {
|
||||
// RPC stream used to access the ALTS Handshaker service.
|
||||
stream altsgrpc.HandshakerService_DoHandshakeClient
|
||||
// the connection to the peer.
|
||||
conn net.Conn
|
||||
// a virtual connection to the ALTS handshaker service.
|
||||
clientConn *grpc.ClientConn
|
||||
// client handshake options.
|
||||
clientOpts *ClientHandshakerOptions
|
||||
// server handshake options.
|
||||
serverOpts *ServerHandshakerOptions
|
||||
// defines the side doing the handshake, client or server.
|
||||
side core.Side
|
||||
}
|
||||
|
||||
// NewClientHandshaker creates a core.Handshaker that performs a client-side
|
||||
// ALTS handshake by acting as a proxy between the peer and the ALTS handshaker
|
||||
// service in the metadata server.
|
||||
func NewClientHandshaker(ctx context.Context, conn *grpc.ClientConn, c net.Conn, opts *ClientHandshakerOptions) (core.Handshaker, error) {
|
||||
return &altsHandshaker{
|
||||
stream: nil,
|
||||
conn: c,
|
||||
clientConn: conn,
|
||||
clientOpts: opts,
|
||||
side: core.ClientSide,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewServerHandshaker creates a core.Handshaker that performs a server-side
|
||||
// ALTS handshake by acting as a proxy between the peer and the ALTS handshaker
|
||||
// service in the metadata server.
|
||||
func NewServerHandshaker(ctx context.Context, conn *grpc.ClientConn, c net.Conn, opts *ServerHandshakerOptions) (core.Handshaker, error) {
|
||||
return &altsHandshaker{
|
||||
stream: nil,
|
||||
conn: c,
|
||||
clientConn: conn,
|
||||
serverOpts: opts,
|
||||
side: core.ServerSide,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ClientHandshake starts and completes a client ALTS handshake for GCP. Once
|
||||
// done, ClientHandshake returns a secure connection.
|
||||
func (h *altsHandshaker) ClientHandshake(ctx context.Context) (net.Conn, credentials.AuthInfo, error) {
|
||||
if err := clientHandshakes.Acquire(ctx, 1); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer clientHandshakes.Release(1)
|
||||
|
||||
if h.side != core.ClientSide {
|
||||
return nil, nil, errors.New("only handshakers created using NewClientHandshaker can perform a client handshaker")
|
||||
}
|
||||
|
||||
// TODO(matthewstevenson88): Change unit tests to use public APIs so
|
||||
// that h.stream can unconditionally be set based on h.clientConn.
|
||||
if h.stream == nil {
|
||||
stream, err := altsgrpc.NewHandshakerServiceClient(h.clientConn).DoHandshake(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to establish stream to ALTS handshaker service: %v", err)
|
||||
}
|
||||
h.stream = stream
|
||||
}
|
||||
|
||||
// Create target identities from service account list.
|
||||
targetIdentities := make([]*altspb.Identity, 0, len(h.clientOpts.TargetServiceAccounts))
|
||||
for _, account := range h.clientOpts.TargetServiceAccounts {
|
||||
targetIdentities = append(targetIdentities, &altspb.Identity{
|
||||
IdentityOneof: &altspb.Identity_ServiceAccount{
|
||||
ServiceAccount: account,
|
||||
},
|
||||
})
|
||||
}
|
||||
req := &altspb.HandshakerReq{
|
||||
ReqOneof: &altspb.HandshakerReq_ClientStart{
|
||||
ClientStart: &altspb.StartClientHandshakeReq{
|
||||
HandshakeSecurityProtocol: hsProtocol,
|
||||
ApplicationProtocols: appProtocols,
|
||||
RecordProtocols: recordProtocols,
|
||||
TargetIdentities: targetIdentities,
|
||||
LocalIdentity: h.clientOpts.ClientIdentity,
|
||||
TargetName: h.clientOpts.TargetName,
|
||||
RpcVersions: h.clientOpts.RPCVersions,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
conn, result, err := h.doHandshake(req)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
authInfo := authinfo.New(result)
|
||||
return conn, authInfo, nil
|
||||
}
|
||||
|
||||
// ServerHandshake starts and completes a server ALTS handshake for GCP. Once
|
||||
// done, ServerHandshake returns a secure connection.
|
||||
func (h *altsHandshaker) ServerHandshake(ctx context.Context) (net.Conn, credentials.AuthInfo, error) {
|
||||
if err := serverHandshakes.Acquire(ctx, 1); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer serverHandshakes.Release(1)
|
||||
|
||||
if h.side != core.ServerSide {
|
||||
return nil, nil, errors.New("only handshakers created using NewServerHandshaker can perform a server handshaker")
|
||||
}
|
||||
|
||||
// TODO(matthewstevenson88): Change unit tests to use public APIs so
|
||||
// that h.stream can unconditionally be set based on h.clientConn.
|
||||
if h.stream == nil {
|
||||
stream, err := altsgrpc.NewHandshakerServiceClient(h.clientConn).DoHandshake(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to establish stream to ALTS handshaker service: %v", err)
|
||||
}
|
||||
h.stream = stream
|
||||
}
|
||||
|
||||
p := make([]byte, frameLimit)
|
||||
n, err := h.conn.Read(p)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Prepare server parameters.
|
||||
params := make(map[int32]*altspb.ServerHandshakeParameters)
|
||||
params[int32(altspb.HandshakeProtocol_ALTS)] = &altspb.ServerHandshakeParameters{
|
||||
RecordProtocols: recordProtocols,
|
||||
}
|
||||
req := &altspb.HandshakerReq{
|
||||
ReqOneof: &altspb.HandshakerReq_ServerStart{
|
||||
ServerStart: &altspb.StartServerHandshakeReq{
|
||||
ApplicationProtocols: appProtocols,
|
||||
HandshakeParameters: params,
|
||||
InBytes: p[:n],
|
||||
RpcVersions: h.serverOpts.RPCVersions,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
conn, result, err := h.doHandshake(req)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
authInfo := authinfo.New(result)
|
||||
return conn, authInfo, nil
|
||||
}
|
||||
|
||||
func (h *altsHandshaker) doHandshake(req *altspb.HandshakerReq) (net.Conn, *altspb.HandshakerResult, error) {
|
||||
resp, err := h.accessHandshakerService(req)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// Check of the returned status is an error.
|
||||
if resp.GetStatus() != nil {
|
||||
if got, want := resp.GetStatus().Code, uint32(codes.OK); got != want {
|
||||
return nil, nil, fmt.Errorf("%v", resp.GetStatus().Details)
|
||||
}
|
||||
}
|
||||
|
||||
var extra []byte
|
||||
if req.GetServerStart() != nil {
|
||||
if resp.GetBytesConsumed() > uint32(len(req.GetServerStart().GetInBytes())) {
|
||||
return nil, nil, errOutOfBound
|
||||
}
|
||||
extra = req.GetServerStart().GetInBytes()[resp.GetBytesConsumed():]
|
||||
}
|
||||
result, extra, err := h.processUntilDone(resp, extra)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// The handshaker returns a 128 bytes key. It should be truncated based
|
||||
// on the returned record protocol.
|
||||
keyLen, ok := keyLength[result.RecordProtocol]
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("unknown resulted record protocol %v", result.RecordProtocol)
|
||||
}
|
||||
sc, err := conn.NewConn(h.conn, h.side, result.GetRecordProtocol(), result.KeyData[:keyLen], extra)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return sc, result, nil
|
||||
}
|
||||
|
||||
func (h *altsHandshaker) accessHandshakerService(req *altspb.HandshakerReq) (*altspb.HandshakerResp, error) {
|
||||
if err := h.stream.Send(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := h.stream.Recv()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// processUntilDone processes the handshake until the handshaker service returns
|
||||
// the results. Handshaker service takes care of frame parsing, so we read
|
||||
// whatever received from the network and send it to the handshaker service.
|
||||
func (h *altsHandshaker) processUntilDone(resp *altspb.HandshakerResp, extra []byte) (*altspb.HandshakerResult, []byte, error) {
|
||||
var lastWriteTime time.Time
|
||||
for {
|
||||
if len(resp.OutFrames) > 0 {
|
||||
lastWriteTime = time.Now()
|
||||
if _, err := h.conn.Write(resp.OutFrames); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
if resp.Result != nil {
|
||||
return resp.Result, extra, nil
|
||||
}
|
||||
buf := make([]byte, frameLimit)
|
||||
n, err := h.conn.Read(buf)
|
||||
if err != nil && err != io.EOF {
|
||||
return nil, nil, err
|
||||
}
|
||||
// If there is nothing to send to the handshaker service, and
|
||||
// nothing is received from the peer, then we are stuck.
|
||||
// This covers the case when the peer is not responding. Note
|
||||
// that handshaker service connection issues are caught in
|
||||
// accessHandshakerService before we even get here.
|
||||
if len(resp.OutFrames) == 0 && n == 0 {
|
||||
return nil, nil, core.PeerNotRespondingError
|
||||
}
|
||||
// Append extra bytes from the previous interaction with the
|
||||
// handshaker service with the current buffer read from conn.
|
||||
p := append(extra, buf[:n]...)
|
||||
// Compute the time elapsed since the last write to the peer.
|
||||
timeElapsed := time.Since(lastWriteTime)
|
||||
timeElapsedMs := uint32(timeElapsed.Milliseconds())
|
||||
// From here on, p and extra point to the same slice.
|
||||
resp, err = h.accessHandshakerService(&altspb.HandshakerReq{
|
||||
ReqOneof: &altspb.HandshakerReq_Next{
|
||||
Next: &altspb.NextHandshakeMessageReq{
|
||||
InBytes: p,
|
||||
NetworkLatencyMs: timeElapsedMs,
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// Set extra based on handshaker service response.
|
||||
if resp.GetBytesConsumed() > uint32(len(p)) {
|
||||
return nil, nil, errOutOfBound
|
||||
}
|
||||
extra = p[resp.GetBytesConsumed():]
|
||||
}
|
||||
}
|
||||
|
||||
// Close terminates the Handshaker. It should be called when the caller obtains
|
||||
// the secure connection.
|
||||
func (h *altsHandshaker) Close() {
|
||||
if h.stream != nil {
|
||||
h.stream.CloseSend()
|
||||
}
|
||||
}
|
||||
|
||||
// ResetConcurrentHandshakeSemaphoreForTesting resets the handshake semaphores
|
||||
// to allow numberOfAllowedHandshakes concurrent handshakes each.
|
||||
func ResetConcurrentHandshakeSemaphoreForTesting(numberOfAllowedHandshakes int64) {
|
||||
clientHandshakes = semaphore.NewWeighted(numberOfAllowedHandshakes)
|
||||
serverHandshakes = semaphore.NewWeighted(numberOfAllowedHandshakes)
|
||||
}
|
||||
78
vendor/google.golang.org/grpc/credentials/alts/internal/handshaker/service/service.go
generated
vendored
Normal file
78
vendor/google.golang.org/grpc/credentials/alts/internal/handshaker/service/service.go
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package service manages connections between the VM application and the ALTS
|
||||
// handshaker service.
|
||||
package service
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
grpc "google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
)
|
||||
|
||||
var (
|
||||
// mu guards hsConnMap and hsDialer.
|
||||
mu sync.Mutex
|
||||
// hsConn represents a mapping from a hypervisor handshaker service address
|
||||
// to a corresponding connection to a hypervisor handshaker service
|
||||
// instance.
|
||||
hsConnMap = make(map[string]*grpc.ClientConn)
|
||||
// hsDialer will be reassigned in tests.
|
||||
hsDialer = grpc.Dial
|
||||
)
|
||||
|
||||
// Dial dials the handshake service in the hypervisor. If a connection has
|
||||
// already been established, this function returns it. Otherwise, a new
|
||||
// connection is created.
|
||||
func Dial(hsAddress string) (*grpc.ClientConn, error) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
hsConn, ok := hsConnMap[hsAddress]
|
||||
if !ok {
|
||||
// Create a new connection to the handshaker service. Note that
|
||||
// this connection stays open until the application is closed.
|
||||
var err error
|
||||
hsConn, err = hsDialer(hsAddress, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hsConnMap[hsAddress] = hsConn
|
||||
}
|
||||
return hsConn, nil
|
||||
}
|
||||
|
||||
// CloseForTesting closes all open connections to the handshaker service.
|
||||
//
|
||||
// For testing purposes only.
|
||||
func CloseForTesting() error {
|
||||
for _, hsConn := range hsConnMap {
|
||||
if hsConn == nil {
|
||||
continue
|
||||
}
|
||||
if err := hsConn.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the connection map.
|
||||
hsConnMap = make(map[string]*grpc.ClientConn)
|
||||
return nil
|
||||
}
|
||||
259
vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/altscontext.pb.go
generated
vendored
Normal file
259
vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/altscontext.pb.go
generated
vendored
Normal file
@@ -0,0 +1,259 @@
|
||||
// Copyright 2018 The gRPC Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The canonical version of this proto can be found at
|
||||
// https://github.com/grpc/grpc-proto/blob/master/grpc/gcp/altscontext.proto
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.25.2
|
||||
// source: grpc/gcp/altscontext.proto
|
||||
|
||||
package grpc_gcp
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type AltsContext struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// The application protocol negotiated for this connection.
|
||||
ApplicationProtocol string `protobuf:"bytes,1,opt,name=application_protocol,json=applicationProtocol,proto3" json:"application_protocol,omitempty"`
|
||||
// The record protocol negotiated for this connection.
|
||||
RecordProtocol string `protobuf:"bytes,2,opt,name=record_protocol,json=recordProtocol,proto3" json:"record_protocol,omitempty"`
|
||||
// The security level of the created secure channel.
|
||||
SecurityLevel SecurityLevel `protobuf:"varint,3,opt,name=security_level,json=securityLevel,proto3,enum=grpc.gcp.SecurityLevel" json:"security_level,omitempty"`
|
||||
// The peer service account.
|
||||
PeerServiceAccount string `protobuf:"bytes,4,opt,name=peer_service_account,json=peerServiceAccount,proto3" json:"peer_service_account,omitempty"`
|
||||
// The local service account.
|
||||
LocalServiceAccount string `protobuf:"bytes,5,opt,name=local_service_account,json=localServiceAccount,proto3" json:"local_service_account,omitempty"`
|
||||
// The RPC protocol versions supported by the peer.
|
||||
PeerRpcVersions *RpcProtocolVersions `protobuf:"bytes,6,opt,name=peer_rpc_versions,json=peerRpcVersions,proto3" json:"peer_rpc_versions,omitempty"`
|
||||
// Additional attributes of the peer.
|
||||
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"`
|
||||
}
|
||||
|
||||
func (x *AltsContext) Reset() {
|
||||
*x = AltsContext{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_grpc_gcp_altscontext_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *AltsContext) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*AltsContext) ProtoMessage() {}
|
||||
|
||||
func (x *AltsContext) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_grpc_gcp_altscontext_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use AltsContext.ProtoReflect.Descriptor instead.
|
||||
func (*AltsContext) Descriptor() ([]byte, []int) {
|
||||
return file_grpc_gcp_altscontext_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *AltsContext) GetApplicationProtocol() string {
|
||||
if x != nil {
|
||||
return x.ApplicationProtocol
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *AltsContext) GetRecordProtocol() string {
|
||||
if x != nil {
|
||||
return x.RecordProtocol
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *AltsContext) GetSecurityLevel() SecurityLevel {
|
||||
if x != nil {
|
||||
return x.SecurityLevel
|
||||
}
|
||||
return SecurityLevel_SECURITY_NONE
|
||||
}
|
||||
|
||||
func (x *AltsContext) GetPeerServiceAccount() string {
|
||||
if x != nil {
|
||||
return x.PeerServiceAccount
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *AltsContext) GetLocalServiceAccount() string {
|
||||
if x != nil {
|
||||
return x.LocalServiceAccount
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *AltsContext) GetPeerRpcVersions() *RpcProtocolVersions {
|
||||
if x != nil {
|
||||
return x.PeerRpcVersions
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *AltsContext) GetPeerAttributes() map[string]string {
|
||||
if x != nil {
|
||||
return x.PeerAttributes
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_grpc_gcp_altscontext_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_grpc_gcp_altscontext_proto_rawDesc = []byte{
|
||||
0x0a, 0x1a, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x63, 0x70, 0x2f, 0x61, 0x6c, 0x74, 0x73, 0x63,
|
||||
0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x67, 0x72,
|
||||
0x70, 0x63, 0x2e, 0x67, 0x63, 0x70, 0x1a, 0x28, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x63, 0x70,
|
||||
0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x75, 0x72,
|
||||
0x69, 0x74, 0x79, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x22, 0xf1, 0x03, 0x0a, 0x0b, 0x41, 0x6c, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
|
||||
0x12, 0x31, 0x0a, 0x14, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13,
|
||||
0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x63, 0x6f, 0x6c, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x5f, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65,
|
||||
0x63, 0x6f, 0x72, 0x64, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x3e, 0x0a, 0x0e,
|
||||
0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x63, 0x70, 0x2e,
|
||||
0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x0d, 0x73,
|
||||
0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x30, 0x0a, 0x14,
|
||||
0x70, 0x65, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x63, 0x63,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x70, 0x65, 0x65, 0x72,
|
||||
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x32,
|
||||
0x0a, 0x15, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f,
|
||||
0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x6c,
|
||||
0x6f, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x12, 0x49, 0x0a, 0x11, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x72, 0x70, 0x63, 0x5f, 0x76,
|
||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e,
|
||||
0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x63, 0x70, 0x2e, 0x52, 0x70, 0x63, 0x50, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0f, 0x70, 0x65,
|
||||
0x65, 0x72, 0x52, 0x70, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x52, 0x0a,
|
||||
0x0f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73,
|
||||
0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x63,
|
||||
0x70, 0x2e, 0x41, 0x6c, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x50, 0x65,
|
||||
0x65, 0x72, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72,
|
||||
0x79, 0x52, 0x0e, 0x70, 0x65, 0x65, 0x72, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65,
|
||||
0x73, 0x1a, 0x41, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75,
|
||||
0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x3a, 0x02, 0x38, 0x01, 0x42, 0x6c, 0x0a, 0x15, 0x69, 0x6f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e,
|
||||
0x61, 0x6c, 0x74, 0x73, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x42, 0x10, 0x41,
|
||||
0x6c, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50,
|
||||
0x01, 0x5a, 0x3f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67,
|
||||
0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e,
|
||||
0x74, 0x69, 0x61, 0x6c, 0x73, 0x2f, 0x61, 0x6c, 0x74, 0x73, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
||||
0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x67,
|
||||
0x63, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_grpc_gcp_altscontext_proto_rawDescOnce sync.Once
|
||||
file_grpc_gcp_altscontext_proto_rawDescData = file_grpc_gcp_altscontext_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_grpc_gcp_altscontext_proto_rawDescGZIP() []byte {
|
||||
file_grpc_gcp_altscontext_proto_rawDescOnce.Do(func() {
|
||||
file_grpc_gcp_altscontext_proto_rawDescData = protoimpl.X.CompressGZIP(file_grpc_gcp_altscontext_proto_rawDescData)
|
||||
})
|
||||
return file_grpc_gcp_altscontext_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_grpc_gcp_altscontext_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_grpc_gcp_altscontext_proto_goTypes = []interface{}{
|
||||
(*AltsContext)(nil), // 0: grpc.gcp.AltsContext
|
||||
nil, // 1: grpc.gcp.AltsContext.PeerAttributesEntry
|
||||
(SecurityLevel)(0), // 2: grpc.gcp.SecurityLevel
|
||||
(*RpcProtocolVersions)(nil), // 3: grpc.gcp.RpcProtocolVersions
|
||||
}
|
||||
var file_grpc_gcp_altscontext_proto_depIdxs = []int32{
|
||||
2, // 0: grpc.gcp.AltsContext.security_level:type_name -> grpc.gcp.SecurityLevel
|
||||
3, // 1: grpc.gcp.AltsContext.peer_rpc_versions:type_name -> grpc.gcp.RpcProtocolVersions
|
||||
1, // 2: grpc.gcp.AltsContext.peer_attributes:type_name -> grpc.gcp.AltsContext.PeerAttributesEntry
|
||||
3, // [3:3] is the sub-list for method output_type
|
||||
3, // [3:3] is the sub-list for method input_type
|
||||
3, // [3:3] is the sub-list for extension type_name
|
||||
3, // [3:3] is the sub-list for extension extendee
|
||||
0, // [0:3] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_grpc_gcp_altscontext_proto_init() }
|
||||
func file_grpc_gcp_altscontext_proto_init() {
|
||||
if File_grpc_gcp_altscontext_proto != nil {
|
||||
return
|
||||
}
|
||||
file_grpc_gcp_transport_security_common_proto_init()
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_grpc_gcp_altscontext_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*AltsContext); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_grpc_gcp_altscontext_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_grpc_gcp_altscontext_proto_goTypes,
|
||||
DependencyIndexes: file_grpc_gcp_altscontext_proto_depIdxs,
|
||||
MessageInfos: file_grpc_gcp_altscontext_proto_msgTypes,
|
||||
}.Build()
|
||||
File_grpc_gcp_altscontext_proto = out.File
|
||||
file_grpc_gcp_altscontext_proto_rawDesc = nil
|
||||
file_grpc_gcp_altscontext_proto_goTypes = nil
|
||||
file_grpc_gcp_altscontext_proto_depIdxs = nil
|
||||
}
|
||||
1466
vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/handshaker.pb.go
generated
vendored
Normal file
1466
vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/handshaker.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
133
vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/handshaker_grpc.pb.go
generated
vendored
Normal file
133
vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/handshaker_grpc.pb.go
generated
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
// Copyright 2018 The gRPC Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The canonical version of this proto can be found at
|
||||
// https://github.com/grpc/grpc-proto/blob/master/grpc/gcp/handshaker.proto
|
||||
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc v4.25.2
|
||||
// source: grpc/gcp/handshaker.proto
|
||||
|
||||
package grpc_gcp
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
HandshakerService_DoHandshake_FullMethodName = "/grpc.gcp.HandshakerService/DoHandshake"
|
||||
)
|
||||
|
||||
// HandshakerServiceClient is the client API for HandshakerService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type HandshakerServiceClient interface {
|
||||
// Handshaker service accepts a stream of handshaker request, returning a
|
||||
// stream of handshaker response. Client is expected to send exactly one
|
||||
// message with either client_start or server_start followed by one or more
|
||||
// messages with next. Each time client sends a request, the handshaker
|
||||
// service expects to respond. Client does not have to wait for service's
|
||||
// response before sending next request.
|
||||
DoHandshake(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[HandshakerReq, HandshakerResp], error)
|
||||
}
|
||||
|
||||
type handshakerServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewHandshakerServiceClient(cc grpc.ClientConnInterface) HandshakerServiceClient {
|
||||
return &handshakerServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *handshakerServiceClient) DoHandshake(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[HandshakerReq, HandshakerResp], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &HandshakerService_ServiceDesc.Streams[0], HandshakerService_DoHandshake_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[HandshakerReq, HandshakerResp]{ClientStream: stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type HandshakerService_DoHandshakeClient = grpc.BidiStreamingClient[HandshakerReq, HandshakerResp]
|
||||
|
||||
// HandshakerServiceServer is the server API for HandshakerService service.
|
||||
// All implementations must embed UnimplementedHandshakerServiceServer
|
||||
// for forward compatibility
|
||||
type HandshakerServiceServer interface {
|
||||
// Handshaker service accepts a stream of handshaker request, returning a
|
||||
// stream of handshaker response. Client is expected to send exactly one
|
||||
// message with either client_start or server_start followed by one or more
|
||||
// messages with next. Each time client sends a request, the handshaker
|
||||
// service expects to respond. Client does not have to wait for service's
|
||||
// response before sending next request.
|
||||
DoHandshake(grpc.BidiStreamingServer[HandshakerReq, HandshakerResp]) error
|
||||
mustEmbedUnimplementedHandshakerServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedHandshakerServiceServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedHandshakerServiceServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedHandshakerServiceServer) DoHandshake(grpc.BidiStreamingServer[HandshakerReq, HandshakerResp]) error {
|
||||
return status.Errorf(codes.Unimplemented, "method DoHandshake not implemented")
|
||||
}
|
||||
func (UnimplementedHandshakerServiceServer) mustEmbedUnimplementedHandshakerServiceServer() {}
|
||||
|
||||
// UnsafeHandshakerServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to HandshakerServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeHandshakerServiceServer interface {
|
||||
mustEmbedUnimplementedHandshakerServiceServer()
|
||||
}
|
||||
|
||||
func RegisterHandshakerServiceServer(s grpc.ServiceRegistrar, srv HandshakerServiceServer) {
|
||||
s.RegisterService(&HandshakerService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _HandshakerService_DoHandshake_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(HandshakerServiceServer).DoHandshake(&grpc.GenericServerStream[HandshakerReq, HandshakerResp]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type HandshakerService_DoHandshakeServer = grpc.BidiStreamingServer[HandshakerReq, HandshakerResp]
|
||||
|
||||
// HandshakerService_ServiceDesc is the grpc.ServiceDesc for HandshakerService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var HandshakerService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "grpc.gcp.HandshakerService",
|
||||
HandlerType: (*HandshakerServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "DoHandshake",
|
||||
Handler: _HandshakerService_DoHandshake_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "grpc/gcp/handshaker.proto",
|
||||
}
|
||||
321
vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/transport_security_common.pb.go
generated
vendored
Normal file
321
vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/transport_security_common.pb.go
generated
vendored
Normal file
@@ -0,0 +1,321 @@
|
||||
// Copyright 2018 The gRPC Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The canonical version of this proto can be found at
|
||||
// https://github.com/grpc/grpc-proto/blob/master/grpc/gcp/transport_security_common.proto
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.25.2
|
||||
// source: grpc/gcp/transport_security_common.proto
|
||||
|
||||
package grpc_gcp
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// The security level of the created channel. The list is sorted in increasing
|
||||
// level of security. This order must always be maintained.
|
||||
type SecurityLevel int32
|
||||
|
||||
const (
|
||||
SecurityLevel_SECURITY_NONE SecurityLevel = 0
|
||||
SecurityLevel_INTEGRITY_ONLY SecurityLevel = 1
|
||||
SecurityLevel_INTEGRITY_AND_PRIVACY SecurityLevel = 2
|
||||
)
|
||||
|
||||
// Enum value maps for SecurityLevel.
|
||||
var (
|
||||
SecurityLevel_name = map[int32]string{
|
||||
0: "SECURITY_NONE",
|
||||
1: "INTEGRITY_ONLY",
|
||||
2: "INTEGRITY_AND_PRIVACY",
|
||||
}
|
||||
SecurityLevel_value = map[string]int32{
|
||||
"SECURITY_NONE": 0,
|
||||
"INTEGRITY_ONLY": 1,
|
||||
"INTEGRITY_AND_PRIVACY": 2,
|
||||
}
|
||||
)
|
||||
|
||||
func (x SecurityLevel) Enum() *SecurityLevel {
|
||||
p := new(SecurityLevel)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x SecurityLevel) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (SecurityLevel) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_grpc_gcp_transport_security_common_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (SecurityLevel) Type() protoreflect.EnumType {
|
||||
return &file_grpc_gcp_transport_security_common_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x SecurityLevel) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SecurityLevel.Descriptor instead.
|
||||
func (SecurityLevel) EnumDescriptor() ([]byte, []int) {
|
||||
return file_grpc_gcp_transport_security_common_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
// Max and min supported RPC protocol versions.
|
||||
type RpcProtocolVersions struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Maximum supported RPC version.
|
||||
MaxRpcVersion *RpcProtocolVersions_Version `protobuf:"bytes,1,opt,name=max_rpc_version,json=maxRpcVersion,proto3" json:"max_rpc_version,omitempty"`
|
||||
// Minimum supported RPC version.
|
||||
MinRpcVersion *RpcProtocolVersions_Version `protobuf:"bytes,2,opt,name=min_rpc_version,json=minRpcVersion,proto3" json:"min_rpc_version,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RpcProtocolVersions) Reset() {
|
||||
*x = RpcProtocolVersions{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_grpc_gcp_transport_security_common_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *RpcProtocolVersions) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*RpcProtocolVersions) ProtoMessage() {}
|
||||
|
||||
func (x *RpcProtocolVersions) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_grpc_gcp_transport_security_common_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use RpcProtocolVersions.ProtoReflect.Descriptor instead.
|
||||
func (*RpcProtocolVersions) Descriptor() ([]byte, []int) {
|
||||
return file_grpc_gcp_transport_security_common_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *RpcProtocolVersions) GetMaxRpcVersion() *RpcProtocolVersions_Version {
|
||||
if x != nil {
|
||||
return x.MaxRpcVersion
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *RpcProtocolVersions) GetMinRpcVersion() *RpcProtocolVersions_Version {
|
||||
if x != nil {
|
||||
return x.MinRpcVersion
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RPC version contains a major version and a minor version.
|
||||
type RpcProtocolVersions_Version struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Major uint32 `protobuf:"varint,1,opt,name=major,proto3" json:"major,omitempty"`
|
||||
Minor uint32 `protobuf:"varint,2,opt,name=minor,proto3" json:"minor,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RpcProtocolVersions_Version) Reset() {
|
||||
*x = RpcProtocolVersions_Version{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_grpc_gcp_transport_security_common_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *RpcProtocolVersions_Version) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*RpcProtocolVersions_Version) ProtoMessage() {}
|
||||
|
||||
func (x *RpcProtocolVersions_Version) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_grpc_gcp_transport_security_common_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use RpcProtocolVersions_Version.ProtoReflect.Descriptor instead.
|
||||
func (*RpcProtocolVersions_Version) Descriptor() ([]byte, []int) {
|
||||
return file_grpc_gcp_transport_security_common_proto_rawDescGZIP(), []int{0, 0}
|
||||
}
|
||||
|
||||
func (x *RpcProtocolVersions_Version) GetMajor() uint32 {
|
||||
if x != nil {
|
||||
return x.Major
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *RpcProtocolVersions_Version) GetMinor() uint32 {
|
||||
if x != nil {
|
||||
return x.Minor
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var File_grpc_gcp_transport_security_common_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_grpc_gcp_transport_security_common_proto_rawDesc = []byte{
|
||||
0x0a, 0x28, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x63, 0x70, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73,
|
||||
0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x63, 0x6f,
|
||||
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x67, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x67, 0x63, 0x70, 0x22, 0xea, 0x01, 0x0a, 0x13, 0x52, 0x70, 0x63, 0x50, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4d, 0x0a, 0x0f,
|
||||
0x6d, 0x61, 0x78, 0x5f, 0x72, 0x70, 0x63, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x63, 0x70,
|
||||
0x2e, 0x52, 0x70, 0x63, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x6d, 0x61,
|
||||
0x78, 0x52, 0x70, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4d, 0x0a, 0x0f, 0x6d,
|
||||
0x69, 0x6e, 0x5f, 0x72, 0x70, 0x63, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x63, 0x70, 0x2e,
|
||||
0x52, 0x70, 0x63, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x73, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x6d, 0x69, 0x6e,
|
||||
0x52, 0x70, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x35, 0x0a, 0x07, 0x56, 0x65,
|
||||
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6d,
|
||||
0x69, 0x6e, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6d, 0x69, 0x6e, 0x6f,
|
||||
0x72, 0x2a, 0x51, 0x0a, 0x0d, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x4c, 0x65, 0x76,
|
||||
0x65, 0x6c, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x45, 0x43, 0x55, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x4e,
|
||||
0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x49,
|
||||
0x54, 0x59, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x49, 0x4e, 0x54,
|
||||
0x45, 0x47, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x50, 0x52, 0x49, 0x56, 0x41,
|
||||
0x43, 0x59, 0x10, 0x02, 0x42, 0x78, 0x0a, 0x15, 0x69, 0x6f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e,
|
||||
0x61, 0x6c, 0x74, 0x73, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x42, 0x1c, 0x54,
|
||||
0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
|
||||
0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3f, 0x67,
|
||||
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67,
|
||||
0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
|
||||
0x73, 0x2f, 0x61, 0x6c, 0x74, 0x73, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x67, 0x63, 0x70, 0x62, 0x06,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_grpc_gcp_transport_security_common_proto_rawDescOnce sync.Once
|
||||
file_grpc_gcp_transport_security_common_proto_rawDescData = file_grpc_gcp_transport_security_common_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_grpc_gcp_transport_security_common_proto_rawDescGZIP() []byte {
|
||||
file_grpc_gcp_transport_security_common_proto_rawDescOnce.Do(func() {
|
||||
file_grpc_gcp_transport_security_common_proto_rawDescData = protoimpl.X.CompressGZIP(file_grpc_gcp_transport_security_common_proto_rawDescData)
|
||||
})
|
||||
return file_grpc_gcp_transport_security_common_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_grpc_gcp_transport_security_common_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_grpc_gcp_transport_security_common_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_grpc_gcp_transport_security_common_proto_goTypes = []interface{}{
|
||||
(SecurityLevel)(0), // 0: grpc.gcp.SecurityLevel
|
||||
(*RpcProtocolVersions)(nil), // 1: grpc.gcp.RpcProtocolVersions
|
||||
(*RpcProtocolVersions_Version)(nil), // 2: grpc.gcp.RpcProtocolVersions.Version
|
||||
}
|
||||
var file_grpc_gcp_transport_security_common_proto_depIdxs = []int32{
|
||||
2, // 0: grpc.gcp.RpcProtocolVersions.max_rpc_version:type_name -> grpc.gcp.RpcProtocolVersions.Version
|
||||
2, // 1: grpc.gcp.RpcProtocolVersions.min_rpc_version:type_name -> grpc.gcp.RpcProtocolVersions.Version
|
||||
2, // [2:2] is the sub-list for method output_type
|
||||
2, // [2:2] is the sub-list for method input_type
|
||||
2, // [2:2] is the sub-list for extension type_name
|
||||
2, // [2:2] is the sub-list for extension extendee
|
||||
0, // [0:2] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_grpc_gcp_transport_security_common_proto_init() }
|
||||
func file_grpc_gcp_transport_security_common_proto_init() {
|
||||
if File_grpc_gcp_transport_security_common_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_grpc_gcp_transport_security_common_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*RpcProtocolVersions); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_grpc_gcp_transport_security_common_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*RpcProtocolVersions_Version); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_grpc_gcp_transport_security_common_proto_rawDesc,
|
||||
NumEnums: 1,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_grpc_gcp_transport_security_common_proto_goTypes,
|
||||
DependencyIndexes: file_grpc_gcp_transport_security_common_proto_depIdxs,
|
||||
EnumInfos: file_grpc_gcp_transport_security_common_proto_enumTypes,
|
||||
MessageInfos: file_grpc_gcp_transport_security_common_proto_msgTypes,
|
||||
}.Build()
|
||||
File_grpc_gcp_transport_security_common_proto = out.File
|
||||
file_grpc_gcp_transport_security_common_proto_rawDesc = nil
|
||||
file_grpc_gcp_transport_security_common_proto_goTypes = nil
|
||||
file_grpc_gcp_transport_security_common_proto_depIdxs = nil
|
||||
}
|
||||
70
vendor/google.golang.org/grpc/credentials/alts/utils.go
generated
vendored
Normal file
70
vendor/google.golang.org/grpc/credentials/alts/utils.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package alts
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/peer"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// AuthInfoFromContext extracts the alts.AuthInfo object from the given context,
|
||||
// if it exists. This API should be used by gRPC server RPC handlers to get
|
||||
// information about the communicating peer. For client-side, use grpc.Peer()
|
||||
// CallOption.
|
||||
func AuthInfoFromContext(ctx context.Context) (AuthInfo, error) {
|
||||
p, ok := peer.FromContext(ctx)
|
||||
if !ok {
|
||||
return nil, errors.New("no Peer found in Context")
|
||||
}
|
||||
return AuthInfoFromPeer(p)
|
||||
}
|
||||
|
||||
// AuthInfoFromPeer extracts the alts.AuthInfo object from the given peer, if it
|
||||
// exists. This API should be used by gRPC clients after obtaining a peer object
|
||||
// using the grpc.Peer() CallOption.
|
||||
func AuthInfoFromPeer(p *peer.Peer) (AuthInfo, error) {
|
||||
altsAuthInfo, ok := p.AuthInfo.(AuthInfo)
|
||||
if !ok {
|
||||
return nil, errors.New("no alts.AuthInfo found in Peer")
|
||||
}
|
||||
return altsAuthInfo, nil
|
||||
}
|
||||
|
||||
// ClientAuthorizationCheck checks whether the client is authorized to access
|
||||
// the requested resources based on the given expected client service accounts.
|
||||
// This API should be used by gRPC server RPC handlers. This API should not be
|
||||
// used by clients.
|
||||
func ClientAuthorizationCheck(ctx context.Context, expectedServiceAccounts []string) error {
|
||||
authInfo, err := AuthInfoFromContext(ctx)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.PermissionDenied, "The context is not an ALTS-compatible context: %v", err)
|
||||
}
|
||||
peer := authInfo.PeerServiceAccount()
|
||||
for _, sa := range expectedServiceAccounts {
|
||||
if strings.EqualFold(peer, sa) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return status.Errorf(codes.PermissionDenied, "Client %v is not authorized", peer)
|
||||
}
|
||||
291
vendor/google.golang.org/grpc/credentials/credentials.go
generated
vendored
Normal file
291
vendor/google.golang.org/grpc/credentials/credentials.go
generated
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2014 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package credentials implements various credentials supported by gRPC library,
|
||||
// which encapsulate all the state needed by a client to authenticate with a
|
||||
// server and make various assertions, e.g., about the client's identity, role,
|
||||
// or whether it is authorized to make a particular call.
|
||||
package credentials // import "google.golang.org/grpc/credentials"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"google.golang.org/grpc/attributes"
|
||||
icredentials "google.golang.org/grpc/internal/credentials"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// PerRPCCredentials defines the common interface for the credentials which need to
|
||||
// attach security information to every RPC (e.g., oauth2).
|
||||
type PerRPCCredentials interface {
|
||||
// GetRequestMetadata gets the current request metadata, refreshing tokens
|
||||
// if required. This should be called by the transport layer on each
|
||||
// request, and the data should be populated in headers or other
|
||||
// context. If a status code is returned, it will be used as the status for
|
||||
// the RPC (restricted to an allowable set of codes as defined by gRFC
|
||||
// A54). uri is the URI of the entry point for the request. When supported
|
||||
// by the underlying implementation, ctx can be used for timeout and
|
||||
// cancellation. Additionally, RequestInfo data will be available via ctx
|
||||
// to this call. TODO(zhaoq): Define the set of the qualified keys instead
|
||||
// of leaving it as an arbitrary string.
|
||||
GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error)
|
||||
// RequireTransportSecurity indicates whether the credentials requires
|
||||
// transport security.
|
||||
RequireTransportSecurity() bool
|
||||
}
|
||||
|
||||
// SecurityLevel defines the protection level on an established connection.
|
||||
//
|
||||
// This API is experimental.
|
||||
type SecurityLevel int
|
||||
|
||||
const (
|
||||
// InvalidSecurityLevel indicates an invalid security level.
|
||||
// The zero SecurityLevel value is invalid for backward compatibility.
|
||||
InvalidSecurityLevel SecurityLevel = iota
|
||||
// NoSecurity indicates a connection is insecure.
|
||||
NoSecurity
|
||||
// IntegrityOnly indicates a connection only provides integrity protection.
|
||||
IntegrityOnly
|
||||
// PrivacyAndIntegrity indicates a connection provides both privacy and integrity protection.
|
||||
PrivacyAndIntegrity
|
||||
)
|
||||
|
||||
// String returns SecurityLevel in a string format.
|
||||
func (s SecurityLevel) String() string {
|
||||
switch s {
|
||||
case NoSecurity:
|
||||
return "NoSecurity"
|
||||
case IntegrityOnly:
|
||||
return "IntegrityOnly"
|
||||
case PrivacyAndIntegrity:
|
||||
return "PrivacyAndIntegrity"
|
||||
}
|
||||
return fmt.Sprintf("invalid SecurityLevel: %v", int(s))
|
||||
}
|
||||
|
||||
// CommonAuthInfo contains authenticated information common to AuthInfo implementations.
|
||||
// It should be embedded in a struct implementing AuthInfo to provide additional information
|
||||
// about the credentials.
|
||||
//
|
||||
// This API is experimental.
|
||||
type CommonAuthInfo struct {
|
||||
SecurityLevel SecurityLevel
|
||||
}
|
||||
|
||||
// GetCommonAuthInfo returns the pointer to CommonAuthInfo struct.
|
||||
func (c CommonAuthInfo) GetCommonAuthInfo() CommonAuthInfo {
|
||||
return c
|
||||
}
|
||||
|
||||
// ProtocolInfo provides information regarding the gRPC wire protocol version,
|
||||
// security protocol, security protocol version in use, server name, etc.
|
||||
type ProtocolInfo struct {
|
||||
// ProtocolVersion is the gRPC wire protocol version.
|
||||
ProtocolVersion string
|
||||
// SecurityProtocol is the security protocol in use.
|
||||
SecurityProtocol string
|
||||
// SecurityVersion is the security protocol version. It is a static version string from the
|
||||
// credentials, not a value that reflects per-connection protocol negotiation. To retrieve
|
||||
// details about the credentials used for a connection, use the Peer's AuthInfo field instead.
|
||||
//
|
||||
// Deprecated: please use Peer.AuthInfo.
|
||||
SecurityVersion string
|
||||
// ServerName is the user-configured server name.
|
||||
ServerName string
|
||||
}
|
||||
|
||||
// AuthInfo defines the common interface for the auth information the users are interested in.
|
||||
// A struct that implements AuthInfo should embed CommonAuthInfo by including additional
|
||||
// information about the credentials in it.
|
||||
type AuthInfo interface {
|
||||
AuthType() string
|
||||
}
|
||||
|
||||
// ErrConnDispatched indicates that rawConn has been dispatched out of gRPC
|
||||
// and the caller should not close rawConn.
|
||||
var ErrConnDispatched = errors.New("credentials: rawConn is dispatched out of gRPC")
|
||||
|
||||
// TransportCredentials defines the common interface for all the live gRPC wire
|
||||
// protocols and supported transport security protocols (e.g., TLS, SSL).
|
||||
type TransportCredentials interface {
|
||||
// ClientHandshake does the authentication handshake specified by the
|
||||
// corresponding authentication protocol on rawConn for clients. It returns
|
||||
// the authenticated connection and the corresponding auth information
|
||||
// about the connection. The auth information should embed CommonAuthInfo
|
||||
// to return additional information about the credentials. Implementations
|
||||
// must use the provided context to implement timely cancellation. gRPC
|
||||
// will try to reconnect if the error returned is a temporary error
|
||||
// (io.EOF, context.DeadlineExceeded or err.Temporary() == true). If the
|
||||
// returned error is a wrapper error, implementations should make sure that
|
||||
// the error implements Temporary() to have the correct retry behaviors.
|
||||
// Additionally, ClientHandshakeInfo data will be available via the context
|
||||
// passed to this call.
|
||||
//
|
||||
// The second argument to this method is the `:authority` header value used
|
||||
// while creating new streams on this connection after authentication
|
||||
// succeeds. Implementations must use this as the server name during the
|
||||
// authentication handshake.
|
||||
//
|
||||
// If the returned net.Conn is closed, it MUST close the net.Conn provided.
|
||||
ClientHandshake(context.Context, string, net.Conn) (net.Conn, AuthInfo, error)
|
||||
// ServerHandshake does the authentication handshake for servers. It returns
|
||||
// the authenticated connection and the corresponding auth information about
|
||||
// the connection. The auth information should embed CommonAuthInfo to return additional information
|
||||
// about the credentials.
|
||||
//
|
||||
// If the returned net.Conn is closed, it MUST close the net.Conn provided.
|
||||
ServerHandshake(net.Conn) (net.Conn, AuthInfo, error)
|
||||
// Info provides the ProtocolInfo of this TransportCredentials.
|
||||
Info() ProtocolInfo
|
||||
// Clone makes a copy of this TransportCredentials.
|
||||
Clone() TransportCredentials
|
||||
// OverrideServerName specifies the value used for the following:
|
||||
// - verifying the hostname on the returned certificates
|
||||
// - as SNI in the client's handshake to support virtual hosting
|
||||
// - as the value for `:authority` header at stream creation time
|
||||
//
|
||||
// Deprecated: use grpc.WithAuthority instead. Will be supported
|
||||
// throughout 1.x.
|
||||
OverrideServerName(string) error
|
||||
}
|
||||
|
||||
// Bundle is a combination of TransportCredentials and PerRPCCredentials.
|
||||
//
|
||||
// It also contains a mode switching method, so it can be used as a combination
|
||||
// of different credential policies.
|
||||
//
|
||||
// Bundle cannot be used together with individual TransportCredentials.
|
||||
// PerRPCCredentials from Bundle will be appended to other PerRPCCredentials.
|
||||
//
|
||||
// This API is experimental.
|
||||
type Bundle interface {
|
||||
// TransportCredentials returns the transport credentials from the Bundle.
|
||||
//
|
||||
// Implementations must return non-nil transport credentials. If transport
|
||||
// security is not needed by the Bundle, implementations may choose to
|
||||
// return insecure.NewCredentials().
|
||||
TransportCredentials() TransportCredentials
|
||||
|
||||
// PerRPCCredentials returns the per-RPC credentials from the Bundle.
|
||||
//
|
||||
// May be nil if per-RPC credentials are not needed.
|
||||
PerRPCCredentials() PerRPCCredentials
|
||||
|
||||
// NewWithMode should make a copy of Bundle, and switch mode. Modifying the
|
||||
// existing Bundle may cause races.
|
||||
//
|
||||
// NewWithMode returns nil if the requested mode is not supported.
|
||||
NewWithMode(mode string) (Bundle, error)
|
||||
}
|
||||
|
||||
// RequestInfo contains request data attached to the context passed to GetRequestMetadata calls.
|
||||
//
|
||||
// This API is experimental.
|
||||
type RequestInfo struct {
|
||||
// The method passed to Invoke or NewStream for this RPC. (For proto methods, this has the format "/some.Service/Method")
|
||||
Method string
|
||||
// AuthInfo contains the information from a security handshake (TransportCredentials.ClientHandshake, TransportCredentials.ServerHandshake)
|
||||
AuthInfo AuthInfo
|
||||
}
|
||||
|
||||
// RequestInfoFromContext extracts the RequestInfo from the context if it exists.
|
||||
//
|
||||
// This API is experimental.
|
||||
func RequestInfoFromContext(ctx context.Context) (ri RequestInfo, ok bool) {
|
||||
ri, ok = icredentials.RequestInfoFromContext(ctx).(RequestInfo)
|
||||
return ri, ok
|
||||
}
|
||||
|
||||
// ClientHandshakeInfo holds data to be passed to ClientHandshake. This makes
|
||||
// it possible to pass arbitrary data to the handshaker from gRPC, resolver,
|
||||
// balancer etc. Individual credential implementations control the actual
|
||||
// format of the data that they are willing to receive.
|
||||
//
|
||||
// This API is experimental.
|
||||
type ClientHandshakeInfo struct {
|
||||
// Attributes contains the attributes for the address. It could be provided
|
||||
// by the gRPC, resolver, balancer etc.
|
||||
Attributes *attributes.Attributes
|
||||
}
|
||||
|
||||
// ClientHandshakeInfoFromContext returns the ClientHandshakeInfo struct stored
|
||||
// in ctx.
|
||||
//
|
||||
// This API is experimental.
|
||||
func ClientHandshakeInfoFromContext(ctx context.Context) ClientHandshakeInfo {
|
||||
chi, _ := icredentials.ClientHandshakeInfoFromContext(ctx).(ClientHandshakeInfo)
|
||||
return chi
|
||||
}
|
||||
|
||||
// CheckSecurityLevel checks if a connection's security level is greater than or equal to the specified one.
|
||||
// It returns success if 1) the condition is satisfied or 2) AuthInfo struct does not implement GetCommonAuthInfo() method
|
||||
// or 3) CommonAuthInfo.SecurityLevel has an invalid zero value. For 2) and 3), it is for the purpose of backward-compatibility.
|
||||
//
|
||||
// This API is experimental.
|
||||
func CheckSecurityLevel(ai AuthInfo, level SecurityLevel) error {
|
||||
type internalInfo interface {
|
||||
GetCommonAuthInfo() CommonAuthInfo
|
||||
}
|
||||
if ai == nil {
|
||||
return errors.New("AuthInfo is nil")
|
||||
}
|
||||
if ci, ok := ai.(internalInfo); ok {
|
||||
// CommonAuthInfo.SecurityLevel has an invalid value.
|
||||
if ci.GetCommonAuthInfo().SecurityLevel == InvalidSecurityLevel {
|
||||
return nil
|
||||
}
|
||||
if ci.GetCommonAuthInfo().SecurityLevel < level {
|
||||
return fmt.Errorf("requires SecurityLevel %v; connection has %v", level, ci.GetCommonAuthInfo().SecurityLevel)
|
||||
}
|
||||
}
|
||||
// The condition is satisfied or AuthInfo struct does not implement GetCommonAuthInfo() method.
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChannelzSecurityInfo defines the interface that security protocols should implement
|
||||
// in order to provide security info to channelz.
|
||||
//
|
||||
// This API is experimental.
|
||||
type ChannelzSecurityInfo interface {
|
||||
GetSecurityValue() ChannelzSecurityValue
|
||||
}
|
||||
|
||||
// ChannelzSecurityValue defines the interface that GetSecurityValue() return value
|
||||
// should satisfy. This interface should only be satisfied by *TLSChannelzSecurityValue
|
||||
// and *OtherChannelzSecurityValue.
|
||||
//
|
||||
// This API is experimental.
|
||||
type ChannelzSecurityValue interface {
|
||||
isChannelzSecurityValue()
|
||||
}
|
||||
|
||||
// OtherChannelzSecurityValue defines the struct that non-TLS protocol should return
|
||||
// from GetSecurityValue(), which contains protocol specific security info. Note
|
||||
// the Value field will be sent to users of channelz requesting channel info, and
|
||||
// thus sensitive info should better be avoided.
|
||||
//
|
||||
// This API is experimental.
|
||||
type OtherChannelzSecurityValue struct {
|
||||
ChannelzSecurityValue
|
||||
Name string
|
||||
Value proto.Message
|
||||
}
|
||||
145
vendor/google.golang.org/grpc/credentials/google/google.go
generated
vendored
Normal file
145
vendor/google.golang.org/grpc/credentials/google/google.go
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package google defines credentials for google cloud services.
|
||||
package google
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/alts"
|
||||
"google.golang.org/grpc/credentials/oauth"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/internal"
|
||||
)
|
||||
|
||||
const tokenRequestTimeout = 30 * time.Second
|
||||
|
||||
var logger = grpclog.Component("credentials")
|
||||
|
||||
// DefaultCredentialsOptions constructs options to build DefaultCredentials.
|
||||
type DefaultCredentialsOptions struct {
|
||||
// PerRPCCreds is a per RPC credentials that is passed to a bundle.
|
||||
PerRPCCreds credentials.PerRPCCredentials
|
||||
}
|
||||
|
||||
// NewDefaultCredentialsWithOptions returns a credentials bundle that is
|
||||
// configured to work with google services.
|
||||
//
|
||||
// This API is experimental.
|
||||
func NewDefaultCredentialsWithOptions(opts DefaultCredentialsOptions) credentials.Bundle {
|
||||
if opts.PerRPCCreds == nil {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), tokenRequestTimeout)
|
||||
defer cancel()
|
||||
var err error
|
||||
opts.PerRPCCreds, err = newADC(ctx)
|
||||
if err != nil {
|
||||
logger.Warningf("NewDefaultCredentialsWithOptions: failed to create application oauth: %v", err)
|
||||
}
|
||||
}
|
||||
c := &creds{opts: opts}
|
||||
bundle, err := c.NewWithMode(internal.CredsBundleModeFallback)
|
||||
if err != nil {
|
||||
logger.Warningf("NewDefaultCredentialsWithOptions: failed to create new creds: %v", err)
|
||||
}
|
||||
return bundle
|
||||
}
|
||||
|
||||
// NewDefaultCredentials returns a credentials bundle that is configured to work
|
||||
// with google services.
|
||||
//
|
||||
// This API is experimental.
|
||||
func NewDefaultCredentials() credentials.Bundle {
|
||||
return NewDefaultCredentialsWithOptions(DefaultCredentialsOptions{})
|
||||
}
|
||||
|
||||
// NewComputeEngineCredentials returns a credentials bundle that is configured to work
|
||||
// with google services. This API must only be used when running on GCE. Authentication configured
|
||||
// by this API represents the GCE VM's default service account.
|
||||
//
|
||||
// This API is experimental.
|
||||
func NewComputeEngineCredentials() credentials.Bundle {
|
||||
return NewDefaultCredentialsWithOptions(DefaultCredentialsOptions{
|
||||
PerRPCCreds: oauth.NewComputeEngine(),
|
||||
})
|
||||
}
|
||||
|
||||
// creds implements credentials.Bundle.
|
||||
type creds struct {
|
||||
opts DefaultCredentialsOptions
|
||||
|
||||
// Supported modes are defined in internal/internal.go.
|
||||
mode string
|
||||
// The active transport credentials associated with this bundle.
|
||||
transportCreds credentials.TransportCredentials
|
||||
// The active per RPC credentials associated with this bundle.
|
||||
perRPCCreds credentials.PerRPCCredentials
|
||||
}
|
||||
|
||||
func (c *creds) TransportCredentials() credentials.TransportCredentials {
|
||||
return c.transportCreds
|
||||
}
|
||||
|
||||
func (c *creds) PerRPCCredentials() credentials.PerRPCCredentials {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.perRPCCreds
|
||||
}
|
||||
|
||||
var (
|
||||
newTLS = func() credentials.TransportCredentials {
|
||||
return credentials.NewTLS(nil)
|
||||
}
|
||||
newALTS = func() credentials.TransportCredentials {
|
||||
return alts.NewClientCreds(alts.DefaultClientOptions())
|
||||
}
|
||||
newADC = func(ctx context.Context) (credentials.PerRPCCredentials, error) {
|
||||
return oauth.NewApplicationDefault(ctx)
|
||||
}
|
||||
)
|
||||
|
||||
// NewWithMode should make a copy of Bundle, and switch mode. Modifying the
|
||||
// existing Bundle may cause races.
|
||||
func (c *creds) NewWithMode(mode string) (credentials.Bundle, error) {
|
||||
newCreds := &creds{
|
||||
opts: c.opts,
|
||||
mode: mode,
|
||||
}
|
||||
|
||||
// Create transport credentials.
|
||||
switch mode {
|
||||
case internal.CredsBundleModeFallback:
|
||||
newCreds.transportCreds = newClusterTransportCreds(newTLS(), newALTS())
|
||||
case internal.CredsBundleModeBackendFromBalancer, internal.CredsBundleModeBalancer:
|
||||
// Only the clients can use google default credentials, so we only need
|
||||
// to create new ALTS client creds here.
|
||||
newCreds.transportCreds = newALTS()
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported mode: %v", mode)
|
||||
}
|
||||
|
||||
if mode == internal.CredsBundleModeFallback || mode == internal.CredsBundleModeBackendFromBalancer {
|
||||
newCreds.perRPCCreds = newCreds.opts.PerRPCCreds
|
||||
}
|
||||
|
||||
return newCreds, nil
|
||||
}
|
||||
128
vendor/google.golang.org/grpc/credentials/google/xds.go
generated
vendored
Normal file
128
vendor/google.golang.org/grpc/credentials/google/xds.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2021 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package google
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/internal/xds"
|
||||
)
|
||||
|
||||
const cfeClusterNamePrefix = "google_cfe_"
|
||||
const cfeClusterResourceNamePrefix = "/envoy.config.cluster.v3.Cluster/google_cfe_"
|
||||
const cfeClusterAuthorityName = "traffic-director-c2p.xds.googleapis.com"
|
||||
|
||||
// clusterTransportCreds is a combo of TLS + ALTS.
|
||||
//
|
||||
// On the client, ClientHandshake picks TLS or ALTS based on address attributes.
|
||||
// - if attributes has cluster name
|
||||
// - if cluster name has prefix "google_cfe_", or
|
||||
// "xdstp://traffic-director-c2p.xds.googleapis.com/envoy.config.cluster.v3.Cluster/google_cfe_",
|
||||
// use TLS
|
||||
// - otherwise, use ALTS
|
||||
//
|
||||
// - else, do TLS
|
||||
//
|
||||
// On the server, ServerHandshake always does TLS.
|
||||
type clusterTransportCreds struct {
|
||||
tls credentials.TransportCredentials
|
||||
alts credentials.TransportCredentials
|
||||
}
|
||||
|
||||
func newClusterTransportCreds(tls, alts credentials.TransportCredentials) *clusterTransportCreds {
|
||||
return &clusterTransportCreds{
|
||||
tls: tls,
|
||||
alts: alts,
|
||||
}
|
||||
}
|
||||
|
||||
// clusterName returns the xDS cluster name stored in the attributes in the
|
||||
// context.
|
||||
func clusterName(ctx context.Context) string {
|
||||
chi := credentials.ClientHandshakeInfoFromContext(ctx)
|
||||
if chi.Attributes == nil {
|
||||
return ""
|
||||
}
|
||||
cluster, _ := xds.GetXDSHandshakeClusterName(chi.Attributes)
|
||||
return cluster
|
||||
}
|
||||
|
||||
// isDirectPathCluster returns true if the cluster in the context is a
|
||||
// directpath cluster, meaning ALTS should be used.
|
||||
func isDirectPathCluster(ctx context.Context) bool {
|
||||
cluster := clusterName(ctx)
|
||||
if cluster == "" {
|
||||
// No cluster; not xDS; use TLS.
|
||||
return false
|
||||
}
|
||||
if strings.HasPrefix(cluster, cfeClusterNamePrefix) {
|
||||
// xDS cluster prefixed by "google_cfe_"; use TLS.
|
||||
return false
|
||||
}
|
||||
if !strings.HasPrefix(cluster, "xdstp:") {
|
||||
// Other xDS cluster name; use ALTS.
|
||||
return true
|
||||
}
|
||||
u, err := url.Parse(cluster)
|
||||
if err != nil {
|
||||
// Shouldn't happen, but assume ALTS.
|
||||
return true
|
||||
}
|
||||
// If authority AND path match our CFE checks, use TLS; otherwise use ALTS.
|
||||
return u.Host != cfeClusterAuthorityName || !strings.HasPrefix(u.Path, cfeClusterResourceNamePrefix)
|
||||
}
|
||||
|
||||
func (c *clusterTransportCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
|
||||
if isDirectPathCluster(ctx) {
|
||||
// If attributes have cluster name, and cluster name is not cfe, it's a
|
||||
// backend address, use ALTS.
|
||||
return c.alts.ClientHandshake(ctx, authority, rawConn)
|
||||
}
|
||||
return c.tls.ClientHandshake(ctx, authority, rawConn)
|
||||
}
|
||||
|
||||
func (c *clusterTransportCreds) ServerHandshake(conn net.Conn) (net.Conn, credentials.AuthInfo, error) {
|
||||
return c.tls.ServerHandshake(conn)
|
||||
}
|
||||
|
||||
func (c *clusterTransportCreds) Info() credentials.ProtocolInfo {
|
||||
// TODO: this always returns tls.Info now, because we don't have a cluster
|
||||
// name to check when this method is called. This method doesn't affect
|
||||
// anything important now. We may want to revisit this if it becomes more
|
||||
// important later.
|
||||
return c.tls.Info()
|
||||
}
|
||||
|
||||
func (c *clusterTransportCreds) Clone() credentials.TransportCredentials {
|
||||
return &clusterTransportCreds{
|
||||
tls: c.tls.Clone(),
|
||||
alts: c.alts.Clone(),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *clusterTransportCreds) OverrideServerName(s string) error {
|
||||
if err := c.tls.OverrideServerName(s); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.alts.OverrideServerName(s)
|
||||
}
|
||||
98
vendor/google.golang.org/grpc/credentials/insecure/insecure.go
generated
vendored
Normal file
98
vendor/google.golang.org/grpc/credentials/insecure/insecure.go
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package insecure provides an implementation of the
|
||||
// credentials.TransportCredentials interface which disables transport security.
|
||||
package insecure
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"google.golang.org/grpc/credentials"
|
||||
)
|
||||
|
||||
// NewCredentials returns a credentials which disables transport security.
|
||||
//
|
||||
// Note that using this credentials with per-RPC credentials which require
|
||||
// transport security is incompatible and will cause grpc.Dial() to fail.
|
||||
func NewCredentials() credentials.TransportCredentials {
|
||||
return insecureTC{}
|
||||
}
|
||||
|
||||
// insecureTC implements the insecure transport credentials. The handshake
|
||||
// methods simply return the passed in net.Conn and set the security level to
|
||||
// NoSecurity.
|
||||
type insecureTC struct{}
|
||||
|
||||
func (insecureTC) ClientHandshake(ctx context.Context, _ string, conn net.Conn) (net.Conn, credentials.AuthInfo, error) {
|
||||
return conn, info{credentials.CommonAuthInfo{SecurityLevel: credentials.NoSecurity}}, nil
|
||||
}
|
||||
|
||||
func (insecureTC) ServerHandshake(conn net.Conn) (net.Conn, credentials.AuthInfo, error) {
|
||||
return conn, info{credentials.CommonAuthInfo{SecurityLevel: credentials.NoSecurity}}, nil
|
||||
}
|
||||
|
||||
func (insecureTC) Info() credentials.ProtocolInfo {
|
||||
return credentials.ProtocolInfo{SecurityProtocol: "insecure"}
|
||||
}
|
||||
|
||||
func (insecureTC) Clone() credentials.TransportCredentials {
|
||||
return insecureTC{}
|
||||
}
|
||||
|
||||
func (insecureTC) OverrideServerName(string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// info contains the auth information for an insecure connection.
|
||||
// It implements the AuthInfo interface.
|
||||
type info struct {
|
||||
credentials.CommonAuthInfo
|
||||
}
|
||||
|
||||
// AuthType returns the type of info as a string.
|
||||
func (info) AuthType() string {
|
||||
return "insecure"
|
||||
}
|
||||
|
||||
// insecureBundle implements an insecure bundle.
|
||||
// An insecure bundle provides a thin wrapper around insecureTC to support
|
||||
// the credentials.Bundle interface.
|
||||
type insecureBundle struct{}
|
||||
|
||||
// NewBundle returns a bundle with disabled transport security and no per rpc credential.
|
||||
func NewBundle() credentials.Bundle {
|
||||
return insecureBundle{}
|
||||
}
|
||||
|
||||
// NewWithMode returns a new insecure Bundle. The mode is ignored.
|
||||
func (insecureBundle) NewWithMode(string) (credentials.Bundle, error) {
|
||||
return insecureBundle{}, nil
|
||||
}
|
||||
|
||||
// PerRPCCredentials returns an nil implementation as insecure
|
||||
// bundle does not support a per rpc credential.
|
||||
func (insecureBundle) PerRPCCredentials() credentials.PerRPCCredentials {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TransportCredentials returns the underlying insecure transport credential.
|
||||
func (insecureBundle) TransportCredentials() credentials.TransportCredentials {
|
||||
return NewCredentials()
|
||||
}
|
||||
244
vendor/google.golang.org/grpc/credentials/oauth/oauth.go
generated
vendored
Normal file
244
vendor/google.golang.org/grpc/credentials/oauth/oauth.go
generated
vendored
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2015 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package oauth implements gRPC credentials using OAuth.
|
||||
package oauth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
"golang.org/x/oauth2/jwt"
|
||||
"google.golang.org/grpc/credentials"
|
||||
)
|
||||
|
||||
// TokenSource supplies PerRPCCredentials from an oauth2.TokenSource.
|
||||
type TokenSource struct {
|
||||
oauth2.TokenSource
|
||||
}
|
||||
|
||||
// GetRequestMetadata gets the request metadata as a map from a TokenSource.
|
||||
func (ts TokenSource) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
|
||||
token, err := ts.Token()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ri, _ := credentials.RequestInfoFromContext(ctx)
|
||||
if err = credentials.CheckSecurityLevel(ri.AuthInfo, credentials.PrivacyAndIntegrity); err != nil {
|
||||
return nil, fmt.Errorf("unable to transfer TokenSource PerRPCCredentials: %v", err)
|
||||
}
|
||||
return map[string]string{
|
||||
"authorization": token.Type() + " " + token.AccessToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RequireTransportSecurity indicates whether the credentials requires transport security.
|
||||
func (ts TokenSource) RequireTransportSecurity() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// removeServiceNameFromJWTURI removes RPC service name from URI.
|
||||
func removeServiceNameFromJWTURI(uri string) (string, error) {
|
||||
parsed, err := url.Parse(uri)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
parsed.Path = "/"
|
||||
return parsed.String(), nil
|
||||
}
|
||||
|
||||
type jwtAccess struct {
|
||||
jsonKey []byte
|
||||
}
|
||||
|
||||
// NewJWTAccessFromFile creates PerRPCCredentials from the given keyFile.
|
||||
func NewJWTAccessFromFile(keyFile string) (credentials.PerRPCCredentials, error) {
|
||||
jsonKey, err := os.ReadFile(keyFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("credentials: failed to read the service account key file: %v", err)
|
||||
}
|
||||
return NewJWTAccessFromKey(jsonKey)
|
||||
}
|
||||
|
||||
// NewJWTAccessFromKey creates PerRPCCredentials from the given jsonKey.
|
||||
func NewJWTAccessFromKey(jsonKey []byte) (credentials.PerRPCCredentials, error) {
|
||||
return jwtAccess{jsonKey}, nil
|
||||
}
|
||||
|
||||
func (j jwtAccess) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
|
||||
// Remove RPC service name from URI that will be used as audience
|
||||
// in a self-signed JWT token. It follows https://google.aip.dev/auth/4111.
|
||||
aud, err := removeServiceNameFromJWTURI(uri[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO: the returned TokenSource is reusable. Store it in a sync.Map, with
|
||||
// uri as the key, to avoid recreating for every RPC.
|
||||
ts, err := google.JWTAccessTokenSourceFromJSON(j.jsonKey, aud)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
token, err := ts.Token()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ri, _ := credentials.RequestInfoFromContext(ctx)
|
||||
if err = credentials.CheckSecurityLevel(ri.AuthInfo, credentials.PrivacyAndIntegrity); err != nil {
|
||||
return nil, fmt.Errorf("unable to transfer jwtAccess PerRPCCredentials: %v", err)
|
||||
}
|
||||
return map[string]string{
|
||||
"authorization": token.Type() + " " + token.AccessToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (j jwtAccess) RequireTransportSecurity() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// oauthAccess supplies PerRPCCredentials from a given token.
|
||||
type oauthAccess struct {
|
||||
token oauth2.Token
|
||||
}
|
||||
|
||||
// NewOauthAccess constructs the PerRPCCredentials using a given token.
|
||||
//
|
||||
// Deprecated: use oauth.TokenSource instead.
|
||||
func NewOauthAccess(token *oauth2.Token) credentials.PerRPCCredentials {
|
||||
return oauthAccess{token: *token}
|
||||
}
|
||||
|
||||
func (oa oauthAccess) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
|
||||
ri, _ := credentials.RequestInfoFromContext(ctx)
|
||||
if err := credentials.CheckSecurityLevel(ri.AuthInfo, credentials.PrivacyAndIntegrity); err != nil {
|
||||
return nil, fmt.Errorf("unable to transfer oauthAccess PerRPCCredentials: %v", err)
|
||||
}
|
||||
return map[string]string{
|
||||
"authorization": oa.token.Type() + " " + oa.token.AccessToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (oa oauthAccess) RequireTransportSecurity() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// NewComputeEngine constructs the PerRPCCredentials that fetches access tokens from
|
||||
// Google Compute Engine (GCE)'s metadata server. It is only valid to use this
|
||||
// if your program is running on a GCE instance.
|
||||
// TODO(dsymonds): Deprecate and remove this.
|
||||
func NewComputeEngine() credentials.PerRPCCredentials {
|
||||
return TokenSource{google.ComputeTokenSource("")}
|
||||
}
|
||||
|
||||
// serviceAccount represents PerRPCCredentials via JWT signing key.
|
||||
type serviceAccount struct {
|
||||
mu sync.Mutex
|
||||
config *jwt.Config
|
||||
t *oauth2.Token
|
||||
}
|
||||
|
||||
func (s *serviceAccount) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if !s.t.Valid() {
|
||||
var err error
|
||||
s.t, err = s.config.TokenSource(ctx).Token()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
ri, _ := credentials.RequestInfoFromContext(ctx)
|
||||
if err := credentials.CheckSecurityLevel(ri.AuthInfo, credentials.PrivacyAndIntegrity); err != nil {
|
||||
return nil, fmt.Errorf("unable to transfer serviceAccount PerRPCCredentials: %v", err)
|
||||
}
|
||||
return map[string]string{
|
||||
"authorization": s.t.Type() + " " + s.t.AccessToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *serviceAccount) RequireTransportSecurity() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// NewServiceAccountFromKey constructs the PerRPCCredentials using the JSON key slice
|
||||
// from a Google Developers service account.
|
||||
func NewServiceAccountFromKey(jsonKey []byte, scope ...string) (credentials.PerRPCCredentials, error) {
|
||||
config, err := google.JWTConfigFromJSON(jsonKey, scope...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &serviceAccount{config: config}, nil
|
||||
}
|
||||
|
||||
// NewServiceAccountFromFile constructs the PerRPCCredentials using the JSON key file
|
||||
// of a Google Developers service account.
|
||||
func NewServiceAccountFromFile(keyFile string, scope ...string) (credentials.PerRPCCredentials, error) {
|
||||
jsonKey, err := os.ReadFile(keyFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("credentials: failed to read the service account key file: %v", err)
|
||||
}
|
||||
return NewServiceAccountFromKey(jsonKey, scope...)
|
||||
}
|
||||
|
||||
// NewApplicationDefault returns "Application Default Credentials". For more
|
||||
// detail, see https://developers.google.com/accounts/docs/application-default-credentials.
|
||||
func NewApplicationDefault(ctx context.Context, scope ...string) (credentials.PerRPCCredentials, error) {
|
||||
creds, err := google.FindDefaultCredentials(ctx, scope...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If JSON is nil, the authentication is provided by the environment and not
|
||||
// with a credentials file, e.g. when code is running on Google Cloud
|
||||
// Platform. Use the returned token source.
|
||||
if creds.JSON == nil {
|
||||
return TokenSource{creds.TokenSource}, nil
|
||||
}
|
||||
|
||||
// If auth is provided by env variable or creds file, the behavior will be
|
||||
// different based on whether scope is set. Because the returned
|
||||
// creds.TokenSource does oauth with jwt by default, and it requires scope.
|
||||
// We can only use it if scope is not empty, otherwise it will fail with
|
||||
// missing scope error.
|
||||
//
|
||||
// If scope is set, use it, it should just work.
|
||||
//
|
||||
// If scope is not set, we try to use jwt directly without oauth (this only
|
||||
// works if it's a service account).
|
||||
|
||||
if len(scope) != 0 {
|
||||
return TokenSource{creds.TokenSource}, nil
|
||||
}
|
||||
|
||||
// Try to convert JSON to a jwt config without setting the optional scope
|
||||
// parameter to check if it's a service account (the function errors if it's
|
||||
// not). This is necessary because the returned config doesn't show the type
|
||||
// of the account.
|
||||
if _, err := google.JWTConfigFromJSON(creds.JSON); err != nil {
|
||||
// If this fails, it's not a service account, return the original
|
||||
// TokenSource from above.
|
||||
return TokenSource{creds.TokenSource}, nil
|
||||
}
|
||||
|
||||
// If it's a service account, create a JWT only access with the key.
|
||||
return NewJWTAccessFromKey(creds.JSON)
|
||||
}
|
||||
251
vendor/google.golang.org/grpc/credentials/tls.go
generated
vendored
Normal file
251
vendor/google.golang.org/grpc/credentials/tls.go
generated
vendored
Normal file
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2014 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package credentials
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
credinternal "google.golang.org/grpc/internal/credentials"
|
||||
)
|
||||
|
||||
// TLSInfo contains the auth information for a TLS authenticated connection.
|
||||
// It implements the AuthInfo interface.
|
||||
type TLSInfo struct {
|
||||
State tls.ConnectionState
|
||||
CommonAuthInfo
|
||||
// This API is experimental.
|
||||
SPIFFEID *url.URL
|
||||
}
|
||||
|
||||
// AuthType returns the type of TLSInfo as a string.
|
||||
func (t TLSInfo) AuthType() string {
|
||||
return "tls"
|
||||
}
|
||||
|
||||
// cipherSuiteLookup returns the string version of a TLS cipher suite ID.
|
||||
func cipherSuiteLookup(cipherSuiteID uint16) string {
|
||||
for _, s := range tls.CipherSuites() {
|
||||
if s.ID == cipherSuiteID {
|
||||
return s.Name
|
||||
}
|
||||
}
|
||||
for _, s := range tls.InsecureCipherSuites() {
|
||||
if s.ID == cipherSuiteID {
|
||||
return s.Name
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("unknown ID: %v", cipherSuiteID)
|
||||
}
|
||||
|
||||
// GetSecurityValue returns security info requested by channelz.
|
||||
func (t TLSInfo) GetSecurityValue() ChannelzSecurityValue {
|
||||
v := &TLSChannelzSecurityValue{
|
||||
StandardName: cipherSuiteLookup(t.State.CipherSuite),
|
||||
}
|
||||
// Currently there's no way to get LocalCertificate info from tls package.
|
||||
if len(t.State.PeerCertificates) > 0 {
|
||||
v.RemoteCertificate = t.State.PeerCertificates[0].Raw
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// tlsCreds is the credentials required for authenticating a connection using TLS.
|
||||
type tlsCreds struct {
|
||||
// TLS configuration
|
||||
config *tls.Config
|
||||
}
|
||||
|
||||
func (c tlsCreds) Info() ProtocolInfo {
|
||||
return ProtocolInfo{
|
||||
SecurityProtocol: "tls",
|
||||
SecurityVersion: "1.2",
|
||||
ServerName: c.config.ServerName,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *tlsCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (_ net.Conn, _ AuthInfo, err error) {
|
||||
// use local cfg to avoid clobbering ServerName if using multiple endpoints
|
||||
cfg := credinternal.CloneTLSConfig(c.config)
|
||||
if cfg.ServerName == "" {
|
||||
serverName, _, err := net.SplitHostPort(authority)
|
||||
if err != nil {
|
||||
// If the authority had no host port or if the authority cannot be parsed, use it as-is.
|
||||
serverName = authority
|
||||
}
|
||||
cfg.ServerName = serverName
|
||||
}
|
||||
conn := tls.Client(rawConn, cfg)
|
||||
errChannel := make(chan error, 1)
|
||||
go func() {
|
||||
errChannel <- conn.Handshake()
|
||||
close(errChannel)
|
||||
}()
|
||||
select {
|
||||
case err := <-errChannel:
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, nil, err
|
||||
}
|
||||
case <-ctx.Done():
|
||||
conn.Close()
|
||||
return nil, nil, ctx.Err()
|
||||
}
|
||||
tlsInfo := TLSInfo{
|
||||
State: conn.ConnectionState(),
|
||||
CommonAuthInfo: CommonAuthInfo{
|
||||
SecurityLevel: PrivacyAndIntegrity,
|
||||
},
|
||||
}
|
||||
id := credinternal.SPIFFEIDFromState(conn.ConnectionState())
|
||||
if id != nil {
|
||||
tlsInfo.SPIFFEID = id
|
||||
}
|
||||
return credinternal.WrapSyscallConn(rawConn, conn), tlsInfo, nil
|
||||
}
|
||||
|
||||
func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) {
|
||||
conn := tls.Server(rawConn, c.config)
|
||||
if err := conn.Handshake(); err != nil {
|
||||
conn.Close()
|
||||
return nil, nil, err
|
||||
}
|
||||
tlsInfo := TLSInfo{
|
||||
State: conn.ConnectionState(),
|
||||
CommonAuthInfo: CommonAuthInfo{
|
||||
SecurityLevel: PrivacyAndIntegrity,
|
||||
},
|
||||
}
|
||||
id := credinternal.SPIFFEIDFromState(conn.ConnectionState())
|
||||
if id != nil {
|
||||
tlsInfo.SPIFFEID = id
|
||||
}
|
||||
return credinternal.WrapSyscallConn(rawConn, conn), tlsInfo, nil
|
||||
}
|
||||
|
||||
func (c *tlsCreds) Clone() TransportCredentials {
|
||||
return NewTLS(c.config)
|
||||
}
|
||||
|
||||
func (c *tlsCreds) OverrideServerName(serverNameOverride string) error {
|
||||
c.config.ServerName = serverNameOverride
|
||||
return nil
|
||||
}
|
||||
|
||||
// The following cipher suites are forbidden for use with HTTP/2 by
|
||||
// https://datatracker.ietf.org/doc/html/rfc7540#appendix-A
|
||||
var tls12ForbiddenCipherSuites = map[uint16]struct{}{
|
||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA: {},
|
||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA: {},
|
||||
tls.TLS_RSA_WITH_AES_128_GCM_SHA256: {},
|
||||
tls.TLS_RSA_WITH_AES_256_GCM_SHA384: {},
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: {},
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: {},
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: {},
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: {},
|
||||
}
|
||||
|
||||
// NewTLS uses c to construct a TransportCredentials based on TLS.
|
||||
func NewTLS(c *tls.Config) TransportCredentials {
|
||||
tc := &tlsCreds{credinternal.CloneTLSConfig(c)}
|
||||
tc.config.NextProtos = credinternal.AppendH2ToNextProtos(tc.config.NextProtos)
|
||||
// If the user did not configure a MinVersion and did not configure a
|
||||
// MaxVersion < 1.2, use MinVersion=1.2, which is required by
|
||||
// https://datatracker.ietf.org/doc/html/rfc7540#section-9.2
|
||||
if tc.config.MinVersion == 0 && (tc.config.MaxVersion == 0 || tc.config.MaxVersion >= tls.VersionTLS12) {
|
||||
tc.config.MinVersion = tls.VersionTLS12
|
||||
}
|
||||
// If the user did not configure CipherSuites, use all "secure" cipher
|
||||
// suites reported by the TLS package, but remove some explicitly forbidden
|
||||
// by https://datatracker.ietf.org/doc/html/rfc7540#appendix-A
|
||||
if tc.config.CipherSuites == nil {
|
||||
for _, cs := range tls.CipherSuites() {
|
||||
if _, ok := tls12ForbiddenCipherSuites[cs.ID]; !ok {
|
||||
tc.config.CipherSuites = append(tc.config.CipherSuites, cs.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
return tc
|
||||
}
|
||||
|
||||
// NewClientTLSFromCert constructs TLS credentials from the provided root
|
||||
// certificate authority certificate(s) to validate server connections. If
|
||||
// certificates to establish the identity of the client need to be included in
|
||||
// the credentials (eg: for mTLS), use NewTLS instead, where a complete
|
||||
// tls.Config can be specified.
|
||||
// serverNameOverride is for testing only. If set to a non empty string,
|
||||
// it will override the virtual host name of authority (e.g. :authority header
|
||||
// field) in requests.
|
||||
func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) TransportCredentials {
|
||||
return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp})
|
||||
}
|
||||
|
||||
// NewClientTLSFromFile constructs TLS credentials from the provided root
|
||||
// certificate authority certificate file(s) to validate server connections. If
|
||||
// certificates to establish the identity of the client need to be included in
|
||||
// the credentials (eg: for mTLS), use NewTLS instead, where a complete
|
||||
// tls.Config can be specified.
|
||||
// serverNameOverride is for testing only. If set to a non empty string,
|
||||
// it will override the virtual host name of authority (e.g. :authority header
|
||||
// field) in requests.
|
||||
func NewClientTLSFromFile(certFile, serverNameOverride string) (TransportCredentials, error) {
|
||||
b, err := os.ReadFile(certFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cp := x509.NewCertPool()
|
||||
if !cp.AppendCertsFromPEM(b) {
|
||||
return nil, fmt.Errorf("credentials: failed to append certificates")
|
||||
}
|
||||
return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp}), nil
|
||||
}
|
||||
|
||||
// NewServerTLSFromCert constructs TLS credentials from the input certificate for server.
|
||||
func NewServerTLSFromCert(cert *tls.Certificate) TransportCredentials {
|
||||
return NewTLS(&tls.Config{Certificates: []tls.Certificate{*cert}})
|
||||
}
|
||||
|
||||
// NewServerTLSFromFile constructs TLS credentials from the input certificate file and key
|
||||
// file for server.
|
||||
func NewServerTLSFromFile(certFile, keyFile string) (TransportCredentials, error) {
|
||||
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewTLS(&tls.Config{Certificates: []tls.Certificate{cert}}), nil
|
||||
}
|
||||
|
||||
// TLSChannelzSecurityValue defines the struct that TLS protocol should return
|
||||
// from GetSecurityValue(), containing security info like cipher and certificate used.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This type is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
type TLSChannelzSecurityValue struct {
|
||||
ChannelzSecurityValue
|
||||
StandardName string
|
||||
LocalCertificate []byte
|
||||
RemoteCertificate []byte
|
||||
}
|
||||
736
vendor/google.golang.org/grpc/dialoptions.go
generated
vendored
Normal file
736
vendor/google.golang.org/grpc/dialoptions.go
generated
vendored
Normal file
@@ -0,0 +1,736 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/backoff"
|
||||
"google.golang.org/grpc/channelz"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/internal"
|
||||
internalbackoff "google.golang.org/grpc/internal/backoff"
|
||||
"google.golang.org/grpc/internal/binarylog"
|
||||
"google.golang.org/grpc/internal/transport"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"google.golang.org/grpc/stats"
|
||||
)
|
||||
|
||||
func init() {
|
||||
internal.AddGlobalDialOptions = func(opt ...DialOption) {
|
||||
globalDialOptions = append(globalDialOptions, opt...)
|
||||
}
|
||||
internal.ClearGlobalDialOptions = func() {
|
||||
globalDialOptions = nil
|
||||
}
|
||||
internal.WithBinaryLogger = withBinaryLogger
|
||||
internal.JoinDialOptions = newJoinDialOption
|
||||
internal.DisableGlobalDialOptions = newDisableGlobalDialOptions
|
||||
internal.WithRecvBufferPool = withRecvBufferPool
|
||||
}
|
||||
|
||||
// dialOptions configure a Dial call. dialOptions are set by the DialOption
|
||||
// values passed to Dial.
|
||||
type dialOptions struct {
|
||||
unaryInt UnaryClientInterceptor
|
||||
streamInt StreamClientInterceptor
|
||||
|
||||
chainUnaryInts []UnaryClientInterceptor
|
||||
chainStreamInts []StreamClientInterceptor
|
||||
|
||||
cp Compressor
|
||||
dc Decompressor
|
||||
bs internalbackoff.Strategy
|
||||
block bool
|
||||
returnLastError bool
|
||||
timeout time.Duration
|
||||
authority string
|
||||
binaryLogger binarylog.Logger
|
||||
copts transport.ConnectOptions
|
||||
callOptions []CallOption
|
||||
channelzParent channelz.Identifier
|
||||
disableServiceConfig bool
|
||||
disableRetry bool
|
||||
disableHealthCheck bool
|
||||
healthCheckFunc internal.HealthChecker
|
||||
minConnectTimeout func() time.Duration
|
||||
defaultServiceConfig *ServiceConfig // defaultServiceConfig is parsed from defaultServiceConfigRawJSON.
|
||||
defaultServiceConfigRawJSON *string
|
||||
resolvers []resolver.Builder
|
||||
idleTimeout time.Duration
|
||||
recvBufferPool SharedBufferPool
|
||||
defaultScheme string
|
||||
}
|
||||
|
||||
// DialOption configures how we set up the connection.
|
||||
type DialOption interface {
|
||||
apply(*dialOptions)
|
||||
}
|
||||
|
||||
var globalDialOptions []DialOption
|
||||
|
||||
// EmptyDialOption does not alter the dial configuration. It can be embedded in
|
||||
// another structure to build custom dial options.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This type is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
type EmptyDialOption struct{}
|
||||
|
||||
func (EmptyDialOption) apply(*dialOptions) {}
|
||||
|
||||
type disableGlobalDialOptions struct{}
|
||||
|
||||
func (disableGlobalDialOptions) apply(*dialOptions) {}
|
||||
|
||||
// newDisableGlobalDialOptions returns a DialOption that prevents the ClientConn
|
||||
// from applying the global DialOptions (set via AddGlobalDialOptions).
|
||||
func newDisableGlobalDialOptions() DialOption {
|
||||
return &disableGlobalDialOptions{}
|
||||
}
|
||||
|
||||
// funcDialOption wraps a function that modifies dialOptions into an
|
||||
// implementation of the DialOption interface.
|
||||
type funcDialOption struct {
|
||||
f func(*dialOptions)
|
||||
}
|
||||
|
||||
func (fdo *funcDialOption) apply(do *dialOptions) {
|
||||
fdo.f(do)
|
||||
}
|
||||
|
||||
func newFuncDialOption(f func(*dialOptions)) *funcDialOption {
|
||||
return &funcDialOption{
|
||||
f: f,
|
||||
}
|
||||
}
|
||||
|
||||
type joinDialOption struct {
|
||||
opts []DialOption
|
||||
}
|
||||
|
||||
func (jdo *joinDialOption) apply(do *dialOptions) {
|
||||
for _, opt := range jdo.opts {
|
||||
opt.apply(do)
|
||||
}
|
||||
}
|
||||
|
||||
func newJoinDialOption(opts ...DialOption) DialOption {
|
||||
return &joinDialOption{opts: opts}
|
||||
}
|
||||
|
||||
// WithSharedWriteBuffer allows reusing per-connection transport write buffer.
|
||||
// If this option is set to true every connection will release the buffer after
|
||||
// flushing the data on the wire.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
func WithSharedWriteBuffer(val bool) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.SharedWriteBuffer = val
|
||||
})
|
||||
}
|
||||
|
||||
// WithWriteBufferSize determines how much data can be batched before doing a
|
||||
// write on the wire. The default value for this buffer is 32KB.
|
||||
//
|
||||
// Zero or negative values will disable the write buffer such that each write
|
||||
// will be on underlying connection. Note: A Send call may not directly
|
||||
// translate to a write.
|
||||
func WithWriteBufferSize(s int) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.WriteBufferSize = s
|
||||
})
|
||||
}
|
||||
|
||||
// WithReadBufferSize lets you set the size of read buffer, this determines how
|
||||
// much data can be read at most for each read syscall.
|
||||
//
|
||||
// The default value for this buffer is 32KB. Zero or negative values will
|
||||
// disable read buffer for a connection so data framer can access the
|
||||
// underlying conn directly.
|
||||
func WithReadBufferSize(s int) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.ReadBufferSize = s
|
||||
})
|
||||
}
|
||||
|
||||
// WithInitialWindowSize returns a DialOption which sets the value for initial
|
||||
// window size on a stream. The lower bound for window size is 64K and any value
|
||||
// smaller than that will be ignored.
|
||||
func WithInitialWindowSize(s int32) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.InitialWindowSize = s
|
||||
})
|
||||
}
|
||||
|
||||
// WithInitialConnWindowSize returns a DialOption which sets the value for
|
||||
// initial window size on a connection. The lower bound for window size is 64K
|
||||
// and any value smaller than that will be ignored.
|
||||
func WithInitialConnWindowSize(s int32) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.InitialConnWindowSize = s
|
||||
})
|
||||
}
|
||||
|
||||
// WithMaxMsgSize returns a DialOption which sets the maximum message size the
|
||||
// client can receive.
|
||||
//
|
||||
// Deprecated: use WithDefaultCallOptions(MaxCallRecvMsgSize(s)) instead. Will
|
||||
// be supported throughout 1.x.
|
||||
func WithMaxMsgSize(s int) DialOption {
|
||||
return WithDefaultCallOptions(MaxCallRecvMsgSize(s))
|
||||
}
|
||||
|
||||
// WithDefaultCallOptions returns a DialOption which sets the default
|
||||
// CallOptions for calls over the connection.
|
||||
func WithDefaultCallOptions(cos ...CallOption) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.callOptions = append(o.callOptions, cos...)
|
||||
})
|
||||
}
|
||||
|
||||
// WithCodec returns a DialOption which sets a codec for message marshaling and
|
||||
// unmarshaling.
|
||||
//
|
||||
// Deprecated: use WithDefaultCallOptions(ForceCodec(_)) instead. Will be
|
||||
// supported throughout 1.x.
|
||||
func WithCodec(c Codec) DialOption {
|
||||
return WithDefaultCallOptions(CallCustomCodec(c))
|
||||
}
|
||||
|
||||
// WithCompressor returns a DialOption which sets a Compressor to use for
|
||||
// message compression. It has lower priority than the compressor set by the
|
||||
// UseCompressor CallOption.
|
||||
//
|
||||
// Deprecated: use UseCompressor instead. Will be supported throughout 1.x.
|
||||
func WithCompressor(cp Compressor) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.cp = cp
|
||||
})
|
||||
}
|
||||
|
||||
// WithDecompressor returns a DialOption which sets a Decompressor to use for
|
||||
// incoming message decompression. If incoming response messages are encoded
|
||||
// using the decompressor's Type(), it will be used. Otherwise, the message
|
||||
// encoding will be used to look up the compressor registered via
|
||||
// encoding.RegisterCompressor, which will then be used to decompress the
|
||||
// message. If no compressor is registered for the encoding, an Unimplemented
|
||||
// status error will be returned.
|
||||
//
|
||||
// Deprecated: use encoding.RegisterCompressor instead. Will be supported
|
||||
// throughout 1.x.
|
||||
func WithDecompressor(dc Decompressor) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.dc = dc
|
||||
})
|
||||
}
|
||||
|
||||
// WithConnectParams configures the ClientConn to use the provided ConnectParams
|
||||
// for creating and maintaining connections to servers.
|
||||
//
|
||||
// The backoff configuration specified as part of the ConnectParams overrides
|
||||
// all defaults specified in
|
||||
// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md. Consider
|
||||
// using the backoff.DefaultConfig as a base, in cases where you want to
|
||||
// override only a subset of the backoff configuration.
|
||||
func WithConnectParams(p ConnectParams) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.bs = internalbackoff.Exponential{Config: p.Backoff}
|
||||
o.minConnectTimeout = func() time.Duration {
|
||||
return p.MinConnectTimeout
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// WithBackoffMaxDelay configures the dialer to use the provided maximum delay
|
||||
// when backing off after failed connection attempts.
|
||||
//
|
||||
// Deprecated: use WithConnectParams instead. Will be supported throughout 1.x.
|
||||
func WithBackoffMaxDelay(md time.Duration) DialOption {
|
||||
return WithBackoffConfig(BackoffConfig{MaxDelay: md})
|
||||
}
|
||||
|
||||
// WithBackoffConfig configures the dialer to use the provided backoff
|
||||
// parameters after connection failures.
|
||||
//
|
||||
// Deprecated: use WithConnectParams instead. Will be supported throughout 1.x.
|
||||
func WithBackoffConfig(b BackoffConfig) DialOption {
|
||||
bc := backoff.DefaultConfig
|
||||
bc.MaxDelay = b.MaxDelay
|
||||
return withBackoff(internalbackoff.Exponential{Config: bc})
|
||||
}
|
||||
|
||||
// withBackoff sets the backoff strategy used for connectRetryNum after a failed
|
||||
// connection attempt.
|
||||
//
|
||||
// This can be exported if arbitrary backoff strategies are allowed by gRPC.
|
||||
func withBackoff(bs internalbackoff.Strategy) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.bs = bs
|
||||
})
|
||||
}
|
||||
|
||||
// WithBlock returns a DialOption which makes callers of Dial block until the
|
||||
// underlying connection is up. Without this, Dial returns immediately and
|
||||
// connecting the server happens in background.
|
||||
//
|
||||
// Use of this feature is not recommended. For more information, please see:
|
||||
// https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md
|
||||
//
|
||||
// Deprecated: this DialOption is not supported by NewClient.
|
||||
// Will be supported throughout 1.x.
|
||||
func WithBlock() DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.block = true
|
||||
})
|
||||
}
|
||||
|
||||
// WithReturnConnectionError returns a DialOption which makes the client connection
|
||||
// return a string containing both the last connection error that occurred and
|
||||
// the context.DeadlineExceeded error.
|
||||
// Implies WithBlock()
|
||||
//
|
||||
// Use of this feature is not recommended. For more information, please see:
|
||||
// https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md
|
||||
//
|
||||
// Deprecated: this DialOption is not supported by NewClient.
|
||||
// Will be supported throughout 1.x.
|
||||
func WithReturnConnectionError() DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.block = true
|
||||
o.returnLastError = true
|
||||
})
|
||||
}
|
||||
|
||||
// WithInsecure returns a DialOption which disables transport security for this
|
||||
// ClientConn. Under the hood, it uses insecure.NewCredentials().
|
||||
//
|
||||
// Note that using this DialOption with per-RPC credentials (through
|
||||
// WithCredentialsBundle or WithPerRPCCredentials) which require transport
|
||||
// security is incompatible and will cause grpc.Dial() to fail.
|
||||
//
|
||||
// Deprecated: use WithTransportCredentials and insecure.NewCredentials()
|
||||
// instead. Will be supported throughout 1.x.
|
||||
func WithInsecure() DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.TransportCredentials = insecure.NewCredentials()
|
||||
})
|
||||
}
|
||||
|
||||
// WithNoProxy returns a DialOption which disables the use of proxies for this
|
||||
// ClientConn. This is ignored if WithDialer or WithContextDialer are used.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
func WithNoProxy() DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.UseProxy = false
|
||||
})
|
||||
}
|
||||
|
||||
// WithTransportCredentials returns a DialOption which configures a connection
|
||||
// level security credentials (e.g., TLS/SSL). This should not be used together
|
||||
// with WithCredentialsBundle.
|
||||
func WithTransportCredentials(creds credentials.TransportCredentials) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.TransportCredentials = creds
|
||||
})
|
||||
}
|
||||
|
||||
// WithPerRPCCredentials returns a DialOption which sets credentials and places
|
||||
// auth state on each outbound RPC.
|
||||
func WithPerRPCCredentials(creds credentials.PerRPCCredentials) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.PerRPCCredentials = append(o.copts.PerRPCCredentials, creds)
|
||||
})
|
||||
}
|
||||
|
||||
// WithCredentialsBundle returns a DialOption to set a credentials bundle for
|
||||
// the ClientConn.WithCreds. This should not be used together with
|
||||
// WithTransportCredentials.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
func WithCredentialsBundle(b credentials.Bundle) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.CredsBundle = b
|
||||
})
|
||||
}
|
||||
|
||||
// WithTimeout returns a DialOption that configures a timeout for dialing a
|
||||
// ClientConn initially. This is valid if and only if WithBlock() is present.
|
||||
//
|
||||
// Deprecated: this DialOption is not supported by NewClient.
|
||||
// Will be supported throughout 1.x.
|
||||
func WithTimeout(d time.Duration) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.timeout = d
|
||||
})
|
||||
}
|
||||
|
||||
// WithContextDialer returns a DialOption that sets a dialer to create
|
||||
// connections. If FailOnNonTempDialError() is set to true, and an error is
|
||||
// returned by f, gRPC checks the error's Temporary() method to decide if it
|
||||
// should try to reconnect to the network address.
|
||||
//
|
||||
// Note: All supported releases of Go (as of December 2023) override the OS
|
||||
// defaults for TCP keepalive time and interval to 15s. To enable TCP keepalive
|
||||
// with OS defaults for keepalive time and interval, use a net.Dialer that sets
|
||||
// the KeepAlive field to a negative value, and sets the SO_KEEPALIVE socket
|
||||
// option to true from the Control field. For a concrete example of how to do
|
||||
// this, see internal.NetDialerWithTCPKeepalive().
|
||||
//
|
||||
// For more information, please see [issue 23459] in the Go github repo.
|
||||
//
|
||||
// [issue 23459]: https://github.com/golang/go/issues/23459
|
||||
func WithContextDialer(f func(context.Context, string) (net.Conn, error)) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.Dialer = f
|
||||
})
|
||||
}
|
||||
|
||||
func init() {
|
||||
internal.WithHealthCheckFunc = withHealthCheckFunc
|
||||
}
|
||||
|
||||
// WithDialer returns a DialOption that specifies a function to use for dialing
|
||||
// network addresses. If FailOnNonTempDialError() is set to true, and an error
|
||||
// is returned by f, gRPC checks the error's Temporary() method to decide if it
|
||||
// should try to reconnect to the network address.
|
||||
//
|
||||
// Deprecated: use WithContextDialer instead. Will be supported throughout
|
||||
// 1.x.
|
||||
func WithDialer(f func(string, time.Duration) (net.Conn, error)) DialOption {
|
||||
return WithContextDialer(
|
||||
func(ctx context.Context, addr string) (net.Conn, error) {
|
||||
if deadline, ok := ctx.Deadline(); ok {
|
||||
return f(addr, time.Until(deadline))
|
||||
}
|
||||
return f(addr, 0)
|
||||
})
|
||||
}
|
||||
|
||||
// WithStatsHandler returns a DialOption that specifies the stats handler for
|
||||
// all the RPCs and underlying network connections in this ClientConn.
|
||||
func WithStatsHandler(h stats.Handler) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
if h == nil {
|
||||
logger.Error("ignoring nil parameter in grpc.WithStatsHandler ClientOption")
|
||||
// Do not allow a nil stats handler, which would otherwise cause
|
||||
// panics.
|
||||
return
|
||||
}
|
||||
o.copts.StatsHandlers = append(o.copts.StatsHandlers, h)
|
||||
})
|
||||
}
|
||||
|
||||
// withBinaryLogger returns a DialOption that specifies the binary logger for
|
||||
// this ClientConn.
|
||||
func withBinaryLogger(bl binarylog.Logger) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.binaryLogger = bl
|
||||
})
|
||||
}
|
||||
|
||||
// FailOnNonTempDialError returns a DialOption that specifies if gRPC fails on
|
||||
// non-temporary dial errors. If f is true, and dialer returns a non-temporary
|
||||
// error, gRPC will fail the connection to the network address and won't try to
|
||||
// reconnect. The default value of FailOnNonTempDialError is false.
|
||||
//
|
||||
// FailOnNonTempDialError only affects the initial dial, and does not do
|
||||
// anything useful unless you are also using WithBlock().
|
||||
//
|
||||
// Use of this feature is not recommended. For more information, please see:
|
||||
// https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md
|
||||
//
|
||||
// Deprecated: this DialOption is not supported by NewClient.
|
||||
// This API may be changed or removed in a
|
||||
// later release.
|
||||
func FailOnNonTempDialError(f bool) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.FailOnNonTempDialError = f
|
||||
})
|
||||
}
|
||||
|
||||
// WithUserAgent returns a DialOption that specifies a user agent string for all
|
||||
// the RPCs.
|
||||
func WithUserAgent(s string) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.UserAgent = s + " " + grpcUA
|
||||
})
|
||||
}
|
||||
|
||||
// WithKeepaliveParams returns a DialOption that specifies keepalive parameters
|
||||
// for the client transport.
|
||||
func WithKeepaliveParams(kp keepalive.ClientParameters) DialOption {
|
||||
if kp.Time < internal.KeepaliveMinPingTime {
|
||||
logger.Warningf("Adjusting keepalive ping interval to minimum period of %v", internal.KeepaliveMinPingTime)
|
||||
kp.Time = internal.KeepaliveMinPingTime
|
||||
}
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.KeepaliveParams = kp
|
||||
})
|
||||
}
|
||||
|
||||
// WithUnaryInterceptor returns a DialOption that specifies the interceptor for
|
||||
// unary RPCs.
|
||||
func WithUnaryInterceptor(f UnaryClientInterceptor) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.unaryInt = f
|
||||
})
|
||||
}
|
||||
|
||||
// WithChainUnaryInterceptor returns a DialOption that specifies the chained
|
||||
// interceptor for unary RPCs. The first interceptor will be the outer most,
|
||||
// while the last interceptor will be the inner most wrapper around the real call.
|
||||
// All interceptors added by this method will be chained, and the interceptor
|
||||
// defined by WithUnaryInterceptor will always be prepended to the chain.
|
||||
func WithChainUnaryInterceptor(interceptors ...UnaryClientInterceptor) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.chainUnaryInts = append(o.chainUnaryInts, interceptors...)
|
||||
})
|
||||
}
|
||||
|
||||
// WithStreamInterceptor returns a DialOption that specifies the interceptor for
|
||||
// streaming RPCs.
|
||||
func WithStreamInterceptor(f StreamClientInterceptor) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.streamInt = f
|
||||
})
|
||||
}
|
||||
|
||||
// WithChainStreamInterceptor returns a DialOption that specifies the chained
|
||||
// interceptor for streaming RPCs. The first interceptor will be the outer most,
|
||||
// while the last interceptor will be the inner most wrapper around the real call.
|
||||
// All interceptors added by this method will be chained, and the interceptor
|
||||
// defined by WithStreamInterceptor will always be prepended to the chain.
|
||||
func WithChainStreamInterceptor(interceptors ...StreamClientInterceptor) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.chainStreamInts = append(o.chainStreamInts, interceptors...)
|
||||
})
|
||||
}
|
||||
|
||||
// WithAuthority returns a DialOption that specifies the value to be used as the
|
||||
// :authority pseudo-header and as the server name in authentication handshake.
|
||||
func WithAuthority(a string) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.authority = a
|
||||
})
|
||||
}
|
||||
|
||||
// WithChannelzParentID returns a DialOption that specifies the channelz ID of
|
||||
// current ClientConn's parent. This function is used in nested channel creation
|
||||
// (e.g. grpclb dial).
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
func WithChannelzParentID(c channelz.Identifier) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.channelzParent = c
|
||||
})
|
||||
}
|
||||
|
||||
// WithDisableServiceConfig returns a DialOption that causes gRPC to ignore any
|
||||
// service config provided by the resolver and provides a hint to the resolver
|
||||
// to not fetch service configs.
|
||||
//
|
||||
// Note that this dial option only disables service config from resolver. If
|
||||
// default service config is provided, gRPC will use the default service config.
|
||||
func WithDisableServiceConfig() DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.disableServiceConfig = true
|
||||
})
|
||||
}
|
||||
|
||||
// WithDefaultServiceConfig returns a DialOption that configures the default
|
||||
// service config, which will be used in cases where:
|
||||
//
|
||||
// 1. WithDisableServiceConfig is also used, or
|
||||
//
|
||||
// 2. The name resolver does not provide a service config or provides an
|
||||
// invalid service config.
|
||||
//
|
||||
// The parameter s is the JSON representation of the default service config.
|
||||
// For more information about service configs, see:
|
||||
// https://github.com/grpc/grpc/blob/master/doc/service_config.md
|
||||
// For a simple example of usage, see:
|
||||
// examples/features/load_balancing/client/main.go
|
||||
func WithDefaultServiceConfig(s string) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.defaultServiceConfigRawJSON = &s
|
||||
})
|
||||
}
|
||||
|
||||
// WithDisableRetry returns a DialOption that disables retries, even if the
|
||||
// service config enables them. This does not impact transparent retries, which
|
||||
// will happen automatically if no data is written to the wire or if the RPC is
|
||||
// unprocessed by the remote server.
|
||||
func WithDisableRetry() DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.disableRetry = true
|
||||
})
|
||||
}
|
||||
|
||||
// MaxHeaderListSizeDialOption is a DialOption that specifies the maximum
|
||||
// (uncompressed) size of header list that the client is prepared to accept.
|
||||
type MaxHeaderListSizeDialOption struct {
|
||||
MaxHeaderListSize uint32
|
||||
}
|
||||
|
||||
func (o MaxHeaderListSizeDialOption) apply(do *dialOptions) {
|
||||
do.copts.MaxHeaderListSize = &o.MaxHeaderListSize
|
||||
}
|
||||
|
||||
// WithMaxHeaderListSize returns a DialOption that specifies the maximum
|
||||
// (uncompressed) size of header list that the client is prepared to accept.
|
||||
func WithMaxHeaderListSize(s uint32) DialOption {
|
||||
return MaxHeaderListSizeDialOption{
|
||||
MaxHeaderListSize: s,
|
||||
}
|
||||
}
|
||||
|
||||
// WithDisableHealthCheck disables the LB channel health checking for all
|
||||
// SubConns of this ClientConn.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
func WithDisableHealthCheck() DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.disableHealthCheck = true
|
||||
})
|
||||
}
|
||||
|
||||
// withHealthCheckFunc replaces the default health check function with the
|
||||
// provided one. It makes tests easier to change the health check function.
|
||||
//
|
||||
// For testing purpose only.
|
||||
func withHealthCheckFunc(f internal.HealthChecker) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.healthCheckFunc = f
|
||||
})
|
||||
}
|
||||
|
||||
func defaultDialOptions() dialOptions {
|
||||
return dialOptions{
|
||||
copts: transport.ConnectOptions{
|
||||
ReadBufferSize: defaultReadBufSize,
|
||||
WriteBufferSize: defaultWriteBufSize,
|
||||
UseProxy: true,
|
||||
UserAgent: grpcUA,
|
||||
},
|
||||
bs: internalbackoff.DefaultExponential,
|
||||
healthCheckFunc: internal.HealthCheckFunc,
|
||||
idleTimeout: 30 * time.Minute,
|
||||
recvBufferPool: nopBufferPool{},
|
||||
defaultScheme: "dns",
|
||||
}
|
||||
}
|
||||
|
||||
// withMinConnectDeadline specifies the function that clientconn uses to
|
||||
// get minConnectDeadline. This can be used to make connection attempts happen
|
||||
// faster/slower.
|
||||
//
|
||||
// For testing purpose only.
|
||||
func withMinConnectDeadline(f func() time.Duration) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.minConnectTimeout = f
|
||||
})
|
||||
}
|
||||
|
||||
// withDefaultScheme is used to allow Dial to use "passthrough" as the default
|
||||
// name resolver, while NewClient uses "dns" otherwise.
|
||||
func withDefaultScheme(s string) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.defaultScheme = s
|
||||
})
|
||||
}
|
||||
|
||||
// WithResolvers allows a list of resolver implementations to be registered
|
||||
// locally with the ClientConn without needing to be globally registered via
|
||||
// resolver.Register. They will be matched against the scheme used for the
|
||||
// current Dial only, and will take precedence over the global registry.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
func WithResolvers(rs ...resolver.Builder) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.resolvers = append(o.resolvers, rs...)
|
||||
})
|
||||
}
|
||||
|
||||
// WithIdleTimeout returns a DialOption that configures an idle timeout for the
|
||||
// channel. If the channel is idle for the configured timeout, i.e there are no
|
||||
// ongoing RPCs and no new RPCs are initiated, the channel will enter idle mode
|
||||
// and as a result the name resolver and load balancer will be shut down. The
|
||||
// channel will exit idle mode when the Connect() method is called or when an
|
||||
// RPC is initiated.
|
||||
//
|
||||
// A default timeout of 30 minutes will be used if this dial option is not set
|
||||
// at dial time and idleness can be disabled by passing a timeout of zero.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
func WithIdleTimeout(d time.Duration) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.idleTimeout = d
|
||||
})
|
||||
}
|
||||
|
||||
// WithRecvBufferPool returns a DialOption that configures the ClientConn
|
||||
// to use the provided shared buffer pool for parsing incoming messages. Depending
|
||||
// on the application's workload, this could result in reduced memory allocation.
|
||||
//
|
||||
// If you are unsure about how to implement a memory pool but want to utilize one,
|
||||
// begin with grpc.NewSharedBufferPool.
|
||||
//
|
||||
// Note: The shared buffer pool feature will not be active if any of the following
|
||||
// options are used: WithStatsHandler, EnableTracing, or binary logging. In such
|
||||
// cases, the shared buffer pool will be ignored.
|
||||
//
|
||||
// Deprecated: use experimental.WithRecvBufferPool instead. Will be deleted in
|
||||
// v1.60.0 or later.
|
||||
func WithRecvBufferPool(bufferPool SharedBufferPool) DialOption {
|
||||
return withRecvBufferPool(bufferPool)
|
||||
}
|
||||
|
||||
func withRecvBufferPool(bufferPool SharedBufferPool) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.recvBufferPool = bufferPool
|
||||
})
|
||||
}
|
||||
26
vendor/google.golang.org/grpc/doc.go
generated
vendored
Normal file
26
vendor/google.golang.org/grpc/doc.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2015 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
//go:generate ./regenerate.sh
|
||||
|
||||
/*
|
||||
Package grpc implements an RPC system called gRPC.
|
||||
|
||||
See grpc.io for more information about gRPC.
|
||||
*/
|
||||
package grpc // import "google.golang.org/grpc"
|
||||
130
vendor/google.golang.org/grpc/encoding/encoding.go
generated
vendored
Normal file
130
vendor/google.golang.org/grpc/encoding/encoding.go
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package encoding defines the interface for the compressor and codec, and
|
||||
// functions to register and retrieve compressors and codecs.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This package is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/grpc/internal/grpcutil"
|
||||
)
|
||||
|
||||
// Identity specifies the optional encoding for uncompressed streams.
|
||||
// It is intended for grpc internal use only.
|
||||
const Identity = "identity"
|
||||
|
||||
// Compressor is used for compressing and decompressing when sending or
|
||||
// receiving messages.
|
||||
//
|
||||
// If a Compressor implements `DecompressedSize(compressedBytes []byte) int`,
|
||||
// gRPC will invoke it to determine the size of the buffer allocated for the
|
||||
// result of decompression. A return value of -1 indicates unknown size.
|
||||
type Compressor interface {
|
||||
// Compress writes the data written to wc to w after compressing it. If an
|
||||
// error occurs while initializing the compressor, that error is returned
|
||||
// instead.
|
||||
Compress(w io.Writer) (io.WriteCloser, error)
|
||||
// Decompress reads data from r, decompresses it, and provides the
|
||||
// uncompressed data via the returned io.Reader. If an error occurs while
|
||||
// initializing the decompressor, that error is returned instead.
|
||||
Decompress(r io.Reader) (io.Reader, error)
|
||||
// Name is the name of the compression codec and is used to set the content
|
||||
// coding header. The result must be static; the result cannot change
|
||||
// between calls.
|
||||
Name() string
|
||||
}
|
||||
|
||||
var registeredCompressor = make(map[string]Compressor)
|
||||
|
||||
// RegisterCompressor registers the compressor with gRPC by its name. It can
|
||||
// be activated when sending an RPC via grpc.UseCompressor(). It will be
|
||||
// automatically accessed when receiving a message based on the content coding
|
||||
// header. Servers also use it to send a response with the same encoding as
|
||||
// the request.
|
||||
//
|
||||
// NOTE: this function must only be called during initialization time (i.e. in
|
||||
// an init() function), and is not thread-safe. If multiple Compressors are
|
||||
// registered with the same name, the one registered last will take effect.
|
||||
func RegisterCompressor(c Compressor) {
|
||||
registeredCompressor[c.Name()] = c
|
||||
if !grpcutil.IsCompressorNameRegistered(c.Name()) {
|
||||
grpcutil.RegisteredCompressorNames = append(grpcutil.RegisteredCompressorNames, c.Name())
|
||||
}
|
||||
}
|
||||
|
||||
// GetCompressor returns Compressor for the given compressor name.
|
||||
func GetCompressor(name string) Compressor {
|
||||
return registeredCompressor[name]
|
||||
}
|
||||
|
||||
// Codec defines the interface gRPC uses to encode and decode messages. Note
|
||||
// that implementations of this interface must be thread safe; a Codec's
|
||||
// methods can be called from concurrent goroutines.
|
||||
type Codec interface {
|
||||
// Marshal returns the wire format of v.
|
||||
Marshal(v any) ([]byte, error)
|
||||
// Unmarshal parses the wire format into v.
|
||||
Unmarshal(data []byte, v any) error
|
||||
// Name returns the name of the Codec implementation. The returned string
|
||||
// will be used as part of content type in transmission. The result must be
|
||||
// static; the result cannot change between calls.
|
||||
Name() string
|
||||
}
|
||||
|
||||
var registeredCodecs = make(map[string]Codec)
|
||||
|
||||
// RegisterCodec registers the provided Codec for use with all gRPC clients and
|
||||
// servers.
|
||||
//
|
||||
// The Codec will be stored and looked up by result of its Name() method, which
|
||||
// should match the content-subtype of the encoding handled by the Codec. This
|
||||
// is case-insensitive, and is stored and looked up as lowercase. If the
|
||||
// result of calling Name() is an empty string, RegisterCodec will panic. See
|
||||
// Content-Type on
|
||||
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
|
||||
// more details.
|
||||
//
|
||||
// NOTE: this function must only be called during initialization time (i.e. in
|
||||
// an init() function), and is not thread-safe. If multiple Codecs are
|
||||
// registered with the same name, the one registered last will take effect.
|
||||
func RegisterCodec(codec Codec) {
|
||||
if codec == nil {
|
||||
panic("cannot register a nil Codec")
|
||||
}
|
||||
if codec.Name() == "" {
|
||||
panic("cannot register Codec with empty string result for Name()")
|
||||
}
|
||||
contentSubtype := strings.ToLower(codec.Name())
|
||||
registeredCodecs[contentSubtype] = codec
|
||||
}
|
||||
|
||||
// GetCodec gets a registered Codec by content-subtype, or nil if no Codec is
|
||||
// registered for the content-subtype.
|
||||
//
|
||||
// The content-subtype is expected to be lowercase.
|
||||
func GetCodec(contentSubtype string) Codec {
|
||||
return registeredCodecs[contentSubtype]
|
||||
}
|
||||
72
vendor/google.golang.org/grpc/encoding/proto/proto.go
generated
vendored
Normal file
72
vendor/google.golang.org/grpc/encoding/proto/proto.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package proto defines the protobuf codec. Importing this package will
|
||||
// register the codec.
|
||||
package proto
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/grpc/encoding"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/protoadapt"
|
||||
)
|
||||
|
||||
// Name is the name registered for the proto compressor.
|
||||
const Name = "proto"
|
||||
|
||||
func init() {
|
||||
encoding.RegisterCodec(codec{})
|
||||
}
|
||||
|
||||
// codec is a Codec implementation with protobuf. It is the default codec for gRPC.
|
||||
type codec struct{}
|
||||
|
||||
func (codec) Marshal(v any) ([]byte, error) {
|
||||
vv := messageV2Of(v)
|
||||
if vv == nil {
|
||||
return nil, fmt.Errorf("failed to marshal, message is %T, want proto.Message", v)
|
||||
}
|
||||
|
||||
return proto.Marshal(vv)
|
||||
}
|
||||
|
||||
func (codec) Unmarshal(data []byte, v any) error {
|
||||
vv := messageV2Of(v)
|
||||
if vv == nil {
|
||||
return fmt.Errorf("failed to unmarshal, message is %T, want proto.Message", v)
|
||||
}
|
||||
|
||||
return proto.Unmarshal(data, vv)
|
||||
}
|
||||
|
||||
func messageV2Of(v any) proto.Message {
|
||||
switch v := v.(type) {
|
||||
case protoadapt.MessageV1:
|
||||
return protoadapt.MessageV2Of(v)
|
||||
case protoadapt.MessageV2:
|
||||
return v
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (codec) Name() string {
|
||||
return Name
|
||||
}
|
||||
117
vendor/google.golang.org/grpc/grpclog/component.go
generated
vendored
Normal file
117
vendor/google.golang.org/grpc/grpclog/component.go
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpclog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/grpc/internal/grpclog"
|
||||
)
|
||||
|
||||
// componentData records the settings for a component.
|
||||
type componentData struct {
|
||||
name string
|
||||
}
|
||||
|
||||
var cache = map[string]*componentData{}
|
||||
|
||||
func (c *componentData) InfoDepth(depth int, args ...any) {
|
||||
args = append([]any{"[" + string(c.name) + "]"}, args...)
|
||||
grpclog.InfoDepth(depth+1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) WarningDepth(depth int, args ...any) {
|
||||
args = append([]any{"[" + string(c.name) + "]"}, args...)
|
||||
grpclog.WarningDepth(depth+1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) ErrorDepth(depth int, args ...any) {
|
||||
args = append([]any{"[" + string(c.name) + "]"}, args...)
|
||||
grpclog.ErrorDepth(depth+1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) FatalDepth(depth int, args ...any) {
|
||||
args = append([]any{"[" + string(c.name) + "]"}, args...)
|
||||
grpclog.FatalDepth(depth+1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) Info(args ...any) {
|
||||
c.InfoDepth(1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) Warning(args ...any) {
|
||||
c.WarningDepth(1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) Error(args ...any) {
|
||||
c.ErrorDepth(1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) Fatal(args ...any) {
|
||||
c.FatalDepth(1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) Infof(format string, args ...any) {
|
||||
c.InfoDepth(1, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (c *componentData) Warningf(format string, args ...any) {
|
||||
c.WarningDepth(1, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (c *componentData) Errorf(format string, args ...any) {
|
||||
c.ErrorDepth(1, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (c *componentData) Fatalf(format string, args ...any) {
|
||||
c.FatalDepth(1, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (c *componentData) Infoln(args ...any) {
|
||||
c.InfoDepth(1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) Warningln(args ...any) {
|
||||
c.WarningDepth(1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) Errorln(args ...any) {
|
||||
c.ErrorDepth(1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) Fatalln(args ...any) {
|
||||
c.FatalDepth(1, args...)
|
||||
}
|
||||
|
||||
func (c *componentData) V(l int) bool {
|
||||
return V(l)
|
||||
}
|
||||
|
||||
// Component creates a new component and returns it for logging. If a component
|
||||
// with the name already exists, nothing will be created and it will be
|
||||
// returned. SetLoggerV2 will panic if it is called with a logger created by
|
||||
// Component.
|
||||
func Component(componentName string) DepthLoggerV2 {
|
||||
if cData, ok := cache[componentName]; ok {
|
||||
return cData
|
||||
}
|
||||
c := &componentData{componentName}
|
||||
cache[componentName] = c
|
||||
return c
|
||||
}
|
||||
132
vendor/google.golang.org/grpc/grpclog/grpclog.go
generated
vendored
Normal file
132
vendor/google.golang.org/grpc/grpclog/grpclog.go
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package grpclog defines logging for grpc.
|
||||
//
|
||||
// All logs in transport and grpclb packages only go to verbose level 2.
|
||||
// All logs in other packages in grpc are logged in spite of the verbosity level.
|
||||
//
|
||||
// In the default logger,
|
||||
// severity level can be set by environment variable GRPC_GO_LOG_SEVERITY_LEVEL,
|
||||
// verbosity level can be set by GRPC_GO_LOG_VERBOSITY_LEVEL.
|
||||
package grpclog // import "google.golang.org/grpc/grpclog"
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"google.golang.org/grpc/internal/grpclog"
|
||||
)
|
||||
|
||||
func init() {
|
||||
SetLoggerV2(newLoggerV2())
|
||||
}
|
||||
|
||||
// V reports whether verbosity level l is at least the requested verbose level.
|
||||
func V(l int) bool {
|
||||
return grpclog.Logger.V(l)
|
||||
}
|
||||
|
||||
// Info logs to the INFO log.
|
||||
func Info(args ...any) {
|
||||
grpclog.Logger.Info(args...)
|
||||
}
|
||||
|
||||
// Infof logs to the INFO log. Arguments are handled in the manner of fmt.Printf.
|
||||
func Infof(format string, args ...any) {
|
||||
grpclog.Logger.Infof(format, args...)
|
||||
}
|
||||
|
||||
// Infoln logs to the INFO log. Arguments are handled in the manner of fmt.Println.
|
||||
func Infoln(args ...any) {
|
||||
grpclog.Logger.Infoln(args...)
|
||||
}
|
||||
|
||||
// Warning logs to the WARNING log.
|
||||
func Warning(args ...any) {
|
||||
grpclog.Logger.Warning(args...)
|
||||
}
|
||||
|
||||
// Warningf logs to the WARNING log. Arguments are handled in the manner of fmt.Printf.
|
||||
func Warningf(format string, args ...any) {
|
||||
grpclog.Logger.Warningf(format, args...)
|
||||
}
|
||||
|
||||
// Warningln logs to the WARNING log. Arguments are handled in the manner of fmt.Println.
|
||||
func Warningln(args ...any) {
|
||||
grpclog.Logger.Warningln(args...)
|
||||
}
|
||||
|
||||
// Error logs to the ERROR log.
|
||||
func Error(args ...any) {
|
||||
grpclog.Logger.Error(args...)
|
||||
}
|
||||
|
||||
// Errorf logs to the ERROR log. Arguments are handled in the manner of fmt.Printf.
|
||||
func Errorf(format string, args ...any) {
|
||||
grpclog.Logger.Errorf(format, args...)
|
||||
}
|
||||
|
||||
// Errorln logs to the ERROR log. Arguments are handled in the manner of fmt.Println.
|
||||
func Errorln(args ...any) {
|
||||
grpclog.Logger.Errorln(args...)
|
||||
}
|
||||
|
||||
// Fatal logs to the FATAL log. Arguments are handled in the manner of fmt.Print.
|
||||
// It calls os.Exit() with exit code 1.
|
||||
func Fatal(args ...any) {
|
||||
grpclog.Logger.Fatal(args...)
|
||||
// Make sure fatal logs will exit.
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Fatalf logs to the FATAL log. Arguments are handled in the manner of fmt.Printf.
|
||||
// It calls os.Exit() with exit code 1.
|
||||
func Fatalf(format string, args ...any) {
|
||||
grpclog.Logger.Fatalf(format, args...)
|
||||
// Make sure fatal logs will exit.
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Fatalln logs to the FATAL log. Arguments are handled in the manner of fmt.Println.
|
||||
// It calle os.Exit()) with exit code 1.
|
||||
func Fatalln(args ...any) {
|
||||
grpclog.Logger.Fatalln(args...)
|
||||
// Make sure fatal logs will exit.
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Print prints to the logger. Arguments are handled in the manner of fmt.Print.
|
||||
//
|
||||
// Deprecated: use Info.
|
||||
func Print(args ...any) {
|
||||
grpclog.Logger.Info(args...)
|
||||
}
|
||||
|
||||
// Printf prints to the logger. Arguments are handled in the manner of fmt.Printf.
|
||||
//
|
||||
// Deprecated: use Infof.
|
||||
func Printf(format string, args ...any) {
|
||||
grpclog.Logger.Infof(format, args...)
|
||||
}
|
||||
|
||||
// Println prints to the logger. Arguments are handled in the manner of fmt.Println.
|
||||
//
|
||||
// Deprecated: use Infoln.
|
||||
func Println(args ...any) {
|
||||
grpclog.Logger.Infoln(args...)
|
||||
}
|
||||
87
vendor/google.golang.org/grpc/grpclog/logger.go
generated
vendored
Normal file
87
vendor/google.golang.org/grpc/grpclog/logger.go
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2015 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpclog
|
||||
|
||||
import "google.golang.org/grpc/internal/grpclog"
|
||||
|
||||
// Logger mimics golang's standard Logger as an interface.
|
||||
//
|
||||
// Deprecated: use LoggerV2.
|
||||
type Logger interface {
|
||||
Fatal(args ...any)
|
||||
Fatalf(format string, args ...any)
|
||||
Fatalln(args ...any)
|
||||
Print(args ...any)
|
||||
Printf(format string, args ...any)
|
||||
Println(args ...any)
|
||||
}
|
||||
|
||||
// SetLogger sets the logger that is used in grpc. Call only from
|
||||
// init() functions.
|
||||
//
|
||||
// Deprecated: use SetLoggerV2.
|
||||
func SetLogger(l Logger) {
|
||||
grpclog.Logger = &loggerWrapper{Logger: l}
|
||||
}
|
||||
|
||||
// loggerWrapper wraps Logger into a LoggerV2.
|
||||
type loggerWrapper struct {
|
||||
Logger
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Info(args ...any) {
|
||||
g.Logger.Print(args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Infoln(args ...any) {
|
||||
g.Logger.Println(args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Infof(format string, args ...any) {
|
||||
g.Logger.Printf(format, args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Warning(args ...any) {
|
||||
g.Logger.Print(args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Warningln(args ...any) {
|
||||
g.Logger.Println(args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Warningf(format string, args ...any) {
|
||||
g.Logger.Printf(format, args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Error(args ...any) {
|
||||
g.Logger.Print(args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Errorln(args ...any) {
|
||||
g.Logger.Println(args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) Errorf(format string, args ...any) {
|
||||
g.Logger.Printf(format, args...)
|
||||
}
|
||||
|
||||
func (g *loggerWrapper) V(l int) bool {
|
||||
// Returns true for all verbose level.
|
||||
return true
|
||||
}
|
||||
258
vendor/google.golang.org/grpc/grpclog/loggerv2.go
generated
vendored
Normal file
258
vendor/google.golang.org/grpc/grpclog/loggerv2.go
generated
vendored
Normal file
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpclog
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/grpc/internal/grpclog"
|
||||
)
|
||||
|
||||
// LoggerV2 does underlying logging work for grpclog.
|
||||
type LoggerV2 interface {
|
||||
// Info logs to INFO log. Arguments are handled in the manner of fmt.Print.
|
||||
Info(args ...any)
|
||||
// Infoln logs to INFO log. Arguments are handled in the manner of fmt.Println.
|
||||
Infoln(args ...any)
|
||||
// Infof logs to INFO log. Arguments are handled in the manner of fmt.Printf.
|
||||
Infof(format string, args ...any)
|
||||
// Warning logs to WARNING log. Arguments are handled in the manner of fmt.Print.
|
||||
Warning(args ...any)
|
||||
// Warningln logs to WARNING log. Arguments are handled in the manner of fmt.Println.
|
||||
Warningln(args ...any)
|
||||
// Warningf logs to WARNING log. Arguments are handled in the manner of fmt.Printf.
|
||||
Warningf(format string, args ...any)
|
||||
// Error logs to ERROR log. Arguments are handled in the manner of fmt.Print.
|
||||
Error(args ...any)
|
||||
// Errorln logs to ERROR log. Arguments are handled in the manner of fmt.Println.
|
||||
Errorln(args ...any)
|
||||
// Errorf logs to ERROR log. Arguments are handled in the manner of fmt.Printf.
|
||||
Errorf(format string, args ...any)
|
||||
// Fatal logs to ERROR log. Arguments are handled in the manner of fmt.Print.
|
||||
// gRPC ensures that all Fatal logs will exit with os.Exit(1).
|
||||
// Implementations may also call os.Exit() with a non-zero exit code.
|
||||
Fatal(args ...any)
|
||||
// Fatalln logs to ERROR log. Arguments are handled in the manner of fmt.Println.
|
||||
// gRPC ensures that all Fatal logs will exit with os.Exit(1).
|
||||
// Implementations may also call os.Exit() with a non-zero exit code.
|
||||
Fatalln(args ...any)
|
||||
// Fatalf logs to ERROR log. Arguments are handled in the manner of fmt.Printf.
|
||||
// gRPC ensures that all Fatal logs will exit with os.Exit(1).
|
||||
// Implementations may also call os.Exit() with a non-zero exit code.
|
||||
Fatalf(format string, args ...any)
|
||||
// V reports whether verbosity level l is at least the requested verbose level.
|
||||
V(l int) bool
|
||||
}
|
||||
|
||||
// SetLoggerV2 sets logger that is used in grpc to a V2 logger.
|
||||
// Not mutex-protected, should be called before any gRPC functions.
|
||||
func SetLoggerV2(l LoggerV2) {
|
||||
if _, ok := l.(*componentData); ok {
|
||||
panic("cannot use component logger as grpclog logger")
|
||||
}
|
||||
grpclog.Logger = l
|
||||
grpclog.DepthLogger, _ = l.(grpclog.DepthLoggerV2)
|
||||
}
|
||||
|
||||
const (
|
||||
// infoLog indicates Info severity.
|
||||
infoLog int = iota
|
||||
// warningLog indicates Warning severity.
|
||||
warningLog
|
||||
// errorLog indicates Error severity.
|
||||
errorLog
|
||||
// fatalLog indicates Fatal severity.
|
||||
fatalLog
|
||||
)
|
||||
|
||||
// severityName contains the string representation of each severity.
|
||||
var severityName = []string{
|
||||
infoLog: "INFO",
|
||||
warningLog: "WARNING",
|
||||
errorLog: "ERROR",
|
||||
fatalLog: "FATAL",
|
||||
}
|
||||
|
||||
// loggerT is the default logger used by grpclog.
|
||||
type loggerT struct {
|
||||
m []*log.Logger
|
||||
v int
|
||||
jsonFormat bool
|
||||
}
|
||||
|
||||
// NewLoggerV2 creates a loggerV2 with the provided writers.
|
||||
// Fatal logs will be written to errorW, warningW, infoW, followed by exit(1).
|
||||
// Error logs will be written to errorW, warningW and infoW.
|
||||
// Warning logs will be written to warningW and infoW.
|
||||
// Info logs will be written to infoW.
|
||||
func NewLoggerV2(infoW, warningW, errorW io.Writer) LoggerV2 {
|
||||
return newLoggerV2WithConfig(infoW, warningW, errorW, loggerV2Config{})
|
||||
}
|
||||
|
||||
// NewLoggerV2WithVerbosity creates a loggerV2 with the provided writers and
|
||||
// verbosity level.
|
||||
func NewLoggerV2WithVerbosity(infoW, warningW, errorW io.Writer, v int) LoggerV2 {
|
||||
return newLoggerV2WithConfig(infoW, warningW, errorW, loggerV2Config{verbose: v})
|
||||
}
|
||||
|
||||
type loggerV2Config struct {
|
||||
verbose int
|
||||
jsonFormat bool
|
||||
}
|
||||
|
||||
func newLoggerV2WithConfig(infoW, warningW, errorW io.Writer, c loggerV2Config) LoggerV2 {
|
||||
var m []*log.Logger
|
||||
flag := log.LstdFlags
|
||||
if c.jsonFormat {
|
||||
flag = 0
|
||||
}
|
||||
m = append(m, log.New(infoW, "", flag))
|
||||
m = append(m, log.New(io.MultiWriter(infoW, warningW), "", flag))
|
||||
ew := io.MultiWriter(infoW, warningW, errorW) // ew will be used for error and fatal.
|
||||
m = append(m, log.New(ew, "", flag))
|
||||
m = append(m, log.New(ew, "", flag))
|
||||
return &loggerT{m: m, v: c.verbose, jsonFormat: c.jsonFormat}
|
||||
}
|
||||
|
||||
// newLoggerV2 creates a loggerV2 to be used as default logger.
|
||||
// All logs are written to stderr.
|
||||
func newLoggerV2() LoggerV2 {
|
||||
errorW := io.Discard
|
||||
warningW := io.Discard
|
||||
infoW := io.Discard
|
||||
|
||||
logLevel := os.Getenv("GRPC_GO_LOG_SEVERITY_LEVEL")
|
||||
switch logLevel {
|
||||
case "", "ERROR", "error": // If env is unset, set level to ERROR.
|
||||
errorW = os.Stderr
|
||||
case "WARNING", "warning":
|
||||
warningW = os.Stderr
|
||||
case "INFO", "info":
|
||||
infoW = os.Stderr
|
||||
}
|
||||
|
||||
var v int
|
||||
vLevel := os.Getenv("GRPC_GO_LOG_VERBOSITY_LEVEL")
|
||||
if vl, err := strconv.Atoi(vLevel); err == nil {
|
||||
v = vl
|
||||
}
|
||||
|
||||
jsonFormat := strings.EqualFold(os.Getenv("GRPC_GO_LOG_FORMATTER"), "json")
|
||||
|
||||
return newLoggerV2WithConfig(infoW, warningW, errorW, loggerV2Config{
|
||||
verbose: v,
|
||||
jsonFormat: jsonFormat,
|
||||
})
|
||||
}
|
||||
|
||||
func (g *loggerT) output(severity int, s string) {
|
||||
sevStr := severityName[severity]
|
||||
if !g.jsonFormat {
|
||||
g.m[severity].Output(2, fmt.Sprintf("%v: %v", sevStr, s))
|
||||
return
|
||||
}
|
||||
// TODO: we can also include the logging component, but that needs more
|
||||
// (API) changes.
|
||||
b, _ := json.Marshal(map[string]string{
|
||||
"severity": sevStr,
|
||||
"message": s,
|
||||
})
|
||||
g.m[severity].Output(2, string(b))
|
||||
}
|
||||
|
||||
func (g *loggerT) Info(args ...any) {
|
||||
g.output(infoLog, fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
func (g *loggerT) Infoln(args ...any) {
|
||||
g.output(infoLog, fmt.Sprintln(args...))
|
||||
}
|
||||
|
||||
func (g *loggerT) Infof(format string, args ...any) {
|
||||
g.output(infoLog, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (g *loggerT) Warning(args ...any) {
|
||||
g.output(warningLog, fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
func (g *loggerT) Warningln(args ...any) {
|
||||
g.output(warningLog, fmt.Sprintln(args...))
|
||||
}
|
||||
|
||||
func (g *loggerT) Warningf(format string, args ...any) {
|
||||
g.output(warningLog, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (g *loggerT) Error(args ...any) {
|
||||
g.output(errorLog, fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
func (g *loggerT) Errorln(args ...any) {
|
||||
g.output(errorLog, fmt.Sprintln(args...))
|
||||
}
|
||||
|
||||
func (g *loggerT) Errorf(format string, args ...any) {
|
||||
g.output(errorLog, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (g *loggerT) Fatal(args ...any) {
|
||||
g.output(fatalLog, fmt.Sprint(args...))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func (g *loggerT) Fatalln(args ...any) {
|
||||
g.output(fatalLog, fmt.Sprintln(args...))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func (g *loggerT) Fatalf(format string, args ...any) {
|
||||
g.output(fatalLog, fmt.Sprintf(format, args...))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func (g *loggerT) V(l int) bool {
|
||||
return l <= g.v
|
||||
}
|
||||
|
||||
// DepthLoggerV2 logs at a specified call frame. If a LoggerV2 also implements
|
||||
// DepthLoggerV2, the below functions will be called with the appropriate stack
|
||||
// depth set for trivial functions the logger may ignore.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This type is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
type DepthLoggerV2 interface {
|
||||
LoggerV2
|
||||
// InfoDepth logs to INFO log at the specified depth. Arguments are handled in the manner of fmt.Println.
|
||||
InfoDepth(depth int, args ...any)
|
||||
// WarningDepth logs to WARNING log at the specified depth. Arguments are handled in the manner of fmt.Println.
|
||||
WarningDepth(depth int, args ...any)
|
||||
// ErrorDepth logs to ERROR log at the specified depth. Arguments are handled in the manner of fmt.Println.
|
||||
ErrorDepth(depth int, args ...any)
|
||||
// FatalDepth logs to FATAL log at the specified depth. Arguments are handled in the manner of fmt.Println.
|
||||
FatalDepth(depth int, args ...any)
|
||||
}
|
||||
104
vendor/google.golang.org/grpc/interceptor.go
generated
vendored
Normal file
104
vendor/google.golang.org/grpc/interceptor.go
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2016 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// UnaryInvoker is called by UnaryClientInterceptor to complete RPCs.
|
||||
type UnaryInvoker func(ctx context.Context, method string, req, reply any, cc *ClientConn, opts ...CallOption) error
|
||||
|
||||
// UnaryClientInterceptor intercepts the execution of a unary RPC on the client.
|
||||
// Unary interceptors can be specified as a DialOption, using
|
||||
// WithUnaryInterceptor() or WithChainUnaryInterceptor(), when creating a
|
||||
// ClientConn. When a unary interceptor(s) is set on a ClientConn, gRPC
|
||||
// delegates all unary RPC invocations to the interceptor, and it is the
|
||||
// responsibility of the interceptor to call invoker to complete the processing
|
||||
// of the RPC.
|
||||
//
|
||||
// method is the RPC name. req and reply are the corresponding request and
|
||||
// response messages. cc is the ClientConn on which the RPC was invoked. invoker
|
||||
// is the handler to complete the RPC and it is the responsibility of the
|
||||
// interceptor to call it. opts contain all applicable call options, including
|
||||
// defaults from the ClientConn as well as per-call options.
|
||||
//
|
||||
// The returned error must be compatible with the status package.
|
||||
type UnaryClientInterceptor func(ctx context.Context, method string, req, reply any, cc *ClientConn, invoker UnaryInvoker, opts ...CallOption) error
|
||||
|
||||
// Streamer is called by StreamClientInterceptor to create a ClientStream.
|
||||
type Streamer func(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (ClientStream, error)
|
||||
|
||||
// StreamClientInterceptor intercepts the creation of a ClientStream. Stream
|
||||
// interceptors can be specified as a DialOption, using WithStreamInterceptor()
|
||||
// or WithChainStreamInterceptor(), when creating a ClientConn. When a stream
|
||||
// interceptor(s) is set on the ClientConn, gRPC delegates all stream creations
|
||||
// to the interceptor, and it is the responsibility of the interceptor to call
|
||||
// streamer.
|
||||
//
|
||||
// desc contains a description of the stream. cc is the ClientConn on which the
|
||||
// RPC was invoked. streamer is the handler to create a ClientStream and it is
|
||||
// the responsibility of the interceptor to call it. opts contain all applicable
|
||||
// call options, including defaults from the ClientConn as well as per-call
|
||||
// options.
|
||||
//
|
||||
// StreamClientInterceptor may return a custom ClientStream to intercept all I/O
|
||||
// operations. The returned error must be compatible with the status package.
|
||||
type StreamClientInterceptor func(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, streamer Streamer, opts ...CallOption) (ClientStream, error)
|
||||
|
||||
// UnaryServerInfo consists of various information about a unary RPC on
|
||||
// server side. All per-rpc information may be mutated by the interceptor.
|
||||
type UnaryServerInfo struct {
|
||||
// Server is the service implementation the user provides. This is read-only.
|
||||
Server any
|
||||
// FullMethod is the full RPC method string, i.e., /package.service/method.
|
||||
FullMethod string
|
||||
}
|
||||
|
||||
// UnaryHandler defines the handler invoked by UnaryServerInterceptor to complete the normal
|
||||
// execution of a unary RPC.
|
||||
//
|
||||
// If a UnaryHandler returns an error, it should either be produced by the
|
||||
// status package, or be one of the context errors. Otherwise, gRPC will use
|
||||
// codes.Unknown as the status code and err.Error() as the status message of the
|
||||
// RPC.
|
||||
type UnaryHandler func(ctx context.Context, req any) (any, error)
|
||||
|
||||
// UnaryServerInterceptor provides a hook to intercept the execution of a unary RPC on the server. info
|
||||
// contains all the information of this RPC the interceptor can operate on. And handler is the wrapper
|
||||
// of the service method implementation. It is the responsibility of the interceptor to invoke handler
|
||||
// to complete the RPC.
|
||||
type UnaryServerInterceptor func(ctx context.Context, req any, info *UnaryServerInfo, handler UnaryHandler) (resp any, err error)
|
||||
|
||||
// StreamServerInfo consists of various information about a streaming RPC on
|
||||
// server side. All per-rpc information may be mutated by the interceptor.
|
||||
type StreamServerInfo struct {
|
||||
// FullMethod is the full RPC method string, i.e., /package.service/method.
|
||||
FullMethod string
|
||||
// IsClientStream indicates whether the RPC is a client streaming RPC.
|
||||
IsClientStream bool
|
||||
// IsServerStream indicates whether the RPC is a server streaming RPC.
|
||||
IsServerStream bool
|
||||
}
|
||||
|
||||
// StreamServerInterceptor provides a hook to intercept the execution of a streaming RPC on the server.
|
||||
// info contains all the information of this RPC the interceptor can operate on. And handler is the
|
||||
// service method implementation. It is the responsibility of the interceptor to invoke handler to
|
||||
// complete the RPC.
|
||||
type StreamServerInterceptor func(srv any, ss ServerStream, info *StreamServerInfo, handler StreamHandler) error
|
||||
109
vendor/google.golang.org/grpc/internal/backoff/backoff.go
generated
vendored
Normal file
109
vendor/google.golang.org/grpc/internal/backoff/backoff.go
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package backoff implement the backoff strategy for gRPC.
|
||||
//
|
||||
// This is kept in internal until the gRPC project decides whether or not to
|
||||
// allow alternative backoff strategies.
|
||||
package backoff
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
grpcbackoff "google.golang.org/grpc/backoff"
|
||||
"google.golang.org/grpc/internal/grpcrand"
|
||||
)
|
||||
|
||||
// Strategy defines the methodology for backing off after a grpc connection
|
||||
// failure.
|
||||
type Strategy interface {
|
||||
// Backoff returns the amount of time to wait before the next retry given
|
||||
// the number of consecutive failures.
|
||||
Backoff(retries int) time.Duration
|
||||
}
|
||||
|
||||
// DefaultExponential is an exponential backoff implementation using the
|
||||
// default values for all the configurable knobs defined in
|
||||
// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md.
|
||||
var DefaultExponential = Exponential{Config: grpcbackoff.DefaultConfig}
|
||||
|
||||
// Exponential implements exponential backoff algorithm as defined in
|
||||
// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md.
|
||||
type Exponential struct {
|
||||
// Config contains all options to configure the backoff algorithm.
|
||||
Config grpcbackoff.Config
|
||||
}
|
||||
|
||||
// Backoff returns the amount of time to wait before the next retry given the
|
||||
// number of retries.
|
||||
func (bc Exponential) Backoff(retries int) time.Duration {
|
||||
if retries == 0 {
|
||||
return bc.Config.BaseDelay
|
||||
}
|
||||
backoff, max := float64(bc.Config.BaseDelay), float64(bc.Config.MaxDelay)
|
||||
for backoff < max && retries > 0 {
|
||||
backoff *= bc.Config.Multiplier
|
||||
retries--
|
||||
}
|
||||
if backoff > max {
|
||||
backoff = max
|
||||
}
|
||||
// Randomize backoff delays so that if a cluster of requests start at
|
||||
// the same time, they won't operate in lockstep.
|
||||
backoff *= 1 + bc.Config.Jitter*(grpcrand.Float64()*2-1)
|
||||
if backoff < 0 {
|
||||
return 0
|
||||
}
|
||||
return time.Duration(backoff)
|
||||
}
|
||||
|
||||
// ErrResetBackoff is the error to be returned by the function executed by RunF,
|
||||
// to instruct the latter to reset its backoff state.
|
||||
var ErrResetBackoff = errors.New("reset backoff state")
|
||||
|
||||
// RunF provides a convenient way to run a function f repeatedly until the
|
||||
// context expires or f returns a non-nil error that is not ErrResetBackoff.
|
||||
// When f returns ErrResetBackoff, RunF continues to run f, but resets its
|
||||
// backoff state before doing so. backoff accepts an integer representing the
|
||||
// number of retries, and returns the amount of time to backoff.
|
||||
func RunF(ctx context.Context, f func() error, backoff func(int) time.Duration) {
|
||||
attempt := 0
|
||||
timer := time.NewTimer(0)
|
||||
for ctx.Err() == nil {
|
||||
select {
|
||||
case <-timer.C:
|
||||
case <-ctx.Done():
|
||||
timer.Stop()
|
||||
return
|
||||
}
|
||||
|
||||
err := f()
|
||||
if errors.Is(err, ErrResetBackoff) {
|
||||
timer.Reset(0)
|
||||
attempt = 0
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
timer.Reset(backoff(attempt))
|
||||
attempt++
|
||||
}
|
||||
}
|
||||
82
vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/config.go
generated
vendored
Normal file
82
vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/config.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2024 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package gracefulswitch
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/serviceconfig"
|
||||
)
|
||||
|
||||
type lbConfig struct {
|
||||
serviceconfig.LoadBalancingConfig
|
||||
|
||||
childBuilder balancer.Builder
|
||||
childConfig serviceconfig.LoadBalancingConfig
|
||||
}
|
||||
|
||||
func ChildName(l serviceconfig.LoadBalancingConfig) string {
|
||||
return l.(*lbConfig).childBuilder.Name()
|
||||
}
|
||||
|
||||
// ParseConfig parses a child config list and returns a LB config for the
|
||||
// gracefulswitch Balancer.
|
||||
//
|
||||
// cfg is expected to be a json.RawMessage containing a JSON array of LB policy
|
||||
// names + configs as the format of the "loadBalancingConfig" field in
|
||||
// ServiceConfig. It returns a type that should be passed to
|
||||
// UpdateClientConnState in the BalancerConfig field.
|
||||
func ParseConfig(cfg json.RawMessage) (serviceconfig.LoadBalancingConfig, error) {
|
||||
var lbCfg []map[string]json.RawMessage
|
||||
if err := json.Unmarshal(cfg, &lbCfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i, e := range lbCfg {
|
||||
if len(e) != 1 {
|
||||
return nil, fmt.Errorf("expected a JSON struct with one entry; received entry %v at index %d", e, i)
|
||||
}
|
||||
|
||||
var name string
|
||||
var jsonCfg json.RawMessage
|
||||
for name, jsonCfg = range e {
|
||||
}
|
||||
|
||||
builder := balancer.Get(name)
|
||||
if builder == nil {
|
||||
// Skip unregistered balancer names.
|
||||
continue
|
||||
}
|
||||
|
||||
parser, ok := builder.(balancer.ConfigParser)
|
||||
if !ok {
|
||||
// This is a valid child with no config.
|
||||
return &lbConfig{childBuilder: builder}, nil
|
||||
}
|
||||
|
||||
cfg, err := parser.ParseConfig(jsonCfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing config for policy %q: %v", name, err)
|
||||
}
|
||||
return &lbConfig{childBuilder: builder, childConfig: cfg}, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no supported policies found in config: %v", string(cfg))
|
||||
}
|
||||
419
vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go
generated
vendored
Normal file
419
vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go
generated
vendored
Normal file
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2022 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package gracefulswitch implements a graceful switch load balancer.
|
||||
package gracefulswitch
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/balancer/base"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
|
||||
var errBalancerClosed = errors.New("gracefulSwitchBalancer is closed")
|
||||
var _ balancer.Balancer = (*Balancer)(nil)
|
||||
|
||||
// NewBalancer returns a graceful switch Balancer.
|
||||
func NewBalancer(cc balancer.ClientConn, opts balancer.BuildOptions) *Balancer {
|
||||
return &Balancer{
|
||||
cc: cc,
|
||||
bOpts: opts,
|
||||
}
|
||||
}
|
||||
|
||||
// Balancer is a utility to gracefully switch from one balancer to
|
||||
// a new balancer. It implements the balancer.Balancer interface.
|
||||
type Balancer struct {
|
||||
bOpts balancer.BuildOptions
|
||||
cc balancer.ClientConn
|
||||
|
||||
// mu protects the following fields and all fields within balancerCurrent
|
||||
// and balancerPending. mu does not need to be held when calling into the
|
||||
// child balancers, as all calls into these children happen only as a direct
|
||||
// result of a call into the gracefulSwitchBalancer, which are also
|
||||
// guaranteed to be synchronous. There is one exception: an UpdateState call
|
||||
// from a child balancer when current and pending are populated can lead to
|
||||
// calling Close() on the current. To prevent that racing with an
|
||||
// UpdateSubConnState from the channel, we hold currentMu during Close and
|
||||
// UpdateSubConnState calls.
|
||||
mu sync.Mutex
|
||||
balancerCurrent *balancerWrapper
|
||||
balancerPending *balancerWrapper
|
||||
closed bool // set to true when this balancer is closed
|
||||
|
||||
// currentMu must be locked before mu. This mutex guards against this
|
||||
// sequence of events: UpdateSubConnState() called, finds the
|
||||
// balancerCurrent, gives up lock, updateState comes in, causes Close() on
|
||||
// balancerCurrent before the UpdateSubConnState is called on the
|
||||
// balancerCurrent.
|
||||
currentMu sync.Mutex
|
||||
}
|
||||
|
||||
// swap swaps out the current lb with the pending lb and updates the ClientConn.
|
||||
// The caller must hold gsb.mu.
|
||||
func (gsb *Balancer) swap() {
|
||||
gsb.cc.UpdateState(gsb.balancerPending.lastState)
|
||||
cur := gsb.balancerCurrent
|
||||
gsb.balancerCurrent = gsb.balancerPending
|
||||
gsb.balancerPending = nil
|
||||
go func() {
|
||||
gsb.currentMu.Lock()
|
||||
defer gsb.currentMu.Unlock()
|
||||
cur.Close()
|
||||
}()
|
||||
}
|
||||
|
||||
// Helper function that checks if the balancer passed in is current or pending.
|
||||
// The caller must hold gsb.mu.
|
||||
func (gsb *Balancer) balancerCurrentOrPending(bw *balancerWrapper) bool {
|
||||
return bw == gsb.balancerCurrent || bw == gsb.balancerPending
|
||||
}
|
||||
|
||||
// SwitchTo initializes the graceful switch process, which completes based on
|
||||
// connectivity state changes on the current/pending balancer. Thus, the switch
|
||||
// process is not complete when this method returns. This method must be called
|
||||
// synchronously alongside the rest of the balancer.Balancer methods this
|
||||
// Graceful Switch Balancer implements.
|
||||
//
|
||||
// Deprecated: use ParseConfig and pass a parsed config to UpdateClientConnState
|
||||
// to cause the Balancer to automatically change to the new child when necessary.
|
||||
func (gsb *Balancer) SwitchTo(builder balancer.Builder) error {
|
||||
_, err := gsb.switchTo(builder)
|
||||
return err
|
||||
}
|
||||
|
||||
func (gsb *Balancer) switchTo(builder balancer.Builder) (*balancerWrapper, error) {
|
||||
gsb.mu.Lock()
|
||||
if gsb.closed {
|
||||
gsb.mu.Unlock()
|
||||
return nil, errBalancerClosed
|
||||
}
|
||||
bw := &balancerWrapper{
|
||||
builder: builder,
|
||||
gsb: gsb,
|
||||
lastState: balancer.State{
|
||||
ConnectivityState: connectivity.Connecting,
|
||||
Picker: base.NewErrPicker(balancer.ErrNoSubConnAvailable),
|
||||
},
|
||||
subconns: make(map[balancer.SubConn]bool),
|
||||
}
|
||||
balToClose := gsb.balancerPending // nil if there is no pending balancer
|
||||
if gsb.balancerCurrent == nil {
|
||||
gsb.balancerCurrent = bw
|
||||
} else {
|
||||
gsb.balancerPending = bw
|
||||
}
|
||||
gsb.mu.Unlock()
|
||||
balToClose.Close()
|
||||
// This function takes a builder instead of a balancer because builder.Build
|
||||
// can call back inline, and this utility needs to handle the callbacks.
|
||||
newBalancer := builder.Build(bw, gsb.bOpts)
|
||||
if newBalancer == nil {
|
||||
// This is illegal and should never happen; we clear the balancerWrapper
|
||||
// we were constructing if it happens to avoid a potential panic.
|
||||
gsb.mu.Lock()
|
||||
if gsb.balancerPending != nil {
|
||||
gsb.balancerPending = nil
|
||||
} else {
|
||||
gsb.balancerCurrent = nil
|
||||
}
|
||||
gsb.mu.Unlock()
|
||||
return nil, balancer.ErrBadResolverState
|
||||
}
|
||||
|
||||
// This write doesn't need to take gsb.mu because this field never gets read
|
||||
// or written to on any calls from the current or pending. Calls from grpc
|
||||
// to this balancer are guaranteed to be called synchronously, so this
|
||||
// bw.Balancer field will never be forwarded to until this SwitchTo()
|
||||
// function returns.
|
||||
bw.Balancer = newBalancer
|
||||
return bw, nil
|
||||
}
|
||||
|
||||
// Returns nil if the graceful switch balancer is closed.
|
||||
func (gsb *Balancer) latestBalancer() *balancerWrapper {
|
||||
gsb.mu.Lock()
|
||||
defer gsb.mu.Unlock()
|
||||
if gsb.balancerPending != nil {
|
||||
return gsb.balancerPending
|
||||
}
|
||||
return gsb.balancerCurrent
|
||||
}
|
||||
|
||||
// UpdateClientConnState forwards the update to the latest balancer created.
|
||||
//
|
||||
// If the state's BalancerConfig is the config returned by a call to
|
||||
// gracefulswitch.ParseConfig, then this function will automatically SwitchTo
|
||||
// the balancer indicated by the config before forwarding its config to it, if
|
||||
// necessary.
|
||||
func (gsb *Balancer) UpdateClientConnState(state balancer.ClientConnState) error {
|
||||
// The resolver data is only relevant to the most recent LB Policy.
|
||||
balToUpdate := gsb.latestBalancer()
|
||||
gsbCfg, ok := state.BalancerConfig.(*lbConfig)
|
||||
if ok {
|
||||
// Switch to the child in the config unless it is already active.
|
||||
if balToUpdate == nil || gsbCfg.childBuilder.Name() != balToUpdate.builder.Name() {
|
||||
var err error
|
||||
balToUpdate, err = gsb.switchTo(gsbCfg.childBuilder)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not switch to new child balancer: %w", err)
|
||||
}
|
||||
}
|
||||
// Unwrap the child balancer's config.
|
||||
state.BalancerConfig = gsbCfg.childConfig
|
||||
}
|
||||
|
||||
if balToUpdate == nil {
|
||||
return errBalancerClosed
|
||||
}
|
||||
|
||||
// Perform this call without gsb.mu to prevent deadlocks if the child calls
|
||||
// back into the channel. The latest balancer can never be closed during a
|
||||
// call from the channel, even without gsb.mu held.
|
||||
return balToUpdate.UpdateClientConnState(state)
|
||||
}
|
||||
|
||||
// ResolverError forwards the error to the latest balancer created.
|
||||
func (gsb *Balancer) ResolverError(err error) {
|
||||
// The resolver data is only relevant to the most recent LB Policy.
|
||||
balToUpdate := gsb.latestBalancer()
|
||||
if balToUpdate == nil {
|
||||
gsb.cc.UpdateState(balancer.State{
|
||||
ConnectivityState: connectivity.TransientFailure,
|
||||
Picker: base.NewErrPicker(err),
|
||||
})
|
||||
return
|
||||
}
|
||||
// Perform this call without gsb.mu to prevent deadlocks if the child calls
|
||||
// back into the channel. The latest balancer can never be closed during a
|
||||
// call from the channel, even without gsb.mu held.
|
||||
balToUpdate.ResolverError(err)
|
||||
}
|
||||
|
||||
// ExitIdle forwards the call to the latest balancer created.
|
||||
//
|
||||
// If the latest balancer does not support ExitIdle, the subConns are
|
||||
// re-connected to manually.
|
||||
func (gsb *Balancer) ExitIdle() {
|
||||
balToUpdate := gsb.latestBalancer()
|
||||
if balToUpdate == nil {
|
||||
return
|
||||
}
|
||||
// There is no need to protect this read with a mutex, as the write to the
|
||||
// Balancer field happens in SwitchTo, which completes before this can be
|
||||
// called.
|
||||
if ei, ok := balToUpdate.Balancer.(balancer.ExitIdler); ok {
|
||||
ei.ExitIdle()
|
||||
return
|
||||
}
|
||||
gsb.mu.Lock()
|
||||
defer gsb.mu.Unlock()
|
||||
for sc := range balToUpdate.subconns {
|
||||
sc.Connect()
|
||||
}
|
||||
}
|
||||
|
||||
// updateSubConnState forwards the update to the appropriate child.
|
||||
func (gsb *Balancer) updateSubConnState(sc balancer.SubConn, state balancer.SubConnState, cb func(balancer.SubConnState)) {
|
||||
gsb.currentMu.Lock()
|
||||
defer gsb.currentMu.Unlock()
|
||||
gsb.mu.Lock()
|
||||
// Forward update to the appropriate child. Even if there is a pending
|
||||
// balancer, the current balancer should continue to get SubConn updates to
|
||||
// maintain the proper state while the pending is still connecting.
|
||||
var balToUpdate *balancerWrapper
|
||||
if gsb.balancerCurrent != nil && gsb.balancerCurrent.subconns[sc] {
|
||||
balToUpdate = gsb.balancerCurrent
|
||||
} else if gsb.balancerPending != nil && gsb.balancerPending.subconns[sc] {
|
||||
balToUpdate = gsb.balancerPending
|
||||
}
|
||||
if balToUpdate == nil {
|
||||
// SubConn belonged to a stale lb policy that has not yet fully closed,
|
||||
// or the balancer was already closed.
|
||||
gsb.mu.Unlock()
|
||||
return
|
||||
}
|
||||
if state.ConnectivityState == connectivity.Shutdown {
|
||||
delete(balToUpdate.subconns, sc)
|
||||
}
|
||||
gsb.mu.Unlock()
|
||||
if cb != nil {
|
||||
cb(state)
|
||||
} else {
|
||||
balToUpdate.UpdateSubConnState(sc, state)
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateSubConnState forwards the update to the appropriate child.
|
||||
func (gsb *Balancer) UpdateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {
|
||||
gsb.updateSubConnState(sc, state, nil)
|
||||
}
|
||||
|
||||
// Close closes any active child balancers.
|
||||
func (gsb *Balancer) Close() {
|
||||
gsb.mu.Lock()
|
||||
gsb.closed = true
|
||||
currentBalancerToClose := gsb.balancerCurrent
|
||||
gsb.balancerCurrent = nil
|
||||
pendingBalancerToClose := gsb.balancerPending
|
||||
gsb.balancerPending = nil
|
||||
gsb.mu.Unlock()
|
||||
|
||||
currentBalancerToClose.Close()
|
||||
pendingBalancerToClose.Close()
|
||||
}
|
||||
|
||||
// balancerWrapper wraps a balancer.Balancer, and overrides some Balancer
|
||||
// methods to help cleanup SubConns created by the wrapped balancer.
|
||||
//
|
||||
// It implements the balancer.ClientConn interface and is passed down in that
|
||||
// capacity to the wrapped balancer. It maintains a set of subConns created by
|
||||
// the wrapped balancer and calls from the latter to create/update/shutdown
|
||||
// SubConns update this set before being forwarded to the parent ClientConn.
|
||||
// State updates from the wrapped balancer can result in invocation of the
|
||||
// graceful switch logic.
|
||||
type balancerWrapper struct {
|
||||
balancer.Balancer
|
||||
gsb *Balancer
|
||||
builder balancer.Builder
|
||||
|
||||
lastState balancer.State
|
||||
subconns map[balancer.SubConn]bool // subconns created by this balancer
|
||||
}
|
||||
|
||||
// Close closes the underlying LB policy and shuts down the subconns it
|
||||
// created. bw must not be referenced via balancerCurrent or balancerPending in
|
||||
// gsb when called. gsb.mu must not be held. Does not panic with a nil
|
||||
// receiver.
|
||||
func (bw *balancerWrapper) Close() {
|
||||
// before Close is called.
|
||||
if bw == nil {
|
||||
return
|
||||
}
|
||||
// There is no need to protect this read with a mutex, as Close() is
|
||||
// impossible to be called concurrently with the write in SwitchTo(). The
|
||||
// callsites of Close() for this balancer in Graceful Switch Balancer will
|
||||
// never be called until SwitchTo() returns.
|
||||
bw.Balancer.Close()
|
||||
bw.gsb.mu.Lock()
|
||||
for sc := range bw.subconns {
|
||||
sc.Shutdown()
|
||||
}
|
||||
bw.gsb.mu.Unlock()
|
||||
}
|
||||
|
||||
func (bw *balancerWrapper) UpdateState(state balancer.State) {
|
||||
// Hold the mutex for this entire call to ensure it cannot occur
|
||||
// concurrently with other updateState() calls. This causes updates to
|
||||
// lastState and calls to cc.UpdateState to happen atomically.
|
||||
bw.gsb.mu.Lock()
|
||||
defer bw.gsb.mu.Unlock()
|
||||
bw.lastState = state
|
||||
|
||||
if !bw.gsb.balancerCurrentOrPending(bw) {
|
||||
return
|
||||
}
|
||||
|
||||
if bw == bw.gsb.balancerCurrent {
|
||||
// In the case that the current balancer exits READY, and there is a pending
|
||||
// balancer, you can forward the pending balancer's cached State up to
|
||||
// ClientConn and swap the pending into the current. This is because there
|
||||
// is no reason to gracefully switch from and keep using the old policy as
|
||||
// the ClientConn is not connected to any backends.
|
||||
if state.ConnectivityState != connectivity.Ready && bw.gsb.balancerPending != nil {
|
||||
bw.gsb.swap()
|
||||
return
|
||||
}
|
||||
// Even if there is a pending balancer waiting to be gracefully switched to,
|
||||
// continue to forward current balancer updates to the Client Conn. Ignoring
|
||||
// state + picker from the current would cause undefined behavior/cause the
|
||||
// system to behave incorrectly from the current LB policies perspective.
|
||||
// Also, the current LB is still being used by grpc to choose SubConns per
|
||||
// RPC, and thus should use the most updated form of the current balancer.
|
||||
bw.gsb.cc.UpdateState(state)
|
||||
return
|
||||
}
|
||||
// This method is now dealing with a state update from the pending balancer.
|
||||
// If the current balancer is currently in a state other than READY, the new
|
||||
// policy can be swapped into place immediately. This is because there is no
|
||||
// reason to gracefully switch from and keep using the old policy as the
|
||||
// ClientConn is not connected to any backends.
|
||||
if state.ConnectivityState != connectivity.Connecting || bw.gsb.balancerCurrent.lastState.ConnectivityState != connectivity.Ready {
|
||||
bw.gsb.swap()
|
||||
}
|
||||
}
|
||||
|
||||
func (bw *balancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
|
||||
bw.gsb.mu.Lock()
|
||||
if !bw.gsb.balancerCurrentOrPending(bw) {
|
||||
bw.gsb.mu.Unlock()
|
||||
return nil, fmt.Errorf("%T at address %p that called NewSubConn is deleted", bw, bw)
|
||||
}
|
||||
bw.gsb.mu.Unlock()
|
||||
|
||||
var sc balancer.SubConn
|
||||
oldListener := opts.StateListener
|
||||
opts.StateListener = func(state balancer.SubConnState) { bw.gsb.updateSubConnState(sc, state, oldListener) }
|
||||
sc, err := bw.gsb.cc.NewSubConn(addrs, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bw.gsb.mu.Lock()
|
||||
if !bw.gsb.balancerCurrentOrPending(bw) { // balancer was closed during this call
|
||||
sc.Shutdown()
|
||||
bw.gsb.mu.Unlock()
|
||||
return nil, fmt.Errorf("%T at address %p that called NewSubConn is deleted", bw, bw)
|
||||
}
|
||||
bw.subconns[sc] = true
|
||||
bw.gsb.mu.Unlock()
|
||||
return sc, nil
|
||||
}
|
||||
|
||||
func (bw *balancerWrapper) ResolveNow(opts resolver.ResolveNowOptions) {
|
||||
// Ignore ResolveNow requests from anything other than the most recent
|
||||
// balancer, because older balancers were already removed from the config.
|
||||
if bw != bw.gsb.latestBalancer() {
|
||||
return
|
||||
}
|
||||
bw.gsb.cc.ResolveNow(opts)
|
||||
}
|
||||
|
||||
func (bw *balancerWrapper) RemoveSubConn(sc balancer.SubConn) {
|
||||
// Note: existing third party balancers may call this, so it must remain
|
||||
// until RemoveSubConn is fully removed.
|
||||
sc.Shutdown()
|
||||
}
|
||||
|
||||
func (bw *balancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resolver.Address) {
|
||||
bw.gsb.mu.Lock()
|
||||
if !bw.gsb.balancerCurrentOrPending(bw) {
|
||||
bw.gsb.mu.Unlock()
|
||||
return
|
||||
}
|
||||
bw.gsb.mu.Unlock()
|
||||
bw.gsb.cc.UpdateAddresses(sc, addrs)
|
||||
}
|
||||
|
||||
func (bw *balancerWrapper) Target() string {
|
||||
return bw.gsb.cc.Target()
|
||||
}
|
||||
46
vendor/google.golang.org/grpc/internal/balancerload/load.go
generated
vendored
Normal file
46
vendor/google.golang.org/grpc/internal/balancerload/load.go
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2019 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Package balancerload defines APIs to parse server loads in trailers. The
|
||||
// parsed loads are sent to balancers in DoneInfo.
|
||||
package balancerload
|
||||
|
||||
import (
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
// Parser converts loads from metadata into a concrete type.
|
||||
type Parser interface {
|
||||
// Parse parses loads from metadata.
|
||||
Parse(md metadata.MD) any
|
||||
}
|
||||
|
||||
var parser Parser
|
||||
|
||||
// SetParser sets the load parser.
|
||||
//
|
||||
// Not mutex-protected, should be called before any gRPC functions.
|
||||
func SetParser(lr Parser) {
|
||||
parser = lr
|
||||
}
|
||||
|
||||
// Parse calls parser.Read().
|
||||
func Parse(md metadata.MD) any {
|
||||
if parser == nil {
|
||||
return nil
|
||||
}
|
||||
return parser.Parse(md)
|
||||
}
|
||||
192
vendor/google.golang.org/grpc/internal/binarylog/binarylog.go
generated
vendored
Normal file
192
vendor/google.golang.org/grpc/internal/binarylog/binarylog.go
generated
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package binarylog implementation binary logging as defined in
|
||||
// https://github.com/grpc/proposal/blob/master/A16-binary-logging.md.
|
||||
package binarylog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/internal/grpcutil"
|
||||
)
|
||||
|
||||
var grpclogLogger = grpclog.Component("binarylog")
|
||||
|
||||
// Logger specifies MethodLoggers for method names with a Log call that
|
||||
// takes a context.
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
type Logger interface {
|
||||
GetMethodLogger(methodName string) MethodLogger
|
||||
}
|
||||
|
||||
// binLogger is the global binary logger for the binary. One of this should be
|
||||
// built at init time from the configuration (environment variable or flags).
|
||||
//
|
||||
// It is used to get a MethodLogger for each individual method.
|
||||
var binLogger Logger
|
||||
|
||||
// SetLogger sets the binary logger.
|
||||
//
|
||||
// Only call this at init time.
|
||||
func SetLogger(l Logger) {
|
||||
binLogger = l
|
||||
}
|
||||
|
||||
// GetLogger gets the binary logger.
|
||||
//
|
||||
// Only call this at init time.
|
||||
func GetLogger() Logger {
|
||||
return binLogger
|
||||
}
|
||||
|
||||
// GetMethodLogger returns the MethodLogger for the given methodName.
|
||||
//
|
||||
// methodName should be in the format of "/service/method".
|
||||
//
|
||||
// Each MethodLogger returned by this method is a new instance. This is to
|
||||
// generate sequence id within the call.
|
||||
func GetMethodLogger(methodName string) MethodLogger {
|
||||
if binLogger == nil {
|
||||
return nil
|
||||
}
|
||||
return binLogger.GetMethodLogger(methodName)
|
||||
}
|
||||
|
||||
func init() {
|
||||
const envStr = "GRPC_BINARY_LOG_FILTER"
|
||||
configStr := os.Getenv(envStr)
|
||||
binLogger = NewLoggerFromConfigString(configStr)
|
||||
}
|
||||
|
||||
// MethodLoggerConfig contains the setting for logging behavior of a method
|
||||
// logger. Currently, it contains the max length of header and message.
|
||||
type MethodLoggerConfig struct {
|
||||
// Max length of header and message.
|
||||
Header, Message uint64
|
||||
}
|
||||
|
||||
// LoggerConfig contains the config for loggers to create method loggers.
|
||||
type LoggerConfig struct {
|
||||
All *MethodLoggerConfig
|
||||
Services map[string]*MethodLoggerConfig
|
||||
Methods map[string]*MethodLoggerConfig
|
||||
|
||||
Blacklist map[string]struct{}
|
||||
}
|
||||
|
||||
type logger struct {
|
||||
config LoggerConfig
|
||||
}
|
||||
|
||||
// NewLoggerFromConfig builds a logger with the given LoggerConfig.
|
||||
func NewLoggerFromConfig(config LoggerConfig) Logger {
|
||||
return &logger{config: config}
|
||||
}
|
||||
|
||||
// newEmptyLogger creates an empty logger. The map fields need to be filled in
|
||||
// using the set* functions.
|
||||
func newEmptyLogger() *logger {
|
||||
return &logger{}
|
||||
}
|
||||
|
||||
// Set method logger for "*".
|
||||
func (l *logger) setDefaultMethodLogger(ml *MethodLoggerConfig) error {
|
||||
if l.config.All != nil {
|
||||
return fmt.Errorf("conflicting global rules found")
|
||||
}
|
||||
l.config.All = ml
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set method logger for "service/*".
|
||||
//
|
||||
// New MethodLogger with same service overrides the old one.
|
||||
func (l *logger) setServiceMethodLogger(service string, ml *MethodLoggerConfig) error {
|
||||
if _, ok := l.config.Services[service]; ok {
|
||||
return fmt.Errorf("conflicting service rules for service %v found", service)
|
||||
}
|
||||
if l.config.Services == nil {
|
||||
l.config.Services = make(map[string]*MethodLoggerConfig)
|
||||
}
|
||||
l.config.Services[service] = ml
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set method logger for "service/method".
|
||||
//
|
||||
// New MethodLogger with same method overrides the old one.
|
||||
func (l *logger) setMethodMethodLogger(method string, ml *MethodLoggerConfig) error {
|
||||
if _, ok := l.config.Blacklist[method]; ok {
|
||||
return fmt.Errorf("conflicting blacklist rules for method %v found", method)
|
||||
}
|
||||
if _, ok := l.config.Methods[method]; ok {
|
||||
return fmt.Errorf("conflicting method rules for method %v found", method)
|
||||
}
|
||||
if l.config.Methods == nil {
|
||||
l.config.Methods = make(map[string]*MethodLoggerConfig)
|
||||
}
|
||||
l.config.Methods[method] = ml
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set blacklist method for "-service/method".
|
||||
func (l *logger) setBlacklist(method string) error {
|
||||
if _, ok := l.config.Blacklist[method]; ok {
|
||||
return fmt.Errorf("conflicting blacklist rules for method %v found", method)
|
||||
}
|
||||
if _, ok := l.config.Methods[method]; ok {
|
||||
return fmt.Errorf("conflicting method rules for method %v found", method)
|
||||
}
|
||||
if l.config.Blacklist == nil {
|
||||
l.config.Blacklist = make(map[string]struct{})
|
||||
}
|
||||
l.config.Blacklist[method] = struct{}{}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getMethodLogger returns the MethodLogger for the given methodName.
|
||||
//
|
||||
// methodName should be in the format of "/service/method".
|
||||
//
|
||||
// Each MethodLogger returned by this method is a new instance. This is to
|
||||
// generate sequence id within the call.
|
||||
func (l *logger) GetMethodLogger(methodName string) MethodLogger {
|
||||
s, m, err := grpcutil.ParseMethod(methodName)
|
||||
if err != nil {
|
||||
grpclogLogger.Infof("binarylogging: failed to parse %q: %v", methodName, err)
|
||||
return nil
|
||||
}
|
||||
if ml, ok := l.config.Methods[s+"/"+m]; ok {
|
||||
return NewTruncatingMethodLogger(ml.Header, ml.Message)
|
||||
}
|
||||
if _, ok := l.config.Blacklist[s+"/"+m]; ok {
|
||||
return nil
|
||||
}
|
||||
if ml, ok := l.config.Services[s]; ok {
|
||||
return NewTruncatingMethodLogger(ml.Header, ml.Message)
|
||||
}
|
||||
if l.config.All == nil {
|
||||
return nil
|
||||
}
|
||||
return NewTruncatingMethodLogger(l.config.All.Header, l.config.All.Message)
|
||||
}
|
||||
42
vendor/google.golang.org/grpc/internal/binarylog/binarylog_testutil.go
generated
vendored
Normal file
42
vendor/google.golang.org/grpc/internal/binarylog/binarylog_testutil.go
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// This file contains exported variables/functions that are exported for testing
|
||||
// only.
|
||||
//
|
||||
// An ideal way for this would be to put those in a *_test.go but in binarylog
|
||||
// package. But this doesn't work with staticcheck with go module. Error was:
|
||||
// "MdToMetadataProto not declared by package binarylog". This could be caused
|
||||
// by the way staticcheck looks for files for a certain package, which doesn't
|
||||
// support *_test.go files.
|
||||
//
|
||||
// Move those to binary_test.go when staticcheck is fixed.
|
||||
|
||||
package binarylog
|
||||
|
||||
var (
|
||||
// AllLogger is a logger that logs all headers/messages for all RPCs. It's
|
||||
// for testing only.
|
||||
AllLogger = NewLoggerFromConfigString("*")
|
||||
// MdToMetadataProto converts metadata to a binary logging proto message.
|
||||
// It's for testing only.
|
||||
MdToMetadataProto = mdToMetadataProto
|
||||
// AddrToProto converts an address to a binary logging proto message. It's
|
||||
// for testing only.
|
||||
AddrToProto = addrToProto
|
||||
)
|
||||
208
vendor/google.golang.org/grpc/internal/binarylog/env_config.go
generated
vendored
Normal file
208
vendor/google.golang.org/grpc/internal/binarylog/env_config.go
generated
vendored
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package binarylog
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// NewLoggerFromConfigString reads the string and build a logger. It can be used
|
||||
// to build a new logger and assign it to binarylog.Logger.
|
||||
//
|
||||
// Example filter config strings:
|
||||
// - "" Nothing will be logged
|
||||
// - "*" All headers and messages will be fully logged.
|
||||
// - "*{h}" Only headers will be logged.
|
||||
// - "*{m:256}" Only the first 256 bytes of each message will be logged.
|
||||
// - "Foo/*" Logs every method in service Foo
|
||||
// - "Foo/*,-Foo/Bar" Logs every method in service Foo except method /Foo/Bar
|
||||
// - "Foo/*,Foo/Bar{m:256}" Logs the first 256 bytes of each message in method
|
||||
// /Foo/Bar, logs all headers and messages in every other method in service
|
||||
// Foo.
|
||||
//
|
||||
// If two configs exist for one certain method or service, the one specified
|
||||
// later overrides the previous config.
|
||||
func NewLoggerFromConfigString(s string) Logger {
|
||||
if s == "" {
|
||||
return nil
|
||||
}
|
||||
l := newEmptyLogger()
|
||||
methods := strings.Split(s, ",")
|
||||
for _, method := range methods {
|
||||
if err := l.fillMethodLoggerWithConfigString(method); err != nil {
|
||||
grpclogLogger.Warningf("failed to parse binary log config: %v", err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
// fillMethodLoggerWithConfigString parses config, creates TruncatingMethodLogger and adds
|
||||
// it to the right map in the logger.
|
||||
func (l *logger) fillMethodLoggerWithConfigString(config string) error {
|
||||
// "" is invalid.
|
||||
if config == "" {
|
||||
return errors.New("empty string is not a valid method binary logging config")
|
||||
}
|
||||
|
||||
// "-service/method", blacklist, no * or {} allowed.
|
||||
if config[0] == '-' {
|
||||
s, m, suffix, err := parseMethodConfigAndSuffix(config[1:])
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid config: %q, %v", config, err)
|
||||
}
|
||||
if m == "*" {
|
||||
return fmt.Errorf("invalid config: %q, %v", config, "* not allowed in blacklist config")
|
||||
}
|
||||
if suffix != "" {
|
||||
return fmt.Errorf("invalid config: %q, %v", config, "header/message limit not allowed in blacklist config")
|
||||
}
|
||||
if err := l.setBlacklist(s + "/" + m); err != nil {
|
||||
return fmt.Errorf("invalid config: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// "*{h:256;m:256}"
|
||||
if config[0] == '*' {
|
||||
hdr, msg, err := parseHeaderMessageLengthConfig(config[1:])
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid config: %q, %v", config, err)
|
||||
}
|
||||
if err := l.setDefaultMethodLogger(&MethodLoggerConfig{Header: hdr, Message: msg}); err != nil {
|
||||
return fmt.Errorf("invalid config: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
s, m, suffix, err := parseMethodConfigAndSuffix(config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid config: %q, %v", config, err)
|
||||
}
|
||||
hdr, msg, err := parseHeaderMessageLengthConfig(suffix)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid header/message length config: %q, %v", suffix, err)
|
||||
}
|
||||
if m == "*" {
|
||||
if err := l.setServiceMethodLogger(s, &MethodLoggerConfig{Header: hdr, Message: msg}); err != nil {
|
||||
return fmt.Errorf("invalid config: %v", err)
|
||||
}
|
||||
} else {
|
||||
if err := l.setMethodMethodLogger(s+"/"+m, &MethodLoggerConfig{Header: hdr, Message: msg}); err != nil {
|
||||
return fmt.Errorf("invalid config: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
// TODO: this const is only used by env_config now. But could be useful for
|
||||
// other config. Move to binarylog.go if necessary.
|
||||
maxUInt = ^uint64(0)
|
||||
|
||||
// For "p.s/m" plus any suffix. Suffix will be parsed again. See test for
|
||||
// expected output.
|
||||
longMethodConfigRegexpStr = `^([\w./]+)/((?:\w+)|[*])(.+)?$`
|
||||
|
||||
// For suffix from above, "{h:123,m:123}". See test for expected output.
|
||||
optionalLengthRegexpStr = `(?::(\d+))?` // Optional ":123".
|
||||
headerConfigRegexpStr = `^{h` + optionalLengthRegexpStr + `}$`
|
||||
messageConfigRegexpStr = `^{m` + optionalLengthRegexpStr + `}$`
|
||||
headerMessageConfigRegexpStr = `^{h` + optionalLengthRegexpStr + `;m` + optionalLengthRegexpStr + `}$`
|
||||
)
|
||||
|
||||
var (
|
||||
longMethodConfigRegexp = regexp.MustCompile(longMethodConfigRegexpStr)
|
||||
headerConfigRegexp = regexp.MustCompile(headerConfigRegexpStr)
|
||||
messageConfigRegexp = regexp.MustCompile(messageConfigRegexpStr)
|
||||
headerMessageConfigRegexp = regexp.MustCompile(headerMessageConfigRegexpStr)
|
||||
)
|
||||
|
||||
// Turn "service/method{h;m}" into "service", "method", "{h;m}".
|
||||
func parseMethodConfigAndSuffix(c string) (service, method, suffix string, _ error) {
|
||||
// Regexp result:
|
||||
//
|
||||
// in: "p.s/m{h:123,m:123}",
|
||||
// out: []string{"p.s/m{h:123,m:123}", "p.s", "m", "{h:123,m:123}"},
|
||||
match := longMethodConfigRegexp.FindStringSubmatch(c)
|
||||
if match == nil {
|
||||
return "", "", "", fmt.Errorf("%q contains invalid substring", c)
|
||||
}
|
||||
service = match[1]
|
||||
method = match[2]
|
||||
suffix = match[3]
|
||||
return
|
||||
}
|
||||
|
||||
// Turn "{h:123;m:345}" into 123, 345.
|
||||
//
|
||||
// Return maxUInt if length is unspecified.
|
||||
func parseHeaderMessageLengthConfig(c string) (hdrLenStr, msgLenStr uint64, err error) {
|
||||
if c == "" {
|
||||
return maxUInt, maxUInt, nil
|
||||
}
|
||||
// Header config only.
|
||||
if match := headerConfigRegexp.FindStringSubmatch(c); match != nil {
|
||||
if s := match[1]; s != "" {
|
||||
hdrLenStr, err = strconv.ParseUint(s, 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("failed to convert %q to uint", s)
|
||||
}
|
||||
return hdrLenStr, 0, nil
|
||||
}
|
||||
return maxUInt, 0, nil
|
||||
}
|
||||
|
||||
// Message config only.
|
||||
if match := messageConfigRegexp.FindStringSubmatch(c); match != nil {
|
||||
if s := match[1]; s != "" {
|
||||
msgLenStr, err = strconv.ParseUint(s, 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("failed to convert %q to uint", s)
|
||||
}
|
||||
return 0, msgLenStr, nil
|
||||
}
|
||||
return 0, maxUInt, nil
|
||||
}
|
||||
|
||||
// Header and message config both.
|
||||
if match := headerMessageConfigRegexp.FindStringSubmatch(c); match != nil {
|
||||
// Both hdr and msg are specified, but one or two of them might be empty.
|
||||
hdrLenStr = maxUInt
|
||||
msgLenStr = maxUInt
|
||||
if s := match[1]; s != "" {
|
||||
hdrLenStr, err = strconv.ParseUint(s, 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("failed to convert %q to uint", s)
|
||||
}
|
||||
}
|
||||
if s := match[2]; s != "" {
|
||||
msgLenStr, err = strconv.ParseUint(s, 10, 64)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("failed to convert %q to uint", s)
|
||||
}
|
||||
}
|
||||
return hdrLenStr, msgLenStr, nil
|
||||
}
|
||||
return 0, 0, fmt.Errorf("%q contains invalid substring", c)
|
||||
}
|
||||
446
vendor/google.golang.org/grpc/internal/binarylog/method_logger.go
generated
vendored
Normal file
446
vendor/google.golang.org/grpc/internal/binarylog/method_logger.go
generated
vendored
Normal file
@@ -0,0 +1,446 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package binarylog
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
binlogpb "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
type callIDGenerator struct {
|
||||
id uint64
|
||||
}
|
||||
|
||||
func (g *callIDGenerator) next() uint64 {
|
||||
id := atomic.AddUint64(&g.id, 1)
|
||||
return id
|
||||
}
|
||||
|
||||
// reset is for testing only, and doesn't need to be thread safe.
|
||||
func (g *callIDGenerator) reset() {
|
||||
g.id = 0
|
||||
}
|
||||
|
||||
var idGen callIDGenerator
|
||||
|
||||
// MethodLogger is the sub-logger for each method.
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
type MethodLogger interface {
|
||||
Log(context.Context, LogEntryConfig)
|
||||
}
|
||||
|
||||
// TruncatingMethodLogger is a method logger that truncates headers and messages
|
||||
// based on configured fields.
|
||||
type TruncatingMethodLogger struct {
|
||||
headerMaxLen, messageMaxLen uint64
|
||||
|
||||
callID uint64
|
||||
idWithinCallGen *callIDGenerator
|
||||
|
||||
sink Sink // TODO(blog): make this pluggable.
|
||||
}
|
||||
|
||||
// NewTruncatingMethodLogger returns a new truncating method logger.
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
func NewTruncatingMethodLogger(h, m uint64) *TruncatingMethodLogger {
|
||||
return &TruncatingMethodLogger{
|
||||
headerMaxLen: h,
|
||||
messageMaxLen: m,
|
||||
|
||||
callID: idGen.next(),
|
||||
idWithinCallGen: &callIDGenerator{},
|
||||
|
||||
sink: DefaultSink, // TODO(blog): make it pluggable.
|
||||
}
|
||||
}
|
||||
|
||||
// Build is an internal only method for building the proto message out of the
|
||||
// input event. It's made public to enable other library to reuse as much logic
|
||||
// in TruncatingMethodLogger as possible.
|
||||
func (ml *TruncatingMethodLogger) Build(c LogEntryConfig) *binlogpb.GrpcLogEntry {
|
||||
m := c.toProto()
|
||||
timestamp := timestamppb.Now()
|
||||
m.Timestamp = timestamp
|
||||
m.CallId = ml.callID
|
||||
m.SequenceIdWithinCall = ml.idWithinCallGen.next()
|
||||
|
||||
switch pay := m.Payload.(type) {
|
||||
case *binlogpb.GrpcLogEntry_ClientHeader:
|
||||
m.PayloadTruncated = ml.truncateMetadata(pay.ClientHeader.GetMetadata())
|
||||
case *binlogpb.GrpcLogEntry_ServerHeader:
|
||||
m.PayloadTruncated = ml.truncateMetadata(pay.ServerHeader.GetMetadata())
|
||||
case *binlogpb.GrpcLogEntry_Message:
|
||||
m.PayloadTruncated = ml.truncateMessage(pay.Message)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// Log creates a proto binary log entry, and logs it to the sink.
|
||||
func (ml *TruncatingMethodLogger) Log(ctx context.Context, c LogEntryConfig) {
|
||||
ml.sink.Write(ml.Build(c))
|
||||
}
|
||||
|
||||
func (ml *TruncatingMethodLogger) truncateMetadata(mdPb *binlogpb.Metadata) (truncated bool) {
|
||||
if ml.headerMaxLen == maxUInt {
|
||||
return false
|
||||
}
|
||||
var (
|
||||
bytesLimit = ml.headerMaxLen
|
||||
index int
|
||||
)
|
||||
// At the end of the loop, index will be the first entry where the total
|
||||
// size is greater than the limit:
|
||||
//
|
||||
// len(entry[:index]) <= ml.hdr && len(entry[:index+1]) > ml.hdr.
|
||||
for ; index < len(mdPb.Entry); index++ {
|
||||
entry := mdPb.Entry[index]
|
||||
if entry.Key == "grpc-trace-bin" {
|
||||
// "grpc-trace-bin" is a special key. It's kept in the log entry,
|
||||
// but not counted towards the size limit.
|
||||
continue
|
||||
}
|
||||
currentEntryLen := uint64(len(entry.GetKey())) + uint64(len(entry.GetValue()))
|
||||
if currentEntryLen > bytesLimit {
|
||||
break
|
||||
}
|
||||
bytesLimit -= currentEntryLen
|
||||
}
|
||||
truncated = index < len(mdPb.Entry)
|
||||
mdPb.Entry = mdPb.Entry[:index]
|
||||
return truncated
|
||||
}
|
||||
|
||||
func (ml *TruncatingMethodLogger) truncateMessage(msgPb *binlogpb.Message) (truncated bool) {
|
||||
if ml.messageMaxLen == maxUInt {
|
||||
return false
|
||||
}
|
||||
if ml.messageMaxLen >= uint64(len(msgPb.Data)) {
|
||||
return false
|
||||
}
|
||||
msgPb.Data = msgPb.Data[:ml.messageMaxLen]
|
||||
return true
|
||||
}
|
||||
|
||||
// LogEntryConfig represents the configuration for binary log entry.
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
type LogEntryConfig interface {
|
||||
toProto() *binlogpb.GrpcLogEntry
|
||||
}
|
||||
|
||||
// ClientHeader configs the binary log entry to be a ClientHeader entry.
|
||||
type ClientHeader struct {
|
||||
OnClientSide bool
|
||||
Header metadata.MD
|
||||
MethodName string
|
||||
Authority string
|
||||
Timeout time.Duration
|
||||
// PeerAddr is required only when it's on server side.
|
||||
PeerAddr net.Addr
|
||||
}
|
||||
|
||||
func (c *ClientHeader) toProto() *binlogpb.GrpcLogEntry {
|
||||
// This function doesn't need to set all the fields (e.g. seq ID). The Log
|
||||
// function will set the fields when necessary.
|
||||
clientHeader := &binlogpb.ClientHeader{
|
||||
Metadata: mdToMetadataProto(c.Header),
|
||||
MethodName: c.MethodName,
|
||||
Authority: c.Authority,
|
||||
}
|
||||
if c.Timeout > 0 {
|
||||
clientHeader.Timeout = durationpb.New(c.Timeout)
|
||||
}
|
||||
ret := &binlogpb.GrpcLogEntry{
|
||||
Type: binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER,
|
||||
Payload: &binlogpb.GrpcLogEntry_ClientHeader{
|
||||
ClientHeader: clientHeader,
|
||||
},
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
if c.PeerAddr != nil {
|
||||
ret.Peer = addrToProto(c.PeerAddr)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// ServerHeader configs the binary log entry to be a ServerHeader entry.
|
||||
type ServerHeader struct {
|
||||
OnClientSide bool
|
||||
Header metadata.MD
|
||||
// PeerAddr is required only when it's on client side.
|
||||
PeerAddr net.Addr
|
||||
}
|
||||
|
||||
func (c *ServerHeader) toProto() *binlogpb.GrpcLogEntry {
|
||||
ret := &binlogpb.GrpcLogEntry{
|
||||
Type: binlogpb.GrpcLogEntry_EVENT_TYPE_SERVER_HEADER,
|
||||
Payload: &binlogpb.GrpcLogEntry_ServerHeader{
|
||||
ServerHeader: &binlogpb.ServerHeader{
|
||||
Metadata: mdToMetadataProto(c.Header),
|
||||
},
|
||||
},
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
if c.PeerAddr != nil {
|
||||
ret.Peer = addrToProto(c.PeerAddr)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// ClientMessage configs the binary log entry to be a ClientMessage entry.
|
||||
type ClientMessage struct {
|
||||
OnClientSide bool
|
||||
// Message can be a proto.Message or []byte. Other messages formats are not
|
||||
// supported.
|
||||
Message any
|
||||
}
|
||||
|
||||
func (c *ClientMessage) toProto() *binlogpb.GrpcLogEntry {
|
||||
var (
|
||||
data []byte
|
||||
err error
|
||||
)
|
||||
if m, ok := c.Message.(proto.Message); ok {
|
||||
data, err = proto.Marshal(m)
|
||||
if err != nil {
|
||||
grpclogLogger.Infof("binarylogging: failed to marshal proto message: %v", err)
|
||||
}
|
||||
} else if b, ok := c.Message.([]byte); ok {
|
||||
data = b
|
||||
} else {
|
||||
grpclogLogger.Infof("binarylogging: message to log is neither proto.message nor []byte")
|
||||
}
|
||||
ret := &binlogpb.GrpcLogEntry{
|
||||
Type: binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_MESSAGE,
|
||||
Payload: &binlogpb.GrpcLogEntry_Message{
|
||||
Message: &binlogpb.Message{
|
||||
Length: uint32(len(data)),
|
||||
Data: data,
|
||||
},
|
||||
},
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// ServerMessage configs the binary log entry to be a ServerMessage entry.
|
||||
type ServerMessage struct {
|
||||
OnClientSide bool
|
||||
// Message can be a proto.Message or []byte. Other messages formats are not
|
||||
// supported.
|
||||
Message any
|
||||
}
|
||||
|
||||
func (c *ServerMessage) toProto() *binlogpb.GrpcLogEntry {
|
||||
var (
|
||||
data []byte
|
||||
err error
|
||||
)
|
||||
if m, ok := c.Message.(proto.Message); ok {
|
||||
data, err = proto.Marshal(m)
|
||||
if err != nil {
|
||||
grpclogLogger.Infof("binarylogging: failed to marshal proto message: %v", err)
|
||||
}
|
||||
} else if b, ok := c.Message.([]byte); ok {
|
||||
data = b
|
||||
} else {
|
||||
grpclogLogger.Infof("binarylogging: message to log is neither proto.message nor []byte")
|
||||
}
|
||||
ret := &binlogpb.GrpcLogEntry{
|
||||
Type: binlogpb.GrpcLogEntry_EVENT_TYPE_SERVER_MESSAGE,
|
||||
Payload: &binlogpb.GrpcLogEntry_Message{
|
||||
Message: &binlogpb.Message{
|
||||
Length: uint32(len(data)),
|
||||
Data: data,
|
||||
},
|
||||
},
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// ClientHalfClose configs the binary log entry to be a ClientHalfClose entry.
|
||||
type ClientHalfClose struct {
|
||||
OnClientSide bool
|
||||
}
|
||||
|
||||
func (c *ClientHalfClose) toProto() *binlogpb.GrpcLogEntry {
|
||||
ret := &binlogpb.GrpcLogEntry{
|
||||
Type: binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_HALF_CLOSE,
|
||||
Payload: nil, // No payload here.
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// ServerTrailer configs the binary log entry to be a ServerTrailer entry.
|
||||
type ServerTrailer struct {
|
||||
OnClientSide bool
|
||||
Trailer metadata.MD
|
||||
// Err is the status error.
|
||||
Err error
|
||||
// PeerAddr is required only when it's on client side and the RPC is trailer
|
||||
// only.
|
||||
PeerAddr net.Addr
|
||||
}
|
||||
|
||||
func (c *ServerTrailer) toProto() *binlogpb.GrpcLogEntry {
|
||||
st, ok := status.FromError(c.Err)
|
||||
if !ok {
|
||||
grpclogLogger.Info("binarylogging: error in trailer is not a status error")
|
||||
}
|
||||
var (
|
||||
detailsBytes []byte
|
||||
err error
|
||||
)
|
||||
stProto := st.Proto()
|
||||
if stProto != nil && len(stProto.Details) != 0 {
|
||||
detailsBytes, err = proto.Marshal(stProto)
|
||||
if err != nil {
|
||||
grpclogLogger.Infof("binarylogging: failed to marshal status proto: %v", err)
|
||||
}
|
||||
}
|
||||
ret := &binlogpb.GrpcLogEntry{
|
||||
Type: binlogpb.GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER,
|
||||
Payload: &binlogpb.GrpcLogEntry_Trailer{
|
||||
Trailer: &binlogpb.Trailer{
|
||||
Metadata: mdToMetadataProto(c.Trailer),
|
||||
StatusCode: uint32(st.Code()),
|
||||
StatusMessage: st.Message(),
|
||||
StatusDetails: detailsBytes,
|
||||
},
|
||||
},
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
if c.PeerAddr != nil {
|
||||
ret.Peer = addrToProto(c.PeerAddr)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// Cancel configs the binary log entry to be a Cancel entry.
|
||||
type Cancel struct {
|
||||
OnClientSide bool
|
||||
}
|
||||
|
||||
func (c *Cancel) toProto() *binlogpb.GrpcLogEntry {
|
||||
ret := &binlogpb.GrpcLogEntry{
|
||||
Type: binlogpb.GrpcLogEntry_EVENT_TYPE_CANCEL,
|
||||
Payload: nil,
|
||||
}
|
||||
if c.OnClientSide {
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_CLIENT
|
||||
} else {
|
||||
ret.Logger = binlogpb.GrpcLogEntry_LOGGER_SERVER
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// metadataKeyOmit returns whether the metadata entry with this key should be
|
||||
// omitted.
|
||||
func metadataKeyOmit(key string) bool {
|
||||
switch key {
|
||||
case "lb-token", ":path", ":authority", "content-encoding", "content-type", "user-agent", "te":
|
||||
return true
|
||||
case "grpc-trace-bin": // grpc-trace-bin is special because it's visible to users.
|
||||
return false
|
||||
}
|
||||
return strings.HasPrefix(key, "grpc-")
|
||||
}
|
||||
|
||||
func mdToMetadataProto(md metadata.MD) *binlogpb.Metadata {
|
||||
ret := &binlogpb.Metadata{}
|
||||
for k, vv := range md {
|
||||
if metadataKeyOmit(k) {
|
||||
continue
|
||||
}
|
||||
for _, v := range vv {
|
||||
ret.Entry = append(ret.Entry,
|
||||
&binlogpb.MetadataEntry{
|
||||
Key: k,
|
||||
Value: []byte(v),
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func addrToProto(addr net.Addr) *binlogpb.Address {
|
||||
ret := &binlogpb.Address{}
|
||||
switch a := addr.(type) {
|
||||
case *net.TCPAddr:
|
||||
if a.IP.To4() != nil {
|
||||
ret.Type = binlogpb.Address_TYPE_IPV4
|
||||
} else if a.IP.To16() != nil {
|
||||
ret.Type = binlogpb.Address_TYPE_IPV6
|
||||
} else {
|
||||
ret.Type = binlogpb.Address_TYPE_UNKNOWN
|
||||
// Do not set address and port fields.
|
||||
break
|
||||
}
|
||||
ret.Address = a.IP.String()
|
||||
ret.IpPort = uint32(a.Port)
|
||||
case *net.UnixAddr:
|
||||
ret.Type = binlogpb.Address_TYPE_UNIX
|
||||
ret.Address = a.String()
|
||||
default:
|
||||
ret.Type = binlogpb.Address_TYPE_UNKNOWN
|
||||
}
|
||||
return ret
|
||||
}
|
||||
170
vendor/google.golang.org/grpc/internal/binarylog/sink.go
generated
vendored
Normal file
170
vendor/google.golang.org/grpc/internal/binarylog/sink.go
generated
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package binarylog
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
binlogpb "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultSink is the sink where the logs will be written to. It's exported
|
||||
// for the binarylog package to update.
|
||||
DefaultSink Sink = &noopSink{} // TODO(blog): change this default (file in /tmp).
|
||||
)
|
||||
|
||||
// Sink writes log entry into the binary log sink.
|
||||
//
|
||||
// sink is a copy of the exported binarylog.Sink, to avoid circular dependency.
|
||||
type Sink interface {
|
||||
// Write will be called to write the log entry into the sink.
|
||||
//
|
||||
// It should be thread-safe so it can be called in parallel.
|
||||
Write(*binlogpb.GrpcLogEntry) error
|
||||
// Close will be called when the Sink is replaced by a new Sink.
|
||||
Close() error
|
||||
}
|
||||
|
||||
type noopSink struct{}
|
||||
|
||||
func (ns *noopSink) Write(*binlogpb.GrpcLogEntry) error { return nil }
|
||||
func (ns *noopSink) Close() error { return nil }
|
||||
|
||||
// newWriterSink creates a binary log sink with the given writer.
|
||||
//
|
||||
// Write() marshals the proto message and writes it to the given writer. Each
|
||||
// message is prefixed with a 4 byte big endian unsigned integer as the length.
|
||||
//
|
||||
// No buffer is done, Close() doesn't try to close the writer.
|
||||
func newWriterSink(w io.Writer) Sink {
|
||||
return &writerSink{out: w}
|
||||
}
|
||||
|
||||
type writerSink struct {
|
||||
out io.Writer
|
||||
}
|
||||
|
||||
func (ws *writerSink) Write(e *binlogpb.GrpcLogEntry) error {
|
||||
b, err := proto.Marshal(e)
|
||||
if err != nil {
|
||||
grpclogLogger.Errorf("binary logging: failed to marshal proto message: %v", err)
|
||||
return err
|
||||
}
|
||||
hdr := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(hdr, uint32(len(b)))
|
||||
if _, err := ws.out.Write(hdr); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := ws.out.Write(b); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ws *writerSink) Close() error { return nil }
|
||||
|
||||
type bufferedSink struct {
|
||||
mu sync.Mutex
|
||||
closer io.Closer
|
||||
out Sink // out is built on buf.
|
||||
buf *bufio.Writer // buf is kept for flush.
|
||||
flusherStarted bool
|
||||
|
||||
writeTicker *time.Ticker
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
func (fs *bufferedSink) Write(e *binlogpb.GrpcLogEntry) error {
|
||||
fs.mu.Lock()
|
||||
defer fs.mu.Unlock()
|
||||
if !fs.flusherStarted {
|
||||
// Start the write loop when Write is called.
|
||||
fs.startFlushGoroutine()
|
||||
fs.flusherStarted = true
|
||||
}
|
||||
if err := fs.out.Write(e); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
bufFlushDuration = 60 * time.Second
|
||||
)
|
||||
|
||||
func (fs *bufferedSink) startFlushGoroutine() {
|
||||
fs.writeTicker = time.NewTicker(bufFlushDuration)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-fs.done:
|
||||
return
|
||||
case <-fs.writeTicker.C:
|
||||
}
|
||||
fs.mu.Lock()
|
||||
if err := fs.buf.Flush(); err != nil {
|
||||
grpclogLogger.Warningf("failed to flush to Sink: %v", err)
|
||||
}
|
||||
fs.mu.Unlock()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (fs *bufferedSink) Close() error {
|
||||
fs.mu.Lock()
|
||||
defer fs.mu.Unlock()
|
||||
if fs.writeTicker != nil {
|
||||
fs.writeTicker.Stop()
|
||||
}
|
||||
close(fs.done)
|
||||
if err := fs.buf.Flush(); err != nil {
|
||||
grpclogLogger.Warningf("failed to flush to Sink: %v", err)
|
||||
}
|
||||
if err := fs.closer.Close(); err != nil {
|
||||
grpclogLogger.Warningf("failed to close the underlying WriterCloser: %v", err)
|
||||
}
|
||||
if err := fs.out.Close(); err != nil {
|
||||
grpclogLogger.Warningf("failed to close the Sink: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewBufferedSink creates a binary log sink with the given WriteCloser.
|
||||
//
|
||||
// Write() marshals the proto message and writes it to the given writer. Each
|
||||
// message is prefixed with a 4 byte big endian unsigned integer as the length.
|
||||
//
|
||||
// Content is kept in a buffer, and is flushed every 60 seconds.
|
||||
//
|
||||
// Close closes the WriteCloser.
|
||||
func NewBufferedSink(o io.WriteCloser) Sink {
|
||||
bufW := bufio.NewWriter(o)
|
||||
return &bufferedSink{
|
||||
closer: o,
|
||||
out: newWriterSink(bufW),
|
||||
buf: bufW,
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
116
vendor/google.golang.org/grpc/internal/buffer/unbounded.go
generated
vendored
Normal file
116
vendor/google.golang.org/grpc/internal/buffer/unbounded.go
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2019 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package buffer provides an implementation of an unbounded buffer.
|
||||
package buffer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Unbounded is an implementation of an unbounded buffer which does not use
|
||||
// extra goroutines. This is typically used for passing updates from one entity
|
||||
// to another within gRPC.
|
||||
//
|
||||
// All methods on this type are thread-safe and don't block on anything except
|
||||
// the underlying mutex used for synchronization.
|
||||
//
|
||||
// Unbounded supports values of any type to be stored in it by using a channel
|
||||
// of `any`. This means that a call to Put() incurs an extra memory allocation,
|
||||
// and also that users need a type assertion while reading. For performance
|
||||
// critical code paths, using Unbounded is strongly discouraged and defining a
|
||||
// new type specific implementation of this buffer is preferred. See
|
||||
// internal/transport/transport.go for an example of this.
|
||||
type Unbounded struct {
|
||||
c chan any
|
||||
closed bool
|
||||
closing bool
|
||||
mu sync.Mutex
|
||||
backlog []any
|
||||
}
|
||||
|
||||
// NewUnbounded returns a new instance of Unbounded.
|
||||
func NewUnbounded() *Unbounded {
|
||||
return &Unbounded{c: make(chan any, 1)}
|
||||
}
|
||||
|
||||
var errBufferClosed = errors.New("Put called on closed buffer.Unbounded")
|
||||
|
||||
// Put adds t to the unbounded buffer.
|
||||
func (b *Unbounded) Put(t any) error {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if b.closing {
|
||||
return errBufferClosed
|
||||
}
|
||||
if len(b.backlog) == 0 {
|
||||
select {
|
||||
case b.c <- t:
|
||||
return nil
|
||||
default:
|
||||
}
|
||||
}
|
||||
b.backlog = append(b.backlog, t)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Load sends the earliest buffered data, if any, onto the read channel returned
|
||||
// by Get(). Users are expected to call this every time they successfully read a
|
||||
// value from the read channel.
|
||||
func (b *Unbounded) Load() {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if len(b.backlog) > 0 {
|
||||
select {
|
||||
case b.c <- b.backlog[0]:
|
||||
b.backlog[0] = nil
|
||||
b.backlog = b.backlog[1:]
|
||||
default:
|
||||
}
|
||||
} else if b.closing && !b.closed {
|
||||
close(b.c)
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns a read channel on which values added to the buffer, via Put(),
|
||||
// are sent on.
|
||||
//
|
||||
// Upon reading a value from this channel, users are expected to call Load() to
|
||||
// send the next buffered value onto the channel if there is any.
|
||||
//
|
||||
// If the unbounded buffer is closed, the read channel returned by this method
|
||||
// is closed after all data is drained.
|
||||
func (b *Unbounded) Get() <-chan any {
|
||||
return b.c
|
||||
}
|
||||
|
||||
// Close closes the unbounded buffer. No subsequent data may be Put(), and the
|
||||
// channel returned from Get() will be closed after all the data is read and
|
||||
// Load() is called for the final time.
|
||||
func (b *Unbounded) Close() {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if b.closing {
|
||||
return
|
||||
}
|
||||
b.closing = true
|
||||
if len(b.backlog) == 0 {
|
||||
b.closed = true
|
||||
close(b.c)
|
||||
}
|
||||
}
|
||||
255
vendor/google.golang.org/grpc/internal/channelz/channel.go
generated
vendored
Normal file
255
vendor/google.golang.org/grpc/internal/channelz/channel.go
generated
vendored
Normal file
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2024 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package channelz
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
|
||||
"google.golang.org/grpc/connectivity"
|
||||
)
|
||||
|
||||
// Channel represents a channel within channelz, which includes metrics and
|
||||
// internal channelz data, such as channelz id, child list, etc.
|
||||
type Channel struct {
|
||||
Entity
|
||||
// ID is the channelz id of this channel.
|
||||
ID int64
|
||||
// RefName is the human readable reference string of this channel.
|
||||
RefName string
|
||||
|
||||
closeCalled bool
|
||||
nestedChans map[int64]string
|
||||
subChans map[int64]string
|
||||
Parent *Channel
|
||||
trace *ChannelTrace
|
||||
// traceRefCount is the number of trace events that reference this channel.
|
||||
// Non-zero traceRefCount means the trace of this channel cannot be deleted.
|
||||
traceRefCount int32
|
||||
|
||||
ChannelMetrics ChannelMetrics
|
||||
}
|
||||
|
||||
// Implemented to make Channel implement the Identifier interface used for
|
||||
// nesting.
|
||||
func (c *Channel) channelzIdentifier() {}
|
||||
|
||||
func (c *Channel) String() string {
|
||||
if c.Parent == nil {
|
||||
return fmt.Sprintf("Channel #%d", c.ID)
|
||||
}
|
||||
return fmt.Sprintf("%s Channel #%d", c.Parent, c.ID)
|
||||
}
|
||||
|
||||
func (c *Channel) id() int64 {
|
||||
return c.ID
|
||||
}
|
||||
|
||||
func (c *Channel) SubChans() map[int64]string {
|
||||
db.mu.RLock()
|
||||
defer db.mu.RUnlock()
|
||||
return copyMap(c.subChans)
|
||||
}
|
||||
|
||||
func (c *Channel) NestedChans() map[int64]string {
|
||||
db.mu.RLock()
|
||||
defer db.mu.RUnlock()
|
||||
return copyMap(c.nestedChans)
|
||||
}
|
||||
|
||||
func (c *Channel) Trace() *ChannelTrace {
|
||||
db.mu.RLock()
|
||||
defer db.mu.RUnlock()
|
||||
return c.trace.copy()
|
||||
}
|
||||
|
||||
type ChannelMetrics struct {
|
||||
// The current connectivity state of the channel.
|
||||
State atomic.Pointer[connectivity.State]
|
||||
// The target this channel originally tried to connect to. May be absent
|
||||
Target atomic.Pointer[string]
|
||||
// The number of calls started on the channel.
|
||||
CallsStarted atomic.Int64
|
||||
// The number of calls that have completed with an OK status.
|
||||
CallsSucceeded atomic.Int64
|
||||
// The number of calls that have a completed with a non-OK status.
|
||||
CallsFailed atomic.Int64
|
||||
// The last time a call was started on the channel.
|
||||
LastCallStartedTimestamp atomic.Int64
|
||||
}
|
||||
|
||||
// CopyFrom copies the metrics in o to c. For testing only.
|
||||
func (c *ChannelMetrics) CopyFrom(o *ChannelMetrics) {
|
||||
c.State.Store(o.State.Load())
|
||||
c.Target.Store(o.Target.Load())
|
||||
c.CallsStarted.Store(o.CallsStarted.Load())
|
||||
c.CallsSucceeded.Store(o.CallsSucceeded.Load())
|
||||
c.CallsFailed.Store(o.CallsFailed.Load())
|
||||
c.LastCallStartedTimestamp.Store(o.LastCallStartedTimestamp.Load())
|
||||
}
|
||||
|
||||
// Equal returns true iff the metrics of c are the same as the metrics of o.
|
||||
// For testing only.
|
||||
func (c *ChannelMetrics) Equal(o any) bool {
|
||||
oc, ok := o.(*ChannelMetrics)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if (c.State.Load() == nil) != (oc.State.Load() == nil) {
|
||||
return false
|
||||
}
|
||||
if c.State.Load() != nil && *c.State.Load() != *oc.State.Load() {
|
||||
return false
|
||||
}
|
||||
if (c.Target.Load() == nil) != (oc.Target.Load() == nil) {
|
||||
return false
|
||||
}
|
||||
if c.Target.Load() != nil && *c.Target.Load() != *oc.Target.Load() {
|
||||
return false
|
||||
}
|
||||
return c.CallsStarted.Load() == oc.CallsStarted.Load() &&
|
||||
c.CallsFailed.Load() == oc.CallsFailed.Load() &&
|
||||
c.CallsSucceeded.Load() == oc.CallsSucceeded.Load() &&
|
||||
c.LastCallStartedTimestamp.Load() == oc.LastCallStartedTimestamp.Load()
|
||||
}
|
||||
|
||||
func strFromPointer(s *string) string {
|
||||
if s == nil {
|
||||
return ""
|
||||
}
|
||||
return *s
|
||||
}
|
||||
|
||||
func (c *ChannelMetrics) String() string {
|
||||
return fmt.Sprintf("State: %v, Target: %s, CallsStarted: %v, CallsSucceeded: %v, CallsFailed: %v, LastCallStartedTimestamp: %v",
|
||||
c.State.Load(), strFromPointer(c.Target.Load()), c.CallsStarted.Load(), c.CallsSucceeded.Load(), c.CallsFailed.Load(), c.LastCallStartedTimestamp.Load(),
|
||||
)
|
||||
}
|
||||
|
||||
func NewChannelMetricForTesting(state connectivity.State, target string, started, succeeded, failed, timestamp int64) *ChannelMetrics {
|
||||
c := &ChannelMetrics{}
|
||||
c.State.Store(&state)
|
||||
c.Target.Store(&target)
|
||||
c.CallsStarted.Store(started)
|
||||
c.CallsSucceeded.Store(succeeded)
|
||||
c.CallsFailed.Store(failed)
|
||||
c.LastCallStartedTimestamp.Store(timestamp)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Channel) addChild(id int64, e entry) {
|
||||
switch v := e.(type) {
|
||||
case *SubChannel:
|
||||
c.subChans[id] = v.RefName
|
||||
case *Channel:
|
||||
c.nestedChans[id] = v.RefName
|
||||
default:
|
||||
logger.Errorf("cannot add a child (id = %d) of type %T to a channel", id, e)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Channel) deleteChild(id int64) {
|
||||
delete(c.subChans, id)
|
||||
delete(c.nestedChans, id)
|
||||
c.deleteSelfIfReady()
|
||||
}
|
||||
|
||||
func (c *Channel) triggerDelete() {
|
||||
c.closeCalled = true
|
||||
c.deleteSelfIfReady()
|
||||
}
|
||||
|
||||
func (c *Channel) getParentID() int64 {
|
||||
if c.Parent == nil {
|
||||
return -1
|
||||
}
|
||||
return c.Parent.ID
|
||||
}
|
||||
|
||||
// deleteSelfFromTree tries to delete the channel from the channelz entry relation tree, which means
|
||||
// deleting the channel reference from its parent's child list.
|
||||
//
|
||||
// In order for a channel to be deleted from the tree, it must meet the criteria that, removal of the
|
||||
// corresponding grpc object has been invoked, and the channel does not have any children left.
|
||||
//
|
||||
// The returned boolean value indicates whether the channel has been successfully deleted from tree.
|
||||
func (c *Channel) deleteSelfFromTree() (deleted bool) {
|
||||
if !c.closeCalled || len(c.subChans)+len(c.nestedChans) != 0 {
|
||||
return false
|
||||
}
|
||||
// not top channel
|
||||
if c.Parent != nil {
|
||||
c.Parent.deleteChild(c.ID)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// deleteSelfFromMap checks whether it is valid to delete the channel from the map, which means
|
||||
// deleting the channel from channelz's tracking entirely. Users can no longer use id to query the
|
||||
// channel, and its memory will be garbage collected.
|
||||
//
|
||||
// The trace reference count of the channel must be 0 in order to be deleted from the map. This is
|
||||
// specified in the channel tracing gRFC that as long as some other trace has reference to an entity,
|
||||
// the trace of the referenced entity must not be deleted. In order to release the resource allocated
|
||||
// by grpc, the reference to the grpc object is reset to a dummy object.
|
||||
//
|
||||
// deleteSelfFromMap must be called after deleteSelfFromTree returns true.
|
||||
//
|
||||
// It returns a bool to indicate whether the channel can be safely deleted from map.
|
||||
func (c *Channel) deleteSelfFromMap() (delete bool) {
|
||||
return c.getTraceRefCount() == 0
|
||||
}
|
||||
|
||||
// deleteSelfIfReady tries to delete the channel itself from the channelz database.
|
||||
// The delete process includes two steps:
|
||||
// 1. delete the channel from the entry relation tree, i.e. delete the channel reference from its
|
||||
// parent's child list.
|
||||
// 2. delete the channel from the map, i.e. delete the channel entirely from channelz. Lookup by id
|
||||
// will return entry not found error.
|
||||
func (c *Channel) deleteSelfIfReady() {
|
||||
if !c.deleteSelfFromTree() {
|
||||
return
|
||||
}
|
||||
if !c.deleteSelfFromMap() {
|
||||
return
|
||||
}
|
||||
db.deleteEntry(c.ID)
|
||||
c.trace.clear()
|
||||
}
|
||||
|
||||
func (c *Channel) getChannelTrace() *ChannelTrace {
|
||||
return c.trace
|
||||
}
|
||||
|
||||
func (c *Channel) incrTraceRefCount() {
|
||||
atomic.AddInt32(&c.traceRefCount, 1)
|
||||
}
|
||||
|
||||
func (c *Channel) decrTraceRefCount() {
|
||||
atomic.AddInt32(&c.traceRefCount, -1)
|
||||
}
|
||||
|
||||
func (c *Channel) getTraceRefCount() int {
|
||||
i := atomic.LoadInt32(&c.traceRefCount)
|
||||
return int(i)
|
||||
}
|
||||
|
||||
func (c *Channel) getRefName() string {
|
||||
return c.RefName
|
||||
}
|
||||
402
vendor/google.golang.org/grpc/internal/channelz/channelmap.go
generated
vendored
Normal file
402
vendor/google.golang.org/grpc/internal/channelz/channelmap.go
generated
vendored
Normal file
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package channelz
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// entry represents a node in the channelz database.
|
||||
type entry interface {
|
||||
// addChild adds a child e, whose channelz id is id to child list
|
||||
addChild(id int64, e entry)
|
||||
// deleteChild deletes a child with channelz id to be id from child list
|
||||
deleteChild(id int64)
|
||||
// triggerDelete tries to delete self from channelz database. However, if
|
||||
// child list is not empty, then deletion from the database is on hold until
|
||||
// the last child is deleted from database.
|
||||
triggerDelete()
|
||||
// deleteSelfIfReady check whether triggerDelete() has been called before,
|
||||
// and whether child list is now empty. If both conditions are met, then
|
||||
// delete self from database.
|
||||
deleteSelfIfReady()
|
||||
// getParentID returns parent ID of the entry. 0 value parent ID means no parent.
|
||||
getParentID() int64
|
||||
Entity
|
||||
}
|
||||
|
||||
// channelMap is the storage data structure for channelz.
|
||||
//
|
||||
// Methods of channelMap can be divided in two two categories with respect to
|
||||
// locking.
|
||||
//
|
||||
// 1. Methods acquire the global lock.
|
||||
// 2. Methods that can only be called when global lock is held.
|
||||
//
|
||||
// A second type of method need always to be called inside a first type of method.
|
||||
type channelMap struct {
|
||||
mu sync.RWMutex
|
||||
topLevelChannels map[int64]struct{}
|
||||
channels map[int64]*Channel
|
||||
subChannels map[int64]*SubChannel
|
||||
sockets map[int64]*Socket
|
||||
servers map[int64]*Server
|
||||
}
|
||||
|
||||
func newChannelMap() *channelMap {
|
||||
return &channelMap{
|
||||
topLevelChannels: make(map[int64]struct{}),
|
||||
channels: make(map[int64]*Channel),
|
||||
subChannels: make(map[int64]*SubChannel),
|
||||
sockets: make(map[int64]*Socket),
|
||||
servers: make(map[int64]*Server),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *channelMap) addServer(id int64, s *Server) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
s.cm = c
|
||||
c.servers[id] = s
|
||||
}
|
||||
|
||||
func (c *channelMap) addChannel(id int64, cn *Channel, isTopChannel bool, pid int64) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
cn.trace.cm = c
|
||||
c.channels[id] = cn
|
||||
if isTopChannel {
|
||||
c.topLevelChannels[id] = struct{}{}
|
||||
} else if p := c.channels[pid]; p != nil {
|
||||
p.addChild(id, cn)
|
||||
} else {
|
||||
logger.Infof("channel %d references invalid parent ID %d", id, pid)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *channelMap) addSubChannel(id int64, sc *SubChannel, pid int64) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
sc.trace.cm = c
|
||||
c.subChannels[id] = sc
|
||||
if p := c.channels[pid]; p != nil {
|
||||
p.addChild(id, sc)
|
||||
} else {
|
||||
logger.Infof("subchannel %d references invalid parent ID %d", id, pid)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *channelMap) addSocket(s *Socket) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
s.cm = c
|
||||
c.sockets[s.ID] = s
|
||||
if s.Parent == nil {
|
||||
logger.Infof("normal socket %d has no parent", s.ID)
|
||||
}
|
||||
s.Parent.(entry).addChild(s.ID, s)
|
||||
}
|
||||
|
||||
// removeEntry triggers the removal of an entry, which may not indeed delete the
|
||||
// entry, if it has to wait on the deletion of its children and until no other
|
||||
// entity's channel trace references it. It may lead to a chain of entry
|
||||
// deletion. For example, deleting the last socket of a gracefully shutting down
|
||||
// server will lead to the server being also deleted.
|
||||
func (c *channelMap) removeEntry(id int64) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.findEntry(id).triggerDelete()
|
||||
}
|
||||
|
||||
// tracedChannel represents tracing operations which are present on both
|
||||
// channels and subChannels.
|
||||
type tracedChannel interface {
|
||||
getChannelTrace() *ChannelTrace
|
||||
incrTraceRefCount()
|
||||
decrTraceRefCount()
|
||||
getRefName() string
|
||||
}
|
||||
|
||||
// c.mu must be held by the caller
|
||||
func (c *channelMap) decrTraceRefCount(id int64) {
|
||||
e := c.findEntry(id)
|
||||
if v, ok := e.(tracedChannel); ok {
|
||||
v.decrTraceRefCount()
|
||||
e.deleteSelfIfReady()
|
||||
}
|
||||
}
|
||||
|
||||
// c.mu must be held by the caller.
|
||||
func (c *channelMap) findEntry(id int64) entry {
|
||||
if v, ok := c.channels[id]; ok {
|
||||
return v
|
||||
}
|
||||
if v, ok := c.subChannels[id]; ok {
|
||||
return v
|
||||
}
|
||||
if v, ok := c.servers[id]; ok {
|
||||
return v
|
||||
}
|
||||
if v, ok := c.sockets[id]; ok {
|
||||
return v
|
||||
}
|
||||
return &dummyEntry{idNotFound: id}
|
||||
}
|
||||
|
||||
// c.mu must be held by the caller
|
||||
//
|
||||
// deleteEntry deletes an entry from the channelMap. Before calling this method,
|
||||
// caller must check this entry is ready to be deleted, i.e removeEntry() has
|
||||
// been called on it, and no children still exist.
|
||||
func (c *channelMap) deleteEntry(id int64) entry {
|
||||
if v, ok := c.sockets[id]; ok {
|
||||
delete(c.sockets, id)
|
||||
return v
|
||||
}
|
||||
if v, ok := c.subChannels[id]; ok {
|
||||
delete(c.subChannels, id)
|
||||
return v
|
||||
}
|
||||
if v, ok := c.channels[id]; ok {
|
||||
delete(c.channels, id)
|
||||
delete(c.topLevelChannels, id)
|
||||
return v
|
||||
}
|
||||
if v, ok := c.servers[id]; ok {
|
||||
delete(c.servers, id)
|
||||
return v
|
||||
}
|
||||
return &dummyEntry{idNotFound: id}
|
||||
}
|
||||
|
||||
func (c *channelMap) traceEvent(id int64, desc *TraceEvent) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
child := c.findEntry(id)
|
||||
childTC, ok := child.(tracedChannel)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
childTC.getChannelTrace().append(&traceEvent{Desc: desc.Desc, Severity: desc.Severity, Timestamp: time.Now()})
|
||||
if desc.Parent != nil {
|
||||
parent := c.findEntry(child.getParentID())
|
||||
var chanType RefChannelType
|
||||
switch child.(type) {
|
||||
case *Channel:
|
||||
chanType = RefChannel
|
||||
case *SubChannel:
|
||||
chanType = RefSubChannel
|
||||
}
|
||||
if parentTC, ok := parent.(tracedChannel); ok {
|
||||
parentTC.getChannelTrace().append(&traceEvent{
|
||||
Desc: desc.Parent.Desc,
|
||||
Severity: desc.Parent.Severity,
|
||||
Timestamp: time.Now(),
|
||||
RefID: id,
|
||||
RefName: childTC.getRefName(),
|
||||
RefType: chanType,
|
||||
})
|
||||
childTC.incrTraceRefCount()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type int64Slice []int64
|
||||
|
||||
func (s int64Slice) Len() int { return len(s) }
|
||||
func (s int64Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
func (s int64Slice) Less(i, j int) bool { return s[i] < s[j] }
|
||||
|
||||
func copyMap(m map[int64]string) map[int64]string {
|
||||
n := make(map[int64]string)
|
||||
for k, v := range m {
|
||||
n[k] = v
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (c *channelMap) getTopChannels(id int64, maxResults int) ([]*Channel, bool) {
|
||||
if maxResults <= 0 {
|
||||
maxResults = EntriesPerPage
|
||||
}
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
l := int64(len(c.topLevelChannels))
|
||||
ids := make([]int64, 0, l)
|
||||
|
||||
for k := range c.topLevelChannels {
|
||||
ids = append(ids, k)
|
||||
}
|
||||
sort.Sort(int64Slice(ids))
|
||||
idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= id })
|
||||
end := true
|
||||
var t []*Channel
|
||||
for _, v := range ids[idx:] {
|
||||
if len(t) == maxResults {
|
||||
end = false
|
||||
break
|
||||
}
|
||||
if cn, ok := c.channels[v]; ok {
|
||||
t = append(t, cn)
|
||||
}
|
||||
}
|
||||
return t, end
|
||||
}
|
||||
|
||||
func (c *channelMap) getServers(id int64, maxResults int) ([]*Server, bool) {
|
||||
if maxResults <= 0 {
|
||||
maxResults = EntriesPerPage
|
||||
}
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
ids := make([]int64, 0, len(c.servers))
|
||||
for k := range c.servers {
|
||||
ids = append(ids, k)
|
||||
}
|
||||
sort.Sort(int64Slice(ids))
|
||||
idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= id })
|
||||
end := true
|
||||
var s []*Server
|
||||
for _, v := range ids[idx:] {
|
||||
if len(s) == maxResults {
|
||||
end = false
|
||||
break
|
||||
}
|
||||
if svr, ok := c.servers[v]; ok {
|
||||
s = append(s, svr)
|
||||
}
|
||||
}
|
||||
return s, end
|
||||
}
|
||||
|
||||
func (c *channelMap) getServerSockets(id int64, startID int64, maxResults int) ([]*Socket, bool) {
|
||||
if maxResults <= 0 {
|
||||
maxResults = EntriesPerPage
|
||||
}
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
svr, ok := c.servers[id]
|
||||
if !ok {
|
||||
// server with id doesn't exist.
|
||||
return nil, true
|
||||
}
|
||||
svrskts := svr.sockets
|
||||
ids := make([]int64, 0, len(svrskts))
|
||||
sks := make([]*Socket, 0, min(len(svrskts), maxResults))
|
||||
for k := range svrskts {
|
||||
ids = append(ids, k)
|
||||
}
|
||||
sort.Sort(int64Slice(ids))
|
||||
idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= startID })
|
||||
end := true
|
||||
for _, v := range ids[idx:] {
|
||||
if len(sks) == maxResults {
|
||||
end = false
|
||||
break
|
||||
}
|
||||
if ns, ok := c.sockets[v]; ok {
|
||||
sks = append(sks, ns)
|
||||
}
|
||||
}
|
||||
return sks, end
|
||||
}
|
||||
|
||||
func (c *channelMap) getChannel(id int64) *Channel {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
return c.channels[id]
|
||||
}
|
||||
|
||||
func (c *channelMap) getSubChannel(id int64) *SubChannel {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
return c.subChannels[id]
|
||||
}
|
||||
|
||||
func (c *channelMap) getSocket(id int64) *Socket {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
return c.sockets[id]
|
||||
}
|
||||
|
||||
func (c *channelMap) getServer(id int64) *Server {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
return c.servers[id]
|
||||
}
|
||||
|
||||
type dummyEntry struct {
|
||||
// dummyEntry is a fake entry to handle entry not found case.
|
||||
idNotFound int64
|
||||
Entity
|
||||
}
|
||||
|
||||
func (d *dummyEntry) String() string {
|
||||
return fmt.Sprintf("non-existent entity #%d", d.idNotFound)
|
||||
}
|
||||
|
||||
func (d *dummyEntry) ID() int64 { return d.idNotFound }
|
||||
|
||||
func (d *dummyEntry) addChild(id int64, e entry) {
|
||||
// Note: It is possible for a normal program to reach here under race
|
||||
// condition. For example, there could be a race between ClientConn.Close()
|
||||
// info being propagated to addrConn and http2Client. ClientConn.Close()
|
||||
// cancel the context and result in http2Client to error. The error info is
|
||||
// then caught by transport monitor and before addrConn.tearDown() is called
|
||||
// in side ClientConn.Close(). Therefore, the addrConn will create a new
|
||||
// transport. And when registering the new transport in channelz, its parent
|
||||
// addrConn could have already been torn down and deleted from channelz
|
||||
// tracking, and thus reach the code here.
|
||||
logger.Infof("attempt to add child of type %T with id %d to a parent (id=%d) that doesn't currently exist", e, id, d.idNotFound)
|
||||
}
|
||||
|
||||
func (d *dummyEntry) deleteChild(id int64) {
|
||||
// It is possible for a normal program to reach here under race condition.
|
||||
// Refer to the example described in addChild().
|
||||
logger.Infof("attempt to delete child with id %d from a parent (id=%d) that doesn't currently exist", id, d.idNotFound)
|
||||
}
|
||||
|
||||
func (d *dummyEntry) triggerDelete() {
|
||||
logger.Warningf("attempt to delete an entry (id=%d) that doesn't currently exist", d.idNotFound)
|
||||
}
|
||||
|
||||
func (*dummyEntry) deleteSelfIfReady() {
|
||||
// code should not reach here. deleteSelfIfReady is always called on an existing entry.
|
||||
}
|
||||
|
||||
func (*dummyEntry) getParentID() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Entity is implemented by all channelz types.
|
||||
type Entity interface {
|
||||
isEntity()
|
||||
fmt.Stringer
|
||||
id() int64
|
||||
}
|
||||
230
vendor/google.golang.org/grpc/internal/channelz/funcs.go
generated
vendored
Normal file
230
vendor/google.golang.org/grpc/internal/channelz/funcs.go
generated
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package channelz defines internal APIs for enabling channelz service, entry
|
||||
// registration/deletion, and accessing channelz data. It also defines channelz
|
||||
// metric struct formats.
|
||||
package channelz
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/internal"
|
||||
)
|
||||
|
||||
var (
|
||||
// IDGen is the global channelz entity ID generator. It should not be used
|
||||
// outside this package except by tests.
|
||||
IDGen IDGenerator
|
||||
|
||||
db *channelMap = newChannelMap()
|
||||
// EntriesPerPage defines the number of channelz entries to be shown on a web page.
|
||||
EntriesPerPage = 50
|
||||
curState int32
|
||||
)
|
||||
|
||||
// TurnOn turns on channelz data collection.
|
||||
func TurnOn() {
|
||||
atomic.StoreInt32(&curState, 1)
|
||||
}
|
||||
|
||||
func init() {
|
||||
internal.ChannelzTurnOffForTesting = func() {
|
||||
atomic.StoreInt32(&curState, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// IsOn returns whether channelz data collection is on.
|
||||
func IsOn() bool {
|
||||
return atomic.LoadInt32(&curState) == 1
|
||||
}
|
||||
|
||||
// GetTopChannels returns a slice of top channel's ChannelMetric, along with a
|
||||
// boolean indicating whether there's more top channels to be queried for.
|
||||
//
|
||||
// The arg id specifies that only top channel with id at or above it will be
|
||||
// included in the result. The returned slice is up to a length of the arg
|
||||
// maxResults or EntriesPerPage if maxResults is zero, and is sorted in ascending
|
||||
// id order.
|
||||
func GetTopChannels(id int64, maxResults int) ([]*Channel, bool) {
|
||||
return db.getTopChannels(id, maxResults)
|
||||
}
|
||||
|
||||
// GetServers returns a slice of server's ServerMetric, along with a
|
||||
// boolean indicating whether there's more servers to be queried for.
|
||||
//
|
||||
// The arg id specifies that only server with id at or above it will be included
|
||||
// in the result. The returned slice is up to a length of the arg maxResults or
|
||||
// EntriesPerPage if maxResults is zero, and is sorted in ascending id order.
|
||||
func GetServers(id int64, maxResults int) ([]*Server, bool) {
|
||||
return db.getServers(id, maxResults)
|
||||
}
|
||||
|
||||
// GetServerSockets returns a slice of server's (identified by id) normal socket's
|
||||
// SocketMetrics, along with a boolean indicating whether there's more sockets to
|
||||
// be queried for.
|
||||
//
|
||||
// The arg startID specifies that only sockets with id at or above it will be
|
||||
// included in the result. The returned slice is up to a length of the arg maxResults
|
||||
// or EntriesPerPage if maxResults is zero, and is sorted in ascending id order.
|
||||
func GetServerSockets(id int64, startID int64, maxResults int) ([]*Socket, bool) {
|
||||
return db.getServerSockets(id, startID, maxResults)
|
||||
}
|
||||
|
||||
// GetChannel returns the Channel for the channel (identified by id).
|
||||
func GetChannel(id int64) *Channel {
|
||||
return db.getChannel(id)
|
||||
}
|
||||
|
||||
// GetSubChannel returns the SubChannel for the subchannel (identified by id).
|
||||
func GetSubChannel(id int64) *SubChannel {
|
||||
return db.getSubChannel(id)
|
||||
}
|
||||
|
||||
// GetSocket returns the Socket for the socket (identified by id).
|
||||
func GetSocket(id int64) *Socket {
|
||||
return db.getSocket(id)
|
||||
}
|
||||
|
||||
// GetServer returns the ServerMetric for the server (identified by id).
|
||||
func GetServer(id int64) *Server {
|
||||
return db.getServer(id)
|
||||
}
|
||||
|
||||
// RegisterChannel registers the given channel c in the channelz database with
|
||||
// target as its target and reference name, and adds it to the child list of its
|
||||
// parent. parent == nil means no parent.
|
||||
//
|
||||
// Returns a unique channelz identifier assigned to this channel.
|
||||
//
|
||||
// If channelz is not turned ON, the channelz database is not mutated.
|
||||
func RegisterChannel(parent *Channel, target string) *Channel {
|
||||
id := IDGen.genID()
|
||||
|
||||
if !IsOn() {
|
||||
return &Channel{ID: id}
|
||||
}
|
||||
|
||||
isTopChannel := parent == nil
|
||||
|
||||
cn := &Channel{
|
||||
ID: id,
|
||||
RefName: target,
|
||||
nestedChans: make(map[int64]string),
|
||||
subChans: make(map[int64]string),
|
||||
Parent: parent,
|
||||
trace: &ChannelTrace{CreationTime: time.Now(), Events: make([]*traceEvent, 0, getMaxTraceEntry())},
|
||||
}
|
||||
cn.ChannelMetrics.Target.Store(&target)
|
||||
db.addChannel(id, cn, isTopChannel, cn.getParentID())
|
||||
return cn
|
||||
}
|
||||
|
||||
// RegisterSubChannel registers the given subChannel c in the channelz database
|
||||
// with ref as its reference name, and adds it to the child list of its parent
|
||||
// (identified by pid).
|
||||
//
|
||||
// Returns a unique channelz identifier assigned to this subChannel.
|
||||
//
|
||||
// If channelz is not turned ON, the channelz database is not mutated.
|
||||
func RegisterSubChannel(parent *Channel, ref string) *SubChannel {
|
||||
id := IDGen.genID()
|
||||
sc := &SubChannel{
|
||||
ID: id,
|
||||
RefName: ref,
|
||||
parent: parent,
|
||||
}
|
||||
|
||||
if !IsOn() {
|
||||
return sc
|
||||
}
|
||||
|
||||
sc.sockets = make(map[int64]string)
|
||||
sc.trace = &ChannelTrace{CreationTime: time.Now(), Events: make([]*traceEvent, 0, getMaxTraceEntry())}
|
||||
db.addSubChannel(id, sc, parent.ID)
|
||||
return sc
|
||||
}
|
||||
|
||||
// RegisterServer registers the given server s in channelz database. It returns
|
||||
// the unique channelz tracking id assigned to this server.
|
||||
//
|
||||
// If channelz is not turned ON, the channelz database is not mutated.
|
||||
func RegisterServer(ref string) *Server {
|
||||
id := IDGen.genID()
|
||||
if !IsOn() {
|
||||
return &Server{ID: id}
|
||||
}
|
||||
|
||||
svr := &Server{
|
||||
RefName: ref,
|
||||
sockets: make(map[int64]string),
|
||||
listenSockets: make(map[int64]string),
|
||||
ID: id,
|
||||
}
|
||||
db.addServer(id, svr)
|
||||
return svr
|
||||
}
|
||||
|
||||
// RegisterSocket registers the given normal socket s in channelz database
|
||||
// with ref as its reference name, and adds it to the child list of its parent
|
||||
// (identified by skt.Parent, which must be set). It returns the unique channelz
|
||||
// tracking id assigned to this normal socket.
|
||||
//
|
||||
// If channelz is not turned ON, the channelz database is not mutated.
|
||||
func RegisterSocket(skt *Socket) *Socket {
|
||||
skt.ID = IDGen.genID()
|
||||
if IsOn() {
|
||||
db.addSocket(skt)
|
||||
}
|
||||
return skt
|
||||
}
|
||||
|
||||
// RemoveEntry removes an entry with unique channelz tracking id to be id from
|
||||
// channelz database.
|
||||
//
|
||||
// If channelz is not turned ON, this function is a no-op.
|
||||
func RemoveEntry(id int64) {
|
||||
if !IsOn() {
|
||||
return
|
||||
}
|
||||
db.removeEntry(id)
|
||||
}
|
||||
|
||||
// IDGenerator is an incrementing atomic that tracks IDs for channelz entities.
|
||||
type IDGenerator struct {
|
||||
id int64
|
||||
}
|
||||
|
||||
// Reset resets the generated ID back to zero. Should only be used at
|
||||
// initialization or by tests sensitive to the ID number.
|
||||
func (i *IDGenerator) Reset() {
|
||||
atomic.StoreInt64(&i.id, 0)
|
||||
}
|
||||
|
||||
func (i *IDGenerator) genID() int64 {
|
||||
return atomic.AddInt64(&i.id, 1)
|
||||
}
|
||||
|
||||
// Identifier is an opaque channelz identifier used to expose channelz symbols
|
||||
// outside of grpc. Currently only implemented by Channel since no other
|
||||
// types require exposure outside grpc.
|
||||
type Identifier interface {
|
||||
Entity
|
||||
channelzIdentifier()
|
||||
}
|
||||
75
vendor/google.golang.org/grpc/internal/channelz/logging.go
generated
vendored
Normal file
75
vendor/google.golang.org/grpc/internal/channelz/logging.go
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package channelz
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
var logger = grpclog.Component("channelz")
|
||||
|
||||
// Info logs and adds a trace event if channelz is on.
|
||||
func Info(l grpclog.DepthLoggerV2, e Entity, args ...any) {
|
||||
AddTraceEvent(l, e, 1, &TraceEvent{
|
||||
Desc: fmt.Sprint(args...),
|
||||
Severity: CtInfo,
|
||||
})
|
||||
}
|
||||
|
||||
// Infof logs and adds a trace event if channelz is on.
|
||||
func Infof(l grpclog.DepthLoggerV2, e Entity, format string, args ...any) {
|
||||
AddTraceEvent(l, e, 1, &TraceEvent{
|
||||
Desc: fmt.Sprintf(format, args...),
|
||||
Severity: CtInfo,
|
||||
})
|
||||
}
|
||||
|
||||
// Warning logs and adds a trace event if channelz is on.
|
||||
func Warning(l grpclog.DepthLoggerV2, e Entity, args ...any) {
|
||||
AddTraceEvent(l, e, 1, &TraceEvent{
|
||||
Desc: fmt.Sprint(args...),
|
||||
Severity: CtWarning,
|
||||
})
|
||||
}
|
||||
|
||||
// Warningf logs and adds a trace event if channelz is on.
|
||||
func Warningf(l grpclog.DepthLoggerV2, e Entity, format string, args ...any) {
|
||||
AddTraceEvent(l, e, 1, &TraceEvent{
|
||||
Desc: fmt.Sprintf(format, args...),
|
||||
Severity: CtWarning,
|
||||
})
|
||||
}
|
||||
|
||||
// Error logs and adds a trace event if channelz is on.
|
||||
func Error(l grpclog.DepthLoggerV2, e Entity, args ...any) {
|
||||
AddTraceEvent(l, e, 1, &TraceEvent{
|
||||
Desc: fmt.Sprint(args...),
|
||||
Severity: CtError,
|
||||
})
|
||||
}
|
||||
|
||||
// Errorf logs and adds a trace event if channelz is on.
|
||||
func Errorf(l grpclog.DepthLoggerV2, e Entity, format string, args ...any) {
|
||||
AddTraceEvent(l, e, 1, &TraceEvent{
|
||||
Desc: fmt.Sprintf(format, args...),
|
||||
Severity: CtError,
|
||||
})
|
||||
}
|
||||
119
vendor/google.golang.org/grpc/internal/channelz/server.go
generated
vendored
Normal file
119
vendor/google.golang.org/grpc/internal/channelz/server.go
generated
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2024 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package channelz
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Server is the channelz representation of a server.
|
||||
type Server struct {
|
||||
Entity
|
||||
ID int64
|
||||
RefName string
|
||||
|
||||
ServerMetrics ServerMetrics
|
||||
|
||||
closeCalled bool
|
||||
sockets map[int64]string
|
||||
listenSockets map[int64]string
|
||||
cm *channelMap
|
||||
}
|
||||
|
||||
// ServerMetrics defines a struct containing metrics for servers.
|
||||
type ServerMetrics struct {
|
||||
// The number of incoming calls started on the server.
|
||||
CallsStarted atomic.Int64
|
||||
// The number of incoming calls that have completed with an OK status.
|
||||
CallsSucceeded atomic.Int64
|
||||
// The number of incoming calls that have a completed with a non-OK status.
|
||||
CallsFailed atomic.Int64
|
||||
// The last time a call was started on the server.
|
||||
LastCallStartedTimestamp atomic.Int64
|
||||
}
|
||||
|
||||
// NewServerMetricsForTesting returns an initialized ServerMetrics.
|
||||
func NewServerMetricsForTesting(started, succeeded, failed, timestamp int64) *ServerMetrics {
|
||||
sm := &ServerMetrics{}
|
||||
sm.CallsStarted.Store(started)
|
||||
sm.CallsSucceeded.Store(succeeded)
|
||||
sm.CallsFailed.Store(failed)
|
||||
sm.LastCallStartedTimestamp.Store(timestamp)
|
||||
return sm
|
||||
}
|
||||
|
||||
func (sm *ServerMetrics) CopyFrom(o *ServerMetrics) {
|
||||
sm.CallsStarted.Store(o.CallsStarted.Load())
|
||||
sm.CallsSucceeded.Store(o.CallsSucceeded.Load())
|
||||
sm.CallsFailed.Store(o.CallsFailed.Load())
|
||||
sm.LastCallStartedTimestamp.Store(o.LastCallStartedTimestamp.Load())
|
||||
}
|
||||
|
||||
// ListenSockets returns the listening sockets for s.
|
||||
func (s *Server) ListenSockets() map[int64]string {
|
||||
db.mu.RLock()
|
||||
defer db.mu.RUnlock()
|
||||
return copyMap(s.listenSockets)
|
||||
}
|
||||
|
||||
// String returns a printable description of s.
|
||||
func (s *Server) String() string {
|
||||
return fmt.Sprintf("Server #%d", s.ID)
|
||||
}
|
||||
|
||||
func (s *Server) id() int64 {
|
||||
return s.ID
|
||||
}
|
||||
|
||||
func (s *Server) addChild(id int64, e entry) {
|
||||
switch v := e.(type) {
|
||||
case *Socket:
|
||||
switch v.SocketType {
|
||||
case SocketTypeNormal:
|
||||
s.sockets[id] = v.RefName
|
||||
case SocketTypeListen:
|
||||
s.listenSockets[id] = v.RefName
|
||||
}
|
||||
default:
|
||||
logger.Errorf("cannot add a child (id = %d) of type %T to a server", id, e)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) deleteChild(id int64) {
|
||||
delete(s.sockets, id)
|
||||
delete(s.listenSockets, id)
|
||||
s.deleteSelfIfReady()
|
||||
}
|
||||
|
||||
func (s *Server) triggerDelete() {
|
||||
s.closeCalled = true
|
||||
s.deleteSelfIfReady()
|
||||
}
|
||||
|
||||
func (s *Server) deleteSelfIfReady() {
|
||||
if !s.closeCalled || len(s.sockets)+len(s.listenSockets) != 0 {
|
||||
return
|
||||
}
|
||||
s.cm.deleteEntry(s.ID)
|
||||
}
|
||||
|
||||
func (s *Server) getParentID() int64 {
|
||||
return 0
|
||||
}
|
||||
130
vendor/google.golang.org/grpc/internal/channelz/socket.go
generated
vendored
Normal file
130
vendor/google.golang.org/grpc/internal/channelz/socket.go
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2024 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package channelz
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sync/atomic"
|
||||
|
||||
"google.golang.org/grpc/credentials"
|
||||
)
|
||||
|
||||
// SocketMetrics defines the struct that the implementor of Socket interface
|
||||
// should return from ChannelzMetric().
|
||||
type SocketMetrics struct {
|
||||
// The number of streams that have been started.
|
||||
StreamsStarted atomic.Int64
|
||||
// The number of streams that have ended successfully:
|
||||
// On client side, receiving frame with eos bit set.
|
||||
// On server side, sending frame with eos bit set.
|
||||
StreamsSucceeded atomic.Int64
|
||||
// The number of streams that have ended unsuccessfully:
|
||||
// On client side, termination without receiving frame with eos bit set.
|
||||
// On server side, termination without sending frame with eos bit set.
|
||||
StreamsFailed atomic.Int64
|
||||
// The number of messages successfully sent on this socket.
|
||||
MessagesSent atomic.Int64
|
||||
MessagesReceived atomic.Int64
|
||||
// The number of keep alives sent. This is typically implemented with HTTP/2
|
||||
// ping messages.
|
||||
KeepAlivesSent atomic.Int64
|
||||
// The last time a stream was created by this endpoint. Usually unset for
|
||||
// servers.
|
||||
LastLocalStreamCreatedTimestamp atomic.Int64
|
||||
// The last time a stream was created by the remote endpoint. Usually unset
|
||||
// for clients.
|
||||
LastRemoteStreamCreatedTimestamp atomic.Int64
|
||||
// The last time a message was sent by this endpoint.
|
||||
LastMessageSentTimestamp atomic.Int64
|
||||
// The last time a message was received by this endpoint.
|
||||
LastMessageReceivedTimestamp atomic.Int64
|
||||
}
|
||||
|
||||
// EphemeralSocketMetrics are metrics that change rapidly and are tracked
|
||||
// outside of channelz.
|
||||
type EphemeralSocketMetrics struct {
|
||||
// The amount of window, granted to the local endpoint by the remote endpoint.
|
||||
// This may be slightly out of date due to network latency. This does NOT
|
||||
// include stream level or TCP level flow control info.
|
||||
LocalFlowControlWindow int64
|
||||
// The amount of window, granted to the remote endpoint by the local endpoint.
|
||||
// This may be slightly out of date due to network latency. This does NOT
|
||||
// include stream level or TCP level flow control info.
|
||||
RemoteFlowControlWindow int64
|
||||
}
|
||||
|
||||
type SocketType string
|
||||
|
||||
const (
|
||||
SocketTypeNormal = "NormalSocket"
|
||||
SocketTypeListen = "ListenSocket"
|
||||
)
|
||||
|
||||
type Socket struct {
|
||||
Entity
|
||||
SocketType SocketType
|
||||
ID int64
|
||||
Parent Entity
|
||||
cm *channelMap
|
||||
SocketMetrics SocketMetrics
|
||||
EphemeralMetrics func() *EphemeralSocketMetrics
|
||||
|
||||
RefName string
|
||||
// The locally bound address. Immutable.
|
||||
LocalAddr net.Addr
|
||||
// The remote bound address. May be absent. Immutable.
|
||||
RemoteAddr net.Addr
|
||||
// Optional, represents the name of the remote endpoint, if different than
|
||||
// the original target name. Immutable.
|
||||
RemoteName string
|
||||
// Immutable.
|
||||
SocketOptions *SocketOptionData
|
||||
// Immutable.
|
||||
Security credentials.ChannelzSecurityValue
|
||||
}
|
||||
|
||||
func (ls *Socket) String() string {
|
||||
return fmt.Sprintf("%s %s #%d", ls.Parent, ls.SocketType, ls.ID)
|
||||
}
|
||||
|
||||
func (ls *Socket) id() int64 {
|
||||
return ls.ID
|
||||
}
|
||||
|
||||
func (ls *Socket) addChild(id int64, e entry) {
|
||||
logger.Errorf("cannot add a child (id = %d) of type %T to a listen socket", id, e)
|
||||
}
|
||||
|
||||
func (ls *Socket) deleteChild(id int64) {
|
||||
logger.Errorf("cannot delete a child (id = %d) from a listen socket", id)
|
||||
}
|
||||
|
||||
func (ls *Socket) triggerDelete() {
|
||||
ls.cm.deleteEntry(ls.ID)
|
||||
ls.Parent.(entry).deleteChild(ls.ID)
|
||||
}
|
||||
|
||||
func (ls *Socket) deleteSelfIfReady() {
|
||||
logger.Errorf("cannot call deleteSelfIfReady on a listen socket")
|
||||
}
|
||||
|
||||
func (ls *Socket) getParentID() int64 {
|
||||
return ls.Parent.id()
|
||||
}
|
||||
151
vendor/google.golang.org/grpc/internal/channelz/subchannel.go
generated
vendored
Normal file
151
vendor/google.golang.org/grpc/internal/channelz/subchannel.go
generated
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2024 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package channelz
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// SubChannel is the channelz representation of a subchannel.
|
||||
type SubChannel struct {
|
||||
Entity
|
||||
// ID is the channelz id of this subchannel.
|
||||
ID int64
|
||||
// RefName is the human readable reference string of this subchannel.
|
||||
RefName string
|
||||
closeCalled bool
|
||||
sockets map[int64]string
|
||||
parent *Channel
|
||||
trace *ChannelTrace
|
||||
traceRefCount int32
|
||||
|
||||
ChannelMetrics ChannelMetrics
|
||||
}
|
||||
|
||||
func (sc *SubChannel) String() string {
|
||||
return fmt.Sprintf("%s SubChannel #%d", sc.parent, sc.ID)
|
||||
}
|
||||
|
||||
func (sc *SubChannel) id() int64 {
|
||||
return sc.ID
|
||||
}
|
||||
|
||||
func (sc *SubChannel) Sockets() map[int64]string {
|
||||
db.mu.RLock()
|
||||
defer db.mu.RUnlock()
|
||||
return copyMap(sc.sockets)
|
||||
}
|
||||
|
||||
func (sc *SubChannel) Trace() *ChannelTrace {
|
||||
db.mu.RLock()
|
||||
defer db.mu.RUnlock()
|
||||
return sc.trace.copy()
|
||||
}
|
||||
|
||||
func (sc *SubChannel) addChild(id int64, e entry) {
|
||||
if v, ok := e.(*Socket); ok && v.SocketType == SocketTypeNormal {
|
||||
sc.sockets[id] = v.RefName
|
||||
} else {
|
||||
logger.Errorf("cannot add a child (id = %d) of type %T to a subChannel", id, e)
|
||||
}
|
||||
}
|
||||
|
||||
func (sc *SubChannel) deleteChild(id int64) {
|
||||
delete(sc.sockets, id)
|
||||
sc.deleteSelfIfReady()
|
||||
}
|
||||
|
||||
func (sc *SubChannel) triggerDelete() {
|
||||
sc.closeCalled = true
|
||||
sc.deleteSelfIfReady()
|
||||
}
|
||||
|
||||
func (sc *SubChannel) getParentID() int64 {
|
||||
return sc.parent.ID
|
||||
}
|
||||
|
||||
// deleteSelfFromTree tries to delete the subchannel from the channelz entry relation tree, which
|
||||
// means deleting the subchannel reference from its parent's child list.
|
||||
//
|
||||
// In order for a subchannel to be deleted from the tree, it must meet the criteria that, removal of
|
||||
// the corresponding grpc object has been invoked, and the subchannel does not have any children left.
|
||||
//
|
||||
// The returned boolean value indicates whether the channel has been successfully deleted from tree.
|
||||
func (sc *SubChannel) deleteSelfFromTree() (deleted bool) {
|
||||
if !sc.closeCalled || len(sc.sockets) != 0 {
|
||||
return false
|
||||
}
|
||||
sc.parent.deleteChild(sc.ID)
|
||||
return true
|
||||
}
|
||||
|
||||
// deleteSelfFromMap checks whether it is valid to delete the subchannel from the map, which means
|
||||
// deleting the subchannel from channelz's tracking entirely. Users can no longer use id to query
|
||||
// the subchannel, and its memory will be garbage collected.
|
||||
//
|
||||
// The trace reference count of the subchannel must be 0 in order to be deleted from the map. This is
|
||||
// specified in the channel tracing gRFC that as long as some other trace has reference to an entity,
|
||||
// the trace of the referenced entity must not be deleted. In order to release the resource allocated
|
||||
// by grpc, the reference to the grpc object is reset to a dummy object.
|
||||
//
|
||||
// deleteSelfFromMap must be called after deleteSelfFromTree returns true.
|
||||
//
|
||||
// It returns a bool to indicate whether the channel can be safely deleted from map.
|
||||
func (sc *SubChannel) deleteSelfFromMap() (delete bool) {
|
||||
return sc.getTraceRefCount() == 0
|
||||
}
|
||||
|
||||
// deleteSelfIfReady tries to delete the subchannel itself from the channelz database.
|
||||
// The delete process includes two steps:
|
||||
// 1. delete the subchannel from the entry relation tree, i.e. delete the subchannel reference from
|
||||
// its parent's child list.
|
||||
// 2. delete the subchannel from the map, i.e. delete the subchannel entirely from channelz. Lookup
|
||||
// by id will return entry not found error.
|
||||
func (sc *SubChannel) deleteSelfIfReady() {
|
||||
if !sc.deleteSelfFromTree() {
|
||||
return
|
||||
}
|
||||
if !sc.deleteSelfFromMap() {
|
||||
return
|
||||
}
|
||||
db.deleteEntry(sc.ID)
|
||||
sc.trace.clear()
|
||||
}
|
||||
|
||||
func (sc *SubChannel) getChannelTrace() *ChannelTrace {
|
||||
return sc.trace
|
||||
}
|
||||
|
||||
func (sc *SubChannel) incrTraceRefCount() {
|
||||
atomic.AddInt32(&sc.traceRefCount, 1)
|
||||
}
|
||||
|
||||
func (sc *SubChannel) decrTraceRefCount() {
|
||||
atomic.AddInt32(&sc.traceRefCount, -1)
|
||||
}
|
||||
|
||||
func (sc *SubChannel) getTraceRefCount() int {
|
||||
i := atomic.LoadInt32(&sc.traceRefCount)
|
||||
return int(i)
|
||||
}
|
||||
|
||||
func (sc *SubChannel) getRefName() string {
|
||||
return sc.RefName
|
||||
}
|
||||
65
vendor/google.golang.org/grpc/internal/channelz/syscall_linux.go
generated
vendored
Normal file
65
vendor/google.golang.org/grpc/internal/channelz/syscall_linux.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package channelz
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// SocketOptionData defines the struct to hold socket option data, and related
|
||||
// getter function to obtain info from fd.
|
||||
type SocketOptionData struct {
|
||||
Linger *unix.Linger
|
||||
RecvTimeout *unix.Timeval
|
||||
SendTimeout *unix.Timeval
|
||||
TCPInfo *unix.TCPInfo
|
||||
}
|
||||
|
||||
// Getsockopt defines the function to get socket options requested by channelz.
|
||||
// It is to be passed to syscall.RawConn.Control().
|
||||
func (s *SocketOptionData) Getsockopt(fd uintptr) {
|
||||
if v, err := unix.GetsockoptLinger(int(fd), syscall.SOL_SOCKET, syscall.SO_LINGER); err == nil {
|
||||
s.Linger = v
|
||||
}
|
||||
if v, err := unix.GetsockoptTimeval(int(fd), syscall.SOL_SOCKET, syscall.SO_RCVTIMEO); err == nil {
|
||||
s.RecvTimeout = v
|
||||
}
|
||||
if v, err := unix.GetsockoptTimeval(int(fd), syscall.SOL_SOCKET, syscall.SO_SNDTIMEO); err == nil {
|
||||
s.SendTimeout = v
|
||||
}
|
||||
if v, err := unix.GetsockoptTCPInfo(int(fd), syscall.SOL_TCP, syscall.TCP_INFO); err == nil {
|
||||
s.TCPInfo = v
|
||||
}
|
||||
}
|
||||
|
||||
// GetSocketOption gets the socket option info of the conn.
|
||||
func GetSocketOption(socket any) *SocketOptionData {
|
||||
c, ok := socket.(syscall.Conn)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
data := &SocketOptionData{}
|
||||
if rawConn, err := c.SyscallConn(); err == nil {
|
||||
rawConn.Control(data.Getsockopt)
|
||||
return data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
47
vendor/google.golang.org/grpc/internal/channelz/syscall_nonlinux.go
generated
vendored
Normal file
47
vendor/google.golang.org/grpc/internal/channelz/syscall_nonlinux.go
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
//go:build !linux
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package channelz
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var once sync.Once
|
||||
|
||||
// SocketOptionData defines the struct to hold socket option data, and related
|
||||
// getter function to obtain info from fd.
|
||||
// Windows OS doesn't support Socket Option
|
||||
type SocketOptionData struct {
|
||||
}
|
||||
|
||||
// Getsockopt defines the function to get socket options requested by channelz.
|
||||
// It is to be passed to syscall.RawConn.Control().
|
||||
// Windows OS doesn't support Socket Option
|
||||
func (s *SocketOptionData) Getsockopt(fd uintptr) {
|
||||
once.Do(func() {
|
||||
logger.Warning("Channelz: socket options are not supported on non-linux environments")
|
||||
})
|
||||
}
|
||||
|
||||
// GetSocketOption gets the socket option info of the conn.
|
||||
func GetSocketOption(c any) *SocketOptionData {
|
||||
return nil
|
||||
}
|
||||
204
vendor/google.golang.org/grpc/internal/channelz/trace.go
generated
vendored
Normal file
204
vendor/google.golang.org/grpc/internal/channelz/trace.go
generated
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package channelz
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultMaxTraceEntry int32 = 30
|
||||
)
|
||||
|
||||
var maxTraceEntry = defaultMaxTraceEntry
|
||||
|
||||
// SetMaxTraceEntry sets maximum number of trace entries per entity (i.e.
|
||||
// channel/subchannel). Setting it to 0 will disable channel tracing.
|
||||
func SetMaxTraceEntry(i int32) {
|
||||
atomic.StoreInt32(&maxTraceEntry, i)
|
||||
}
|
||||
|
||||
// ResetMaxTraceEntryToDefault resets the maximum number of trace entries per
|
||||
// entity to default.
|
||||
func ResetMaxTraceEntryToDefault() {
|
||||
atomic.StoreInt32(&maxTraceEntry, defaultMaxTraceEntry)
|
||||
}
|
||||
|
||||
func getMaxTraceEntry() int {
|
||||
i := atomic.LoadInt32(&maxTraceEntry)
|
||||
return int(i)
|
||||
}
|
||||
|
||||
// traceEvent is an internal representation of a single trace event
|
||||
type traceEvent struct {
|
||||
// Desc is a simple description of the trace event.
|
||||
Desc string
|
||||
// Severity states the severity of this trace event.
|
||||
Severity Severity
|
||||
// Timestamp is the event time.
|
||||
Timestamp time.Time
|
||||
// RefID is the id of the entity that gets referenced in the event. RefID is 0 if no other entity is
|
||||
// involved in this event.
|
||||
// e.g. SubChannel (id: 4[]) Created. --> RefID = 4, RefName = "" (inside [])
|
||||
RefID int64
|
||||
// RefName is the reference name for the entity that gets referenced in the event.
|
||||
RefName string
|
||||
// RefType indicates the referenced entity type, i.e Channel or SubChannel.
|
||||
RefType RefChannelType
|
||||
}
|
||||
|
||||
// TraceEvent is what the caller of AddTraceEvent should provide to describe the
|
||||
// event to be added to the channel trace.
|
||||
//
|
||||
// The Parent field is optional. It is used for an event that will be recorded
|
||||
// in the entity's parent trace.
|
||||
type TraceEvent struct {
|
||||
Desc string
|
||||
Severity Severity
|
||||
Parent *TraceEvent
|
||||
}
|
||||
|
||||
type ChannelTrace struct {
|
||||
cm *channelMap
|
||||
clearCalled bool
|
||||
CreationTime time.Time
|
||||
EventNum int64
|
||||
mu sync.Mutex
|
||||
Events []*traceEvent
|
||||
}
|
||||
|
||||
func (c *ChannelTrace) copy() *ChannelTrace {
|
||||
return &ChannelTrace{
|
||||
CreationTime: c.CreationTime,
|
||||
EventNum: c.EventNum,
|
||||
Events: append(([]*traceEvent)(nil), c.Events...),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ChannelTrace) append(e *traceEvent) {
|
||||
c.mu.Lock()
|
||||
if len(c.Events) == getMaxTraceEntry() {
|
||||
del := c.Events[0]
|
||||
c.Events = c.Events[1:]
|
||||
if del.RefID != 0 {
|
||||
// start recursive cleanup in a goroutine to not block the call originated from grpc.
|
||||
go func() {
|
||||
// need to acquire c.cm.mu lock to call the unlocked attemptCleanup func.
|
||||
c.cm.mu.Lock()
|
||||
c.cm.decrTraceRefCount(del.RefID)
|
||||
c.cm.mu.Unlock()
|
||||
}()
|
||||
}
|
||||
}
|
||||
e.Timestamp = time.Now()
|
||||
c.Events = append(c.Events, e)
|
||||
c.EventNum++
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
func (c *ChannelTrace) clear() {
|
||||
if c.clearCalled {
|
||||
return
|
||||
}
|
||||
c.clearCalled = true
|
||||
c.mu.Lock()
|
||||
for _, e := range c.Events {
|
||||
if e.RefID != 0 {
|
||||
// caller should have already held the c.cm.mu lock.
|
||||
c.cm.decrTraceRefCount(e.RefID)
|
||||
}
|
||||
}
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
// Severity is the severity level of a trace event.
|
||||
// The canonical enumeration of all valid values is here:
|
||||
// https://github.com/grpc/grpc-proto/blob/9b13d199cc0d4703c7ea26c9c330ba695866eb23/grpc/channelz/v1/channelz.proto#L126.
|
||||
type Severity int
|
||||
|
||||
const (
|
||||
// CtUnknown indicates unknown severity of a trace event.
|
||||
CtUnknown Severity = iota
|
||||
// CtInfo indicates info level severity of a trace event.
|
||||
CtInfo
|
||||
// CtWarning indicates warning level severity of a trace event.
|
||||
CtWarning
|
||||
// CtError indicates error level severity of a trace event.
|
||||
CtError
|
||||
)
|
||||
|
||||
// RefChannelType is the type of the entity being referenced in a trace event.
|
||||
type RefChannelType int
|
||||
|
||||
const (
|
||||
// RefUnknown indicates an unknown entity type, the zero value for this type.
|
||||
RefUnknown RefChannelType = iota
|
||||
// RefChannel indicates the referenced entity is a Channel.
|
||||
RefChannel
|
||||
// RefSubChannel indicates the referenced entity is a SubChannel.
|
||||
RefSubChannel
|
||||
// RefServer indicates the referenced entity is a Server.
|
||||
RefServer
|
||||
// RefListenSocket indicates the referenced entity is a ListenSocket.
|
||||
RefListenSocket
|
||||
// RefNormalSocket indicates the referenced entity is a NormalSocket.
|
||||
RefNormalSocket
|
||||
)
|
||||
|
||||
var refChannelTypeToString = map[RefChannelType]string{
|
||||
RefUnknown: "Unknown",
|
||||
RefChannel: "Channel",
|
||||
RefSubChannel: "SubChannel",
|
||||
RefServer: "Server",
|
||||
RefListenSocket: "ListenSocket",
|
||||
RefNormalSocket: "NormalSocket",
|
||||
}
|
||||
|
||||
func (r RefChannelType) String() string {
|
||||
return refChannelTypeToString[r]
|
||||
}
|
||||
|
||||
// AddTraceEvent adds trace related to the entity with specified id, using the
|
||||
// provided TraceEventDesc.
|
||||
//
|
||||
// If channelz is not turned ON, this will simply log the event descriptions.
|
||||
func AddTraceEvent(l grpclog.DepthLoggerV2, e Entity, depth int, desc *TraceEvent) {
|
||||
// Log only the trace description associated with the bottom most entity.
|
||||
d := fmt.Sprintf("[%s]%s", e, desc.Desc)
|
||||
switch desc.Severity {
|
||||
case CtUnknown, CtInfo:
|
||||
l.InfoDepth(depth+1, d)
|
||||
case CtWarning:
|
||||
l.WarningDepth(depth+1, d)
|
||||
case CtError:
|
||||
l.ErrorDepth(depth+1, d)
|
||||
}
|
||||
|
||||
if getMaxTraceEntry() == 0 {
|
||||
return
|
||||
}
|
||||
if IsOn() {
|
||||
db.traceEvent(e.id(), desc)
|
||||
}
|
||||
}
|
||||
49
vendor/google.golang.org/grpc/internal/credentials/credentials.go
generated
vendored
Normal file
49
vendor/google.golang.org/grpc/internal/credentials/credentials.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2021 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package credentials
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// requestInfoKey is a struct to be used as the key to store RequestInfo in a
|
||||
// context.
|
||||
type requestInfoKey struct{}
|
||||
|
||||
// NewRequestInfoContext creates a context with ri.
|
||||
func NewRequestInfoContext(ctx context.Context, ri any) context.Context {
|
||||
return context.WithValue(ctx, requestInfoKey{}, ri)
|
||||
}
|
||||
|
||||
// RequestInfoFromContext extracts the RequestInfo from ctx.
|
||||
func RequestInfoFromContext(ctx context.Context) any {
|
||||
return ctx.Value(requestInfoKey{})
|
||||
}
|
||||
|
||||
// clientHandshakeInfoKey is a struct used as the key to store
|
||||
// ClientHandshakeInfo in a context.
|
||||
type clientHandshakeInfoKey struct{}
|
||||
|
||||
// ClientHandshakeInfoFromContext extracts the ClientHandshakeInfo from ctx.
|
||||
func ClientHandshakeInfoFromContext(ctx context.Context) any {
|
||||
return ctx.Value(clientHandshakeInfoKey{})
|
||||
}
|
||||
|
||||
// NewClientHandshakeInfoContext creates a context with chi.
|
||||
func NewClientHandshakeInfoContext(ctx context.Context, chi any) context.Context {
|
||||
return context.WithValue(ctx, clientHandshakeInfoKey{}, chi)
|
||||
}
|
||||
75
vendor/google.golang.org/grpc/internal/credentials/spiffe.go
generated
vendored
Normal file
75
vendor/google.golang.org/grpc/internal/credentials/spiffe.go
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package credentials defines APIs for parsing SPIFFE ID.
|
||||
//
|
||||
// All APIs in this package are experimental.
|
||||
package credentials
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"net/url"
|
||||
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
var logger = grpclog.Component("credentials")
|
||||
|
||||
// SPIFFEIDFromState parses the SPIFFE ID from State. If the SPIFFE ID format
|
||||
// is invalid, return nil with warning.
|
||||
func SPIFFEIDFromState(state tls.ConnectionState) *url.URL {
|
||||
if len(state.PeerCertificates) == 0 || len(state.PeerCertificates[0].URIs) == 0 {
|
||||
return nil
|
||||
}
|
||||
return SPIFFEIDFromCert(state.PeerCertificates[0])
|
||||
}
|
||||
|
||||
// SPIFFEIDFromCert parses the SPIFFE ID from x509.Certificate. If the SPIFFE
|
||||
// ID format is invalid, return nil with warning.
|
||||
func SPIFFEIDFromCert(cert *x509.Certificate) *url.URL {
|
||||
if cert == nil || cert.URIs == nil {
|
||||
return nil
|
||||
}
|
||||
var spiffeID *url.URL
|
||||
for _, uri := range cert.URIs {
|
||||
if uri == nil || uri.Scheme != "spiffe" || uri.Opaque != "" || (uri.User != nil && uri.User.Username() != "") {
|
||||
continue
|
||||
}
|
||||
// From this point, we assume the uri is intended for a SPIFFE ID.
|
||||
if len(uri.String()) > 2048 {
|
||||
logger.Warning("invalid SPIFFE ID: total ID length larger than 2048 bytes")
|
||||
return nil
|
||||
}
|
||||
if len(uri.Host) == 0 || len(uri.Path) == 0 {
|
||||
logger.Warning("invalid SPIFFE ID: domain or workload ID is empty")
|
||||
return nil
|
||||
}
|
||||
if len(uri.Host) > 255 {
|
||||
logger.Warning("invalid SPIFFE ID: domain length larger than 255 characters")
|
||||
return nil
|
||||
}
|
||||
// A valid SPIFFE certificate can only have exactly one URI SAN field.
|
||||
if len(cert.URIs) > 1 {
|
||||
logger.Warning("invalid SPIFFE ID: multiple URI SANs")
|
||||
return nil
|
||||
}
|
||||
spiffeID = uri
|
||||
}
|
||||
return spiffeID
|
||||
}
|
||||
58
vendor/google.golang.org/grpc/internal/credentials/syscallconn.go
generated
vendored
Normal file
58
vendor/google.golang.org/grpc/internal/credentials/syscallconn.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package credentials
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
type sysConn = syscall.Conn
|
||||
|
||||
// syscallConn keeps reference of rawConn to support syscall.Conn for channelz.
|
||||
// SyscallConn() (the method in interface syscall.Conn) is explicitly
|
||||
// implemented on this type,
|
||||
//
|
||||
// Interface syscall.Conn is implemented by most net.Conn implementations (e.g.
|
||||
// TCPConn, UnixConn), but is not part of net.Conn interface. So wrapper conns
|
||||
// that embed net.Conn don't implement syscall.Conn. (Side note: tls.Conn
|
||||
// doesn't embed net.Conn, so even if syscall.Conn is part of net.Conn, it won't
|
||||
// help here).
|
||||
type syscallConn struct {
|
||||
net.Conn
|
||||
// sysConn is a type alias of syscall.Conn. It's necessary because the name
|
||||
// `Conn` collides with `net.Conn`.
|
||||
sysConn
|
||||
}
|
||||
|
||||
// WrapSyscallConn tries to wrap rawConn and newConn into a net.Conn that
|
||||
// implements syscall.Conn. rawConn will be used to support syscall, and newConn
|
||||
// will be used for read/write.
|
||||
//
|
||||
// This function returns newConn if rawConn doesn't implement syscall.Conn.
|
||||
func WrapSyscallConn(rawConn, newConn net.Conn) net.Conn {
|
||||
sysConn, ok := rawConn.(syscall.Conn)
|
||||
if !ok {
|
||||
return newConn
|
||||
}
|
||||
return &syscallConn{
|
||||
Conn: newConn,
|
||||
sysConn: sysConn,
|
||||
}
|
||||
}
|
||||
52
vendor/google.golang.org/grpc/internal/credentials/util.go
generated
vendored
Normal file
52
vendor/google.golang.org/grpc/internal/credentials/util.go
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package credentials
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
)
|
||||
|
||||
const alpnProtoStrH2 = "h2"
|
||||
|
||||
// AppendH2ToNextProtos appends h2 to next protos.
|
||||
func AppendH2ToNextProtos(ps []string) []string {
|
||||
for _, p := range ps {
|
||||
if p == alpnProtoStrH2 {
|
||||
return ps
|
||||
}
|
||||
}
|
||||
ret := make([]string, 0, len(ps)+1)
|
||||
ret = append(ret, ps...)
|
||||
return append(ret, alpnProtoStrH2)
|
||||
}
|
||||
|
||||
// CloneTLSConfig returns a shallow clone of the exported
|
||||
// fields of cfg, ignoring the unexported sync.Once, which
|
||||
// contains a mutex and must not be copied.
|
||||
//
|
||||
// If cfg is nil, a new zero tls.Config is returned.
|
||||
//
|
||||
// TODO: inline this function if possible.
|
||||
func CloneTLSConfig(cfg *tls.Config) *tls.Config {
|
||||
if cfg == nil {
|
||||
return &tls.Config{}
|
||||
}
|
||||
|
||||
return cfg.Clone()
|
||||
}
|
||||
66
vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
generated
vendored
Normal file
66
vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package envconfig contains grpc settings configured by environment variables.
|
||||
package envconfig
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// TXTErrIgnore is set if TXT errors should be ignored ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false").
|
||||
TXTErrIgnore = boolFromEnv("GRPC_GO_IGNORE_TXT_ERRORS", true)
|
||||
// RingHashCap indicates the maximum ring size which defaults to 4096
|
||||
// entries but may be overridden by setting the environment variable
|
||||
// "GRPC_RING_HASH_CAP". This does not override the default bounds
|
||||
// checking which NACKs configs specifying ring sizes > 8*1024*1024 (~8M).
|
||||
RingHashCap = uint64FromEnv("GRPC_RING_HASH_CAP", 4096, 1, 8*1024*1024)
|
||||
// LeastRequestLB is set if we should support the least_request_experimental
|
||||
// LB policy, which can be enabled by setting the environment variable
|
||||
// "GRPC_EXPERIMENTAL_ENABLE_LEAST_REQUEST" to "true".
|
||||
LeastRequestLB = boolFromEnv("GRPC_EXPERIMENTAL_ENABLE_LEAST_REQUEST", false)
|
||||
// ALTSMaxConcurrentHandshakes is the maximum number of concurrent ALTS
|
||||
// handshakes that can be performed.
|
||||
ALTSMaxConcurrentHandshakes = uint64FromEnv("GRPC_ALTS_MAX_CONCURRENT_HANDSHAKES", 100, 1, 100)
|
||||
)
|
||||
|
||||
func boolFromEnv(envVar string, def bool) bool {
|
||||
if def {
|
||||
// The default is true; return true unless the variable is "false".
|
||||
return !strings.EqualFold(os.Getenv(envVar), "false")
|
||||
}
|
||||
// The default is false; return false unless the variable is "true".
|
||||
return strings.EqualFold(os.Getenv(envVar), "true")
|
||||
}
|
||||
|
||||
func uint64FromEnv(envVar string, def, min, max uint64) uint64 {
|
||||
v, err := strconv.ParseUint(os.Getenv(envVar), 10, 64)
|
||||
if err != nil {
|
||||
return def
|
||||
}
|
||||
if v < min {
|
||||
return min
|
||||
}
|
||||
if v > max {
|
||||
return max
|
||||
}
|
||||
return v
|
||||
}
|
||||
42
vendor/google.golang.org/grpc/internal/envconfig/observability.go
generated
vendored
Normal file
42
vendor/google.golang.org/grpc/internal/envconfig/observability.go
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2022 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package envconfig
|
||||
|
||||
import "os"
|
||||
|
||||
const (
|
||||
envObservabilityConfig = "GRPC_GCP_OBSERVABILITY_CONFIG"
|
||||
envObservabilityConfigFile = "GRPC_GCP_OBSERVABILITY_CONFIG_FILE"
|
||||
)
|
||||
|
||||
var (
|
||||
// ObservabilityConfig is the json configuration for the gcp/observability
|
||||
// package specified directly in the envObservabilityConfig env var.
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
ObservabilityConfig = os.Getenv(envObservabilityConfig)
|
||||
// ObservabilityConfigFile is the json configuration for the
|
||||
// gcp/observability specified in a file with the location specified in
|
||||
// envObservabilityConfigFile env var.
|
||||
//
|
||||
// This is used in the 1.0 release of gcp/observability, and thus must not be
|
||||
// deleted or changed.
|
||||
ObservabilityConfigFile = os.Getenv(envObservabilityConfigFile)
|
||||
)
|
||||
56
vendor/google.golang.org/grpc/internal/envconfig/xds.go
generated
vendored
Normal file
56
vendor/google.golang.org/grpc/internal/envconfig/xds.go
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package envconfig
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
const (
|
||||
// XDSBootstrapFileNameEnv is the env variable to set bootstrap file name.
|
||||
// Do not use this and read from env directly. Its value is read and kept in
|
||||
// variable XDSBootstrapFileName.
|
||||
//
|
||||
// When both bootstrap FileName and FileContent are set, FileName is used.
|
||||
XDSBootstrapFileNameEnv = "GRPC_XDS_BOOTSTRAP"
|
||||
// XDSBootstrapFileContentEnv is the env variable to set bootstrap file
|
||||
// content. Do not use this and read from env directly. Its value is read
|
||||
// and kept in variable XDSBootstrapFileContent.
|
||||
//
|
||||
// When both bootstrap FileName and FileContent are set, FileName is used.
|
||||
XDSBootstrapFileContentEnv = "GRPC_XDS_BOOTSTRAP_CONFIG"
|
||||
)
|
||||
|
||||
var (
|
||||
// XDSBootstrapFileName holds the name of the file which contains xDS
|
||||
// bootstrap configuration. Users can specify the location of the bootstrap
|
||||
// file by setting the environment variable "GRPC_XDS_BOOTSTRAP".
|
||||
//
|
||||
// When both bootstrap FileName and FileContent are set, FileName is used.
|
||||
XDSBootstrapFileName = os.Getenv(XDSBootstrapFileNameEnv)
|
||||
// XDSBootstrapFileContent holds the content of the xDS bootstrap
|
||||
// configuration. Users can specify the bootstrap config by setting the
|
||||
// environment variable "GRPC_XDS_BOOTSTRAP_CONFIG".
|
||||
//
|
||||
// When both bootstrap FileName and FileContent are set, FileName is used.
|
||||
XDSBootstrapFileContent = os.Getenv(XDSBootstrapFileContentEnv)
|
||||
|
||||
// C2PResolverTestOnlyTrafficDirectorURI is the TD URI for testing.
|
||||
C2PResolverTestOnlyTrafficDirectorURI = os.Getenv("GRPC_TEST_ONLY_GOOGLE_C2P_RESOLVER_TRAFFIC_DIRECTOR_URI")
|
||||
)
|
||||
28
vendor/google.golang.org/grpc/internal/experimental.go
generated
vendored
Normal file
28
vendor/google.golang.org/grpc/internal/experimental.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2023 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package internal
|
||||
|
||||
var (
|
||||
// WithRecvBufferPool is implemented by the grpc package and returns a dial
|
||||
// option to configure a shared buffer pool for a grpc.ClientConn.
|
||||
WithRecvBufferPool any // func (grpc.SharedBufferPool) grpc.DialOption
|
||||
|
||||
// RecvBufferPool is implemented by the grpc package and returns a server
|
||||
// option to configure a shared buffer pool for a grpc.Server.
|
||||
RecvBufferPool any // func (grpc.SharedBufferPool) grpc.ServerOption
|
||||
)
|
||||
72
vendor/google.golang.org/grpc/internal/googlecloud/googlecloud.go
generated
vendored
Normal file
72
vendor/google.golang.org/grpc/internal/googlecloud/googlecloud.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2021 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package googlecloud contains internal helpful functions for google cloud.
|
||||
package googlecloud
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/grpc/grpclog"
|
||||
internalgrpclog "google.golang.org/grpc/internal/grpclog"
|
||||
)
|
||||
|
||||
const logPrefix = "[googlecloud]"
|
||||
|
||||
var (
|
||||
vmOnGCEOnce sync.Once
|
||||
vmOnGCE bool
|
||||
|
||||
logger = internalgrpclog.NewPrefixLogger(grpclog.Component("googlecloud"), logPrefix)
|
||||
)
|
||||
|
||||
// OnGCE returns whether the client is running on GCE.
|
||||
//
|
||||
// It provides similar functionality as metadata.OnGCE from the cloud library
|
||||
// package. We keep this to avoid depending on the cloud library module.
|
||||
func OnGCE() bool {
|
||||
vmOnGCEOnce.Do(func() {
|
||||
mf, err := manufacturer()
|
||||
if err != nil {
|
||||
logger.Infof("failed to read manufacturer, setting onGCE=false: %v")
|
||||
return
|
||||
}
|
||||
vmOnGCE = isRunningOnGCE(mf, runtime.GOOS)
|
||||
})
|
||||
return vmOnGCE
|
||||
}
|
||||
|
||||
// isRunningOnGCE checks whether the local system, without doing a network request, is
|
||||
// running on GCP.
|
||||
func isRunningOnGCE(manufacturer []byte, goos string) bool {
|
||||
name := string(manufacturer)
|
||||
switch goos {
|
||||
case "linux":
|
||||
name = strings.TrimSpace(name)
|
||||
return name == "Google" || name == "Google Compute Engine"
|
||||
case "windows":
|
||||
name = strings.Replace(name, " ", "", -1)
|
||||
name = strings.Replace(name, "\n", "", -1)
|
||||
name = strings.Replace(name, "\r", "", -1)
|
||||
return name == "Google"
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
26
vendor/google.golang.org/grpc/internal/googlecloud/manufacturer.go
generated
vendored
Normal file
26
vendor/google.golang.org/grpc/internal/googlecloud/manufacturer.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
//go:build !(linux || windows)
|
||||
// +build !linux,!windows
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright 2022 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package googlecloud
|
||||
|
||||
func manufacturer() ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
27
vendor/google.golang.org/grpc/internal/googlecloud/manufacturer_linux.go
generated
vendored
Normal file
27
vendor/google.golang.org/grpc/internal/googlecloud/manufacturer_linux.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2022 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package googlecloud
|
||||
|
||||
import "os"
|
||||
|
||||
const linuxProductNameFile = "/sys/class/dmi/id/product_name"
|
||||
|
||||
func manufacturer() ([]byte, error) {
|
||||
return os.ReadFile(linuxProductNameFile)
|
||||
}
|
||||
50
vendor/google.golang.org/grpc/internal/googlecloud/manufacturer_windows.go
generated
vendored
Normal file
50
vendor/google.golang.org/grpc/internal/googlecloud/manufacturer_windows.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2022 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package googlecloud
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
windowsCheckCommand = "powershell.exe"
|
||||
windowsCheckCommandArgs = "Get-WmiObject -Class Win32_BIOS"
|
||||
powershellOutputFilter = "Manufacturer"
|
||||
windowsManufacturerRegex = ":(.*)"
|
||||
)
|
||||
|
||||
func manufacturer() ([]byte, error) {
|
||||
cmd := exec.Command(windowsCheckCommand, windowsCheckCommandArgs)
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, line := range strings.Split(strings.TrimSuffix(string(out), "\n"), "\n") {
|
||||
if strings.HasPrefix(line, powershellOutputFilter) {
|
||||
re := regexp.MustCompile(windowsManufacturerRegex)
|
||||
name := re.FindString(line)
|
||||
name = strings.TrimLeft(name, ":")
|
||||
return []byte(name), nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("cannot determine the machine's manufacturer")
|
||||
}
|
||||
126
vendor/google.golang.org/grpc/internal/grpclog/grpclog.go
generated
vendored
Normal file
126
vendor/google.golang.org/grpc/internal/grpclog/grpclog.go
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package grpclog (internal) defines depth logging for grpc.
|
||||
package grpclog
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// Logger is the logger used for the non-depth log functions.
|
||||
var Logger LoggerV2
|
||||
|
||||
// DepthLogger is the logger used for the depth log functions.
|
||||
var DepthLogger DepthLoggerV2
|
||||
|
||||
// InfoDepth logs to the INFO log at the specified depth.
|
||||
func InfoDepth(depth int, args ...any) {
|
||||
if DepthLogger != nil {
|
||||
DepthLogger.InfoDepth(depth, args...)
|
||||
} else {
|
||||
Logger.Infoln(args...)
|
||||
}
|
||||
}
|
||||
|
||||
// WarningDepth logs to the WARNING log at the specified depth.
|
||||
func WarningDepth(depth int, args ...any) {
|
||||
if DepthLogger != nil {
|
||||
DepthLogger.WarningDepth(depth, args...)
|
||||
} else {
|
||||
Logger.Warningln(args...)
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorDepth logs to the ERROR log at the specified depth.
|
||||
func ErrorDepth(depth int, args ...any) {
|
||||
if DepthLogger != nil {
|
||||
DepthLogger.ErrorDepth(depth, args...)
|
||||
} else {
|
||||
Logger.Errorln(args...)
|
||||
}
|
||||
}
|
||||
|
||||
// FatalDepth logs to the FATAL log at the specified depth.
|
||||
func FatalDepth(depth int, args ...any) {
|
||||
if DepthLogger != nil {
|
||||
DepthLogger.FatalDepth(depth, args...)
|
||||
} else {
|
||||
Logger.Fatalln(args...)
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// LoggerV2 does underlying logging work for grpclog.
|
||||
// This is a copy of the LoggerV2 defined in the external grpclog package. It
|
||||
// is defined here to avoid a circular dependency.
|
||||
type LoggerV2 interface {
|
||||
// Info logs to INFO log. Arguments are handled in the manner of fmt.Print.
|
||||
Info(args ...any)
|
||||
// Infoln logs to INFO log. Arguments are handled in the manner of fmt.Println.
|
||||
Infoln(args ...any)
|
||||
// Infof logs to INFO log. Arguments are handled in the manner of fmt.Printf.
|
||||
Infof(format string, args ...any)
|
||||
// Warning logs to WARNING log. Arguments are handled in the manner of fmt.Print.
|
||||
Warning(args ...any)
|
||||
// Warningln logs to WARNING log. Arguments are handled in the manner of fmt.Println.
|
||||
Warningln(args ...any)
|
||||
// Warningf logs to WARNING log. Arguments are handled in the manner of fmt.Printf.
|
||||
Warningf(format string, args ...any)
|
||||
// Error logs to ERROR log. Arguments are handled in the manner of fmt.Print.
|
||||
Error(args ...any)
|
||||
// Errorln logs to ERROR log. Arguments are handled in the manner of fmt.Println.
|
||||
Errorln(args ...any)
|
||||
// Errorf logs to ERROR log. Arguments are handled in the manner of fmt.Printf.
|
||||
Errorf(format string, args ...any)
|
||||
// Fatal logs to ERROR log. Arguments are handled in the manner of fmt.Print.
|
||||
// gRPC ensures that all Fatal logs will exit with os.Exit(1).
|
||||
// Implementations may also call os.Exit() with a non-zero exit code.
|
||||
Fatal(args ...any)
|
||||
// Fatalln logs to ERROR log. Arguments are handled in the manner of fmt.Println.
|
||||
// gRPC ensures that all Fatal logs will exit with os.Exit(1).
|
||||
// Implementations may also call os.Exit() with a non-zero exit code.
|
||||
Fatalln(args ...any)
|
||||
// Fatalf logs to ERROR log. Arguments are handled in the manner of fmt.Printf.
|
||||
// gRPC ensures that all Fatal logs will exit with os.Exit(1).
|
||||
// Implementations may also call os.Exit() with a non-zero exit code.
|
||||
Fatalf(format string, args ...any)
|
||||
// V reports whether verbosity level l is at least the requested verbose level.
|
||||
V(l int) bool
|
||||
}
|
||||
|
||||
// DepthLoggerV2 logs at a specified call frame. If a LoggerV2 also implements
|
||||
// DepthLoggerV2, the below functions will be called with the appropriate stack
|
||||
// depth set for trivial functions the logger may ignore.
|
||||
// This is a copy of the DepthLoggerV2 defined in the external grpclog package.
|
||||
// It is defined here to avoid a circular dependency.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This type is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
type DepthLoggerV2 interface {
|
||||
// InfoDepth logs to INFO log at the specified depth. Arguments are handled in the manner of fmt.Println.
|
||||
InfoDepth(depth int, args ...any)
|
||||
// WarningDepth logs to WARNING log at the specified depth. Arguments are handled in the manner of fmt.Println.
|
||||
WarningDepth(depth int, args ...any)
|
||||
// ErrorDepth logs to ERROR log at the specified depth. Arguments are handled in the manner of fmt.Println.
|
||||
ErrorDepth(depth int, args ...any)
|
||||
// FatalDepth logs to FATAL log at the specified depth. Arguments are handled in the manner of fmt.Println.
|
||||
FatalDepth(depth int, args ...any)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user