aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/google.golang.org/grpc
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/google.golang.org/grpc')
-rw-r--r--vendor/google.golang.org/grpc/.travis.yml42
-rw-r--r--vendor/google.golang.org/grpc/CONTRIBUTING.md6
-rw-r--r--vendor/google.golang.org/grpc/Makefile68
-rw-r--r--vendor/google.golang.org/grpc/README.md28
-rw-r--r--vendor/google.golang.org/grpc/backoff.go70
-rw-r--r--vendor/google.golang.org/grpc/balancer.go46
-rw-r--r--vendor/google.golang.org/grpc/balancer/balancer.go303
-rw-r--r--vendor/google.golang.org/grpc/balancer/base/balancer.go171
-rw-r--r--vendor/google.golang.org/grpc/balancer/base/base.go64
-rw-r--r--vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go79
-rw-r--r--vendor/google.golang.org/grpc/balancer_conn_wrappers.go328
-rw-r--r--vendor/google.golang.org/grpc/balancer_v1_wrapper.go326
-rw-r--r--vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go900
-rw-r--r--vendor/google.golang.org/grpc/call.go309
-rw-r--r--vendor/google.golang.org/grpc/clientconn.go1859
-rw-r--r--vendor/google.golang.org/grpc/codec.go88
-rw-r--r--vendor/google.golang.org/grpc/codes/code_string.go66
-rw-r--r--vendor/google.golang.org/grpc/codes/codes.go79
-rw-r--r--vendor/google.golang.org/grpc/connectivity/connectivity.go3
-rw-r--r--vendor/google.golang.org/grpc/coverage.sh48
-rw-r--r--vendor/google.golang.org/grpc/credentials/credentials.go145
-rw-r--r--vendor/google.golang.org/grpc/credentials/credentials_util_go17.go60
-rw-r--r--vendor/google.golang.org/grpc/credentials/credentials_util_pre_go17.go57
-rw-r--r--vendor/google.golang.org/grpc/credentials/internal/syscallconn.go61
-rw-r--r--vendor/google.golang.org/grpc/credentials/internal/syscallconn_appengine.go (renamed from vendor/google.golang.org/grpc/naming/go17.go)18
-rw-r--r--vendor/google.golang.org/grpc/dialoptions.go492
-rw-r--r--vendor/google.golang.org/grpc/encoding/encoding.go118
-rw-r--r--vendor/google.golang.org/grpc/encoding/proto/proto.go110
-rw-r--r--vendor/google.golang.org/grpc/go.mod20
-rw-r--r--vendor/google.golang.org/grpc/go.sum32
-rw-r--r--vendor/google.golang.org/grpc/go16.go98
-rw-r--r--vendor/google.golang.org/grpc/go17.go98
-rw-r--r--vendor/google.golang.org/grpc/grpclb.go737
-rw-r--r--vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/grpclb.pb.go629
-rw-r--r--vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/grpclb.proto164
-rw-r--r--vendor/google.golang.org/grpc/grpclog/grpclog.go3
-rw-r--r--vendor/google.golang.org/grpc/grpclog/logger.go2
-rw-r--r--vendor/google.golang.org/grpc/health/client.go107
-rw-r--r--vendor/google.golang.org/grpc/health/grpc_health_v1/health.pb.go263
-rw-r--r--vendor/google.golang.org/grpc/health/grpc_health_v1/health.proto34
-rw-r--r--vendor/google.golang.org/grpc/health/health.go70
-rw-r--r--vendor/google.golang.org/grpc/health/regenerate.sh33
-rw-r--r--vendor/google.golang.org/grpc/health/server.go165
-rw-r--r--vendor/google.golang.org/grpc/install_gae.sh6
-rw-r--r--vendor/google.golang.org/grpc/interceptor.go6
-rw-r--r--vendor/google.golang.org/grpc/internal/backoff/backoff.go78
-rw-r--r--vendor/google.golang.org/grpc/internal/binarylog/binarylog.go167
-rw-r--r--vendor/google.golang.org/grpc/internal/binarylog/binarylog_testutil.go42
-rw-r--r--vendor/google.golang.org/grpc/internal/binarylog/env_config.go210
-rw-r--r--vendor/google.golang.org/grpc/internal/binarylog/method_logger.go426
-rw-r--r--vendor/google.golang.org/grpc/internal/binarylog/regenerate.sh33
-rw-r--r--vendor/google.golang.org/grpc/internal/binarylog/sink.go162
-rw-r--r--vendor/google.golang.org/grpc/internal/binarylog/util.go41
-rw-r--r--vendor/google.golang.org/grpc/internal/channelz/funcs.go699
-rw-r--r--vendor/google.golang.org/grpc/internal/channelz/types.go702
-rw-r--r--vendor/google.golang.org/grpc/internal/channelz/types_linux.go53
-rw-r--r--vendor/google.golang.org/grpc/internal/channelz/types_nonlinux.go44
-rw-r--r--vendor/google.golang.org/grpc/internal/channelz/util_linux.go (renamed from vendor/google.golang.org/grpc/credentials/credentials_util_go18.go)29
-rw-r--r--vendor/google.golang.org/grpc/internal/channelz/util_nonlinux.go26
-rw-r--r--vendor/google.golang.org/grpc/internal/envconfig/envconfig.go70
-rw-r--r--vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go56
-rw-r--r--vendor/google.golang.org/grpc/internal/grpcsync/event.go61
-rw-r--r--vendor/google.golang.org/grpc/internal/internal.go44
-rw-r--r--vendor/google.golang.org/grpc/internal/syscall/syscall_linux.go114
-rw-r--r--vendor/google.golang.org/grpc/internal/syscall/syscall_nonlinux.go63
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/bdp_estimator.go (renamed from vendor/google.golang.org/grpc/transport/bdp_estimator.go)22
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/controlbuf.go852
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/defaults.go49
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/flowcontrol.go (renamed from vendor/google.golang.org/grpc/transport/control.go)204
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/handler_server.go (renamed from vendor/google.golang.org/grpc/transport/handler_server.go)136
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/http2_client.go1380
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/http2_server.go (renamed from vendor/google.golang.org/grpc/transport/http2_server.go)1051
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/http_util.go (renamed from vendor/google.golang.org/grpc/transport/http_util.go)386
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/log.go (renamed from vendor/google.golang.org/grpc/transport/log.go)6
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/transport.go (renamed from vendor/google.golang.org/grpc/transport/transport.go)564
-rw-r--r--vendor/google.golang.org/grpc/keepalive/keepalive.go62
-rw-r--r--vendor/google.golang.org/grpc/metadata/metadata.go104
-rw-r--r--vendor/google.golang.org/grpc/naming/dns_resolver.go55
-rw-r--r--vendor/google.golang.org/grpc/naming/naming.go12
-rw-r--r--vendor/google.golang.org/grpc/peer/peer.go2
-rw-r--r--vendor/google.golang.org/grpc/picker_wrapper.go180
-rw-r--r--vendor/google.golang.org/grpc/pickfirst.go110
-rw-r--r--vendor/google.golang.org/grpc/proxy.go52
-rw-r--r--vendor/google.golang.org/grpc/resolver/dns/dns_resolver.go436
-rw-r--r--vendor/google.golang.org/grpc/resolver/passthrough/passthrough.go57
-rw-r--r--vendor/google.golang.org/grpc/resolver/resolver.go158
-rw-r--r--vendor/google.golang.org/grpc/resolver_conn_wrapper.go155
-rw-r--r--vendor/google.golang.org/grpc/rpc_util.go734
-rw-r--r--vendor/google.golang.org/grpc/server.go861
-rw-r--r--vendor/google.golang.org/grpc/service_config.go372
-rw-r--r--vendor/google.golang.org/grpc/stats/handlers.go3
-rw-r--r--vendor/google.golang.org/grpc/stats/stats.go89
-rw-r--r--vendor/google.golang.org/grpc/status/status.go52
-rw-r--r--vendor/google.golang.org/grpc/stream.go1539
-rw-r--r--vendor/google.golang.org/grpc/tap/tap.go22
-rw-r--r--vendor/google.golang.org/grpc/test/bufconn/bufconn.go244
-rw-r--r--vendor/google.golang.org/grpc/trace.go15
-rw-r--r--vendor/google.golang.org/grpc/transport/go16.go45
-rw-r--r--vendor/google.golang.org/grpc/transport/go17.go46
-rw-r--r--vendor/google.golang.org/grpc/transport/http2_client.go1369
-rw-r--r--vendor/google.golang.org/grpc/version.go (renamed from vendor/google.golang.org/grpc/naming/go18.go)14
-rw-r--r--vendor/google.golang.org/grpc/vet.sh141
102 files changed, 16140 insertions, 6970 deletions
diff --git a/vendor/google.golang.org/grpc/.travis.yml b/vendor/google.golang.org/grpc/.travis.yml
index 88a785d..f443eec 100644
--- a/vendor/google.golang.org/grpc/.travis.yml
+++ b/vendor/google.golang.org/grpc/.travis.yml
@@ -1,21 +1,37 @@
1language: go 1language: go
2 2
3go: 3matrix:
4 - 1.6.x 4 include:
5 - 1.7.x 5 - go: 1.11.x
6 - 1.8.x 6 env: VET=1 GO111MODULE=on
7 - go: 1.11.x
8 env: RACE=1 GO111MODULE=on
9 - go: 1.11.x
10 env: RUN386=1
11 - go: 1.11.x
12 env: GRPC_GO_RETRY=on
13 - go: 1.10.x
14 - go: 1.9.x
15 - go: 1.9.x
16 env: GAE=1
7 17
8go_import_path: google.golang.org/grpc 18go_import_path: google.golang.org/grpc
9 19
10before_install: 20before_install:
11 - if [[ $TRAVIS_GO_VERSION = 1.8* ]]; then go get -u github.com/golang/lint/golint honnef.co/go/tools/cmd/staticcheck; fi 21 - if [[ "${GO111MODULE}" = "on" ]]; then mkdir "${HOME}/go"; export GOPATH="${HOME}/go"; fi
12 - go get -u golang.org/x/tools/cmd/goimports github.com/axw/gocov/gocov github.com/mattn/goveralls golang.org/x/tools/cmd/cover 22 - if [[ -n "${RUN386}" ]]; then export GOARCH=386; fi
23 - if [[ "${TRAVIS_EVENT_TYPE}" = "cron" && -z "${RUN386}" ]]; then RACE=1; fi
24 - if [[ "${TRAVIS_EVENT_TYPE}" != "cron" ]]; then VET_SKIP_PROTO=1; fi
25
26install:
27 - try3() { eval "$*" || eval "$*" || eval "$*"; }
28 - try3 'if [[ "${GO111MODULE}" = "on" ]]; then go mod download; else make testdeps; fi'
29 - if [[ "${GAE}" = 1 ]]; then source ./install_gae.sh; make testappenginedeps; fi
30 - if [[ "${VET}" = 1 ]]; then ./vet.sh -install; fi
13 31
14script: 32script:
15 - 'set -o pipefail && git ls-files "*.go" | xargs grep -L "\(Copyright [0-9]\{4,\} gRPC authors\)\|DO NOT EDIT" 2>&1 | tee /dev/stderr | (! read)' 33 - set -e
16 - 'set -o pipefail && gofmt -s -d -l . 2>&1 | tee /dev/stderr | (! read)' 34 - if [[ "${VET}" = 1 ]]; then ./vet.sh; fi
17 - 'set -o pipefail && goimports -l . 2>&1 | tee /dev/stderr | (! read)' 35 - if [[ "${GAE}" = 1 ]]; then make testappengine; exit 0; fi
18 - 'if [[ $TRAVIS_GO_VERSION = 1.8* ]]; then ! golint ./... | grep -vE "(_mock|_string|\.pb)\.go:"; fi' 36 - if [[ "${RACE}" = 1 ]]; then make testrace; exit 0; fi
19 - 'if [[ $TRAVIS_GO_VERSION = 1.8* ]]; then ! go tool vet -all . 2>&1 | grep -vF .pb.go:; fi' # https://github.com/golang/protobuf/issues/214 37 - make test
20 - make test testrace
21 - 'if [[ $TRAVIS_GO_VERSION = 1.8* ]]; then staticcheck -ignore google.golang.org/grpc/transport/transport_test.go:SA2002 ./...; fi' # TODO(menghanl): fix these
diff --git a/vendor/google.golang.org/grpc/CONTRIBUTING.md b/vendor/google.golang.org/grpc/CONTRIBUTING.md
index a5c6e06..0863eb2 100644
--- a/vendor/google.golang.org/grpc/CONTRIBUTING.md
+++ b/vendor/google.golang.org/grpc/CONTRIBUTING.md
@@ -7,7 +7,7 @@ If you are new to github, please start by reading [Pull Request howto](https://h
7## Legal requirements 7## Legal requirements
8 8
9In order to protect both you and ourselves, you will need to sign the 9In order to protect both you and ourselves, you will need to sign the
10[Contributor License Agreement](https://cla.developers.google.com/clas). 10[Contributor License Agreement](https://identity.linuxfoundation.org/projects/cncf).
11 11
12## Guidelines for Pull Requests 12## Guidelines for Pull Requests
13How to get your contributions merged smoothly and quickly. 13How to get your contributions merged smoothly and quickly.
@@ -27,6 +27,10 @@ How to get your contributions merged smoothly and quickly.
27- Keep your PR up to date with upstream/master (if there are merge conflicts, we can't really merge your change). 27- Keep your PR up to date with upstream/master (if there are merge conflicts, we can't really merge your change).
28 28
29- **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. 29- **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.
30 - `make all` to test everything, OR
31 - `make vet` to catch vet errors
32 - `make test` to run the tests
33 - `make testrace` to run tests in race mode
30 34
31- Exceptions to the rules can be made if there's a compelling reason for doing so. 35- Exceptions to the rules can be made if there's a compelling reason for doing so.
32 36
diff --git a/vendor/google.golang.org/grpc/Makefile b/vendor/google.golang.org/grpc/Makefile
index 03bb01f..41a754f 100644
--- a/vendor/google.golang.org/grpc/Makefile
+++ b/vendor/google.golang.org/grpc/Makefile
@@ -1,52 +1,60 @@
1all: test testrace 1all: vet test testrace testappengine
2
3deps:
4 go get -d -v google.golang.org/grpc/...
5
6updatedeps:
7 go get -d -v -u -f google.golang.org/grpc/...
8
9testdeps:
10 go get -d -v -t google.golang.org/grpc/...
11
12updatetestdeps:
13 go get -d -v -t -u -f google.golang.org/grpc/...
14 2
15build: deps 3build: deps
16 go build google.golang.org/grpc/... 4 go build google.golang.org/grpc/...
17 5
6clean:
7 go clean -i google.golang.org/grpc/...
8
9deps:
10 go get -d -v google.golang.org/grpc/...
11
18proto: 12proto:
19 @ if ! which protoc > /dev/null; then \ 13 @ if ! which protoc > /dev/null; then \
20 echo "error: protoc not installed" >&2; \ 14 echo "error: protoc not installed" >&2; \
21 exit 1; \ 15 exit 1; \
22 fi 16 fi
23 go get -u -v github.com/golang/protobuf/protoc-gen-go 17 go generate google.golang.org/grpc/...
24 # use $$dir as the root for all proto files in the same directory
25 for dir in $$(git ls-files '*.proto' | xargs -n1 dirname | uniq); do \
26 protoc -I $$dir --go_out=plugins=grpc:$$dir $$dir/*.proto; \
27 done
28 18
29test: testdeps 19test: testdeps
30 go test -v -cpu 1,4 google.golang.org/grpc/... 20 go test -cpu 1,4 -timeout 7m google.golang.org/grpc/...
21
22testappengine: testappenginedeps
23 goapp test -cpu 1,4 -timeout 7m google.golang.org/grpc/...
24
25testappenginedeps:
26 goapp get -d -v -t -tags 'appengine appenginevm' google.golang.org/grpc/...
27
28testdeps:
29 go get -d -v -t google.golang.org/grpc/...
31 30
32testrace: testdeps 31testrace: testdeps
33 go test -v -race -cpu 1,4 google.golang.org/grpc/... 32 go test -race -cpu 1,4 -timeout 7m google.golang.org/grpc/...
34 33
35clean: 34updatedeps:
36 go clean -i google.golang.org/grpc/... 35 go get -d -v -u -f google.golang.org/grpc/...
36
37updatetestdeps:
38 go get -d -v -t -u -f google.golang.org/grpc/...
39
40vet: vetdeps
41 ./vet.sh
37 42
38coverage: testdeps 43vetdeps:
39 ./coverage.sh --coveralls 44 ./vet.sh -install
40 45
41.PHONY: \ 46.PHONY: \
42 all \ 47 all \
43 deps \
44 updatedeps \
45 testdeps \
46 updatetestdeps \
47 build \ 48 build \
49 clean \
50 deps \
48 proto \ 51 proto \
49 test \ 52 test \
53 testappengine \
54 testappenginedeps \
55 testdeps \
50 testrace \ 56 testrace \
51 clean \ 57 updatedeps \
52 coverage 58 updatetestdeps \
59 vet \
60 vetdeps
diff --git a/vendor/google.golang.org/grpc/README.md b/vendor/google.golang.org/grpc/README.md
index 72c7325..e3fb3c7 100644
--- a/vendor/google.golang.org/grpc/README.md
+++ b/vendor/google.golang.org/grpc/README.md
@@ -1,6 +1,6 @@
1# gRPC-Go 1# gRPC-Go
2 2
3[![Build Status](https://travis-ci.org/grpc/grpc-go.svg)](https://travis-ci.org/grpc/grpc-go) [![GoDoc](https://godoc.org/google.golang.org/grpc?status.svg)](https://godoc.org/google.golang.org/grpc) 3[![Build Status](https://travis-ci.org/grpc/grpc-go.svg)](https://travis-ci.org/grpc/grpc-go) [![GoDoc](https://godoc.org/google.golang.org/grpc?status.svg)](https://godoc.org/google.golang.org/grpc) [![GoReportCard](https://goreportcard.com/badge/grpc/grpc-go)](https://goreportcard.com/report/github.com/grpc/grpc-go)
4 4
5The Go implementation of [gRPC](https://grpc.io/): A high performance, open source, general RPC framework that puts mobile and HTTP/2 first. For more information see the [gRPC Quick Start: Go](https://grpc.io/docs/quickstart/go.html) guide. 5The Go implementation of [gRPC](https://grpc.io/): A high performance, open source, general RPC framework that puts mobile and HTTP/2 first. For more information see the [gRPC Quick Start: Go](https://grpc.io/docs/quickstart/go.html) guide.
6 6
@@ -10,13 +10,13 @@ Installation
10To install this package, you need to install Go and setup your Go workspace on your computer. The simplest way to install the library is to run: 10To install this package, you need to install Go and setup your Go workspace on your computer. The simplest way to install the library is to run:
11 11
12``` 12```
13$ go get google.golang.org/grpc 13$ go get -u google.golang.org/grpc
14``` 14```
15 15
16Prerequisites 16Prerequisites
17------------- 17-------------
18 18
19This requires Go 1.6 or later. 19gRPC-Go requires Go 1.9 or later.
20 20
21Constraints 21Constraints
22----------- 22-----------
@@ -43,3 +43,25 @@ Please update proto package, gRPC package and rebuild the proto files:
43 - `go get -u github.com/golang/protobuf/{proto,protoc-gen-go}` 43 - `go get -u github.com/golang/protobuf/{proto,protoc-gen-go}`
44 - `go get -u google.golang.org/grpc` 44 - `go get -u google.golang.org/grpc`
45 - `protoc --go_out=plugins=grpc:. *.proto` 45 - `protoc --go_out=plugins=grpc:. *.proto`
46
47#### How to turn on logging
48
49The default logger is controlled by the environment variables. Turn everything
50on by setting:
51
52```
53GRPC_GO_LOG_VERBOSITY_LEVEL=99 GRPC_GO_LOG_SEVERITY_LEVEL=info
54```
55
56#### The RPC failed with error `"code = Unavailable desc = transport is closing"`
57
58This error means the connection the RPC is using was closed, and there are many
59possible reasons, including:
60 1. mis-configured transport credentials, connection failed on handshaking
61 1. bytes disrupted, possibly by a proxy in between
62 1. server shutdown
63
64It can be tricky to debug this because the error happens on the client side but
65the root cause of the connection being closed is on the server side. Turn on
66logging on __both client and server__, and see if there are any transport
67errors.
diff --git a/vendor/google.golang.org/grpc/backoff.go b/vendor/google.golang.org/grpc/backoff.go
index 090fbe8..fa31565 100644
--- a/vendor/google.golang.org/grpc/backoff.go
+++ b/vendor/google.golang.org/grpc/backoff.go
@@ -16,83 +16,23 @@
16 * 16 *
17 */ 17 */
18 18
19// See internal/backoff package for the backoff implementation. This file is
20// kept for the exported types and API backward compatility.
21
19package grpc 22package grpc
20 23
21import ( 24import (
22 "math/rand"
23 "time" 25 "time"
24) 26)
25 27
26// DefaultBackoffConfig uses values specified for backoff in 28// DefaultBackoffConfig uses values specified for backoff in
27// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md. 29// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md.
28var ( 30var DefaultBackoffConfig = BackoffConfig{
29 DefaultBackoffConfig = BackoffConfig{ 31 MaxDelay: 120 * time.Second,
30 MaxDelay: 120 * time.Second,
31 baseDelay: 1.0 * time.Second,
32 factor: 1.6,
33 jitter: 0.2,
34 }
35)
36
37// backoffStrategy defines the methodology for backing off after a grpc
38// connection failure.
39//
40// This is unexported until the gRPC project decides whether or not to allow
41// alternative backoff strategies. Once a decision is made, this type and its
42// method may be exported.
43type backoffStrategy interface {
44 // backoff returns the amount of time to wait before the next retry given
45 // the number of consecutive failures.
46 backoff(retries int) time.Duration
47} 32}
48 33
49// BackoffConfig defines the parameters for the default gRPC backoff strategy. 34// BackoffConfig defines the parameters for the default gRPC backoff strategy.
50type BackoffConfig struct { 35type BackoffConfig struct {
51 // MaxDelay is the upper bound of backoff delay. 36 // MaxDelay is the upper bound of backoff delay.
52 MaxDelay time.Duration 37 MaxDelay time.Duration
53
54 // TODO(stevvooe): The following fields are not exported, as allowing
55 // changes would violate the current gRPC specification for backoff. If
56 // gRPC decides to allow more interesting backoff strategies, these fields
57 // may be opened up in the future.
58
59 // baseDelay is the amount of time to wait before retrying after the first
60 // failure.
61 baseDelay time.Duration
62
63 // factor is applied to the backoff after each retry.
64 factor float64
65
66 // jitter provides a range to randomize backoff delays.
67 jitter float64
68}
69
70func setDefaults(bc *BackoffConfig) {
71 md := bc.MaxDelay
72 *bc = DefaultBackoffConfig
73
74 if md > 0 {
75 bc.MaxDelay = md
76 }
77}
78
79func (bc BackoffConfig) backoff(retries int) time.Duration {
80 if retries == 0 {
81 return bc.baseDelay
82 }
83 backoff, max := float64(bc.baseDelay), float64(bc.MaxDelay)
84 for backoff < max && retries > 0 {
85 backoff *= bc.factor
86 retries--
87 }
88 if backoff > max {
89 backoff = max
90 }
91 // Randomize backoff delays so that if a cluster of requests start at
92 // the same time, they won't operate in lockstep.
93 backoff *= 1 + bc.jitter*(rand.Float64()*2-1)
94 if backoff < 0 {
95 return 0
96 }
97 return time.Duration(backoff)
98} 38}
diff --git a/vendor/google.golang.org/grpc/balancer.go b/vendor/google.golang.org/grpc/balancer.go
index cde472c..a78e702 100644
--- a/vendor/google.golang.org/grpc/balancer.go
+++ b/vendor/google.golang.org/grpc/balancer.go
@@ -19,19 +19,20 @@
19package grpc 19package grpc
20 20
21import ( 21import (
22 "fmt" 22 "context"
23 "net" 23 "net"
24 "sync" 24 "sync"
25 25
26 "golang.org/x/net/context"
27 "google.golang.org/grpc/codes" 26 "google.golang.org/grpc/codes"
28 "google.golang.org/grpc/credentials" 27 "google.golang.org/grpc/credentials"
29 "google.golang.org/grpc/grpclog" 28 "google.golang.org/grpc/grpclog"
30 "google.golang.org/grpc/naming" 29 "google.golang.org/grpc/naming"
30 "google.golang.org/grpc/status"
31) 31)
32 32
33// Address represents a server the client connects to. 33// Address represents a server the client connects to.
34// This is the EXPERIMENTAL API and may be changed or extended in the future. 34//
35// Deprecated: please use package balancer.
35type Address struct { 36type Address struct {
36 // Addr is the server address on which a connection will be established. 37 // Addr is the server address on which a connection will be established.
37 Addr string 38 Addr string
@@ -41,6 +42,8 @@ type Address struct {
41} 42}
42 43
43// BalancerConfig specifies the configurations for Balancer. 44// BalancerConfig specifies the configurations for Balancer.
45//
46// Deprecated: please use package balancer.
44type BalancerConfig struct { 47type BalancerConfig struct {
45 // DialCreds is the transport credential the Balancer implementation can 48 // DialCreds is the transport credential the Balancer implementation can
46 // use to dial to a remote load balancer server. The Balancer implementations 49 // use to dial to a remote load balancer server. The Balancer implementations
@@ -53,7 +56,8 @@ type BalancerConfig struct {
53} 56}
54 57
55// BalancerGetOptions configures a Get call. 58// BalancerGetOptions configures a Get call.
56// This is the EXPERIMENTAL API and may be changed or extended in the future. 59//
60// Deprecated: please use package balancer.
57type BalancerGetOptions struct { 61type BalancerGetOptions struct {
58 // BlockingWait specifies whether Get should block when there is no 62 // BlockingWait specifies whether Get should block when there is no
59 // connected address. 63 // connected address.
@@ -61,7 +65,8 @@ type BalancerGetOptions struct {
61} 65}
62 66
63// Balancer chooses network addresses for RPCs. 67// Balancer chooses network addresses for RPCs.
64// This is the EXPERIMENTAL API and may be changed or extended in the future. 68//
69// Deprecated: please use package balancer.
65type Balancer interface { 70type Balancer interface {
66 // Start does the initialization work to bootstrap a Balancer. For example, 71 // Start does the initialization work to bootstrap a Balancer. For example,
67 // this function may start the name resolution and watch the updates. It will 72 // this function may start the name resolution and watch the updates. It will
@@ -112,28 +117,10 @@ type Balancer interface {
112 Close() error 117 Close() error
113} 118}
114 119
115// downErr implements net.Error. It is constructed by gRPC internals and passed to the down
116// call of Balancer.
117type downErr struct {
118 timeout bool
119 temporary bool
120 desc string
121}
122
123func (e downErr) Error() string { return e.desc }
124func (e downErr) Timeout() bool { return e.timeout }
125func (e downErr) Temporary() bool { return e.temporary }
126
127func downErrorf(timeout, temporary bool, format string, a ...interface{}) downErr {
128 return downErr{
129 timeout: timeout,
130 temporary: temporary,
131 desc: fmt.Sprintf(format, a...),
132 }
133}
134
135// RoundRobin returns a Balancer that selects addresses round-robin. It uses r to watch 120// RoundRobin returns a Balancer that selects addresses round-robin. It uses r to watch
136// the name resolution updates and updates the addresses available correspondingly. 121// the name resolution updates and updates the addresses available correspondingly.
122//
123// Deprecated: please use package balancer/roundrobin.
137func RoundRobin(r naming.Resolver) Balancer { 124func RoundRobin(r naming.Resolver) Balancer {
138 return &roundRobin{r: r} 125 return &roundRobin{r: r}
139} 126}
@@ -310,7 +297,7 @@ func (rr *roundRobin) Get(ctx context.Context, opts BalancerGetOptions) (addr Ad
310 if !opts.BlockingWait { 297 if !opts.BlockingWait {
311 if len(rr.addrs) == 0 { 298 if len(rr.addrs) == 0 {
312 rr.mu.Unlock() 299 rr.mu.Unlock()
313 err = Errorf(codes.Unavailable, "there is no address available") 300 err = status.Errorf(codes.Unavailable, "there is no address available")
314 return 301 return
315 } 302 }
316 // Returns the next addr on rr.addrs for failfast RPCs. 303 // Returns the next addr on rr.addrs for failfast RPCs.
@@ -395,3 +382,10 @@ func (rr *roundRobin) Close() error {
395 } 382 }
396 return nil 383 return nil
397} 384}
385
386// pickFirst is used to test multi-addresses in one addrConn in which all addresses share the same addrConn.
387// It is a wrapper around roundRobin balancer. The logic of all methods works fine because balancer.Get()
388// returns the only address Up by resetTransport().
389type pickFirst struct {
390 *roundRobin
391}
diff --git a/vendor/google.golang.org/grpc/balancer/balancer.go b/vendor/google.golang.org/grpc/balancer/balancer.go
new file mode 100644
index 0000000..317c2e7
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer/balancer.go
@@ -0,0 +1,303 @@
1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// Package balancer defines APIs for load balancing in gRPC.
20// All APIs in this package are experimental.
21package balancer
22
23import (
24 "context"
25 "errors"
26 "net"
27 "strings"
28
29 "google.golang.org/grpc/connectivity"
30 "google.golang.org/grpc/credentials"
31 "google.golang.org/grpc/internal"
32 "google.golang.org/grpc/metadata"
33 "google.golang.org/grpc/resolver"
34)
35
36var (
37 // m is a map from name to balancer builder.
38 m = make(map[string]Builder)
39)
40
41// Register registers the balancer builder to the balancer map. b.Name
42// (lowercased) will be used as the name registered with this builder.
43//
44// NOTE: this function must only be called during initialization time (i.e. in
45// an init() function), and is not thread-safe. If multiple Balancers are
46// registered with the same name, the one registered last will take effect.
47func Register(b Builder) {
48 m[strings.ToLower(b.Name())] = b
49}
50
51// unregisterForTesting deletes the balancer with the given name from the
52// balancer map.
53//
54// This function is not thread-safe.
55func unregisterForTesting(name string) {
56 delete(m, name)
57}
58
59func init() {
60 internal.BalancerUnregister = unregisterForTesting
61}
62
63// Get returns the resolver builder registered with the given name.
64// Note that the compare is done in a case-insenstive fashion.
65// If no builder is register with the name, nil will be returned.
66func Get(name string) Builder {
67 if b, ok := m[strings.ToLower(name)]; ok {
68 return b
69 }
70 return nil
71}
72
73// SubConn represents a gRPC sub connection.
74// Each sub connection contains a list of addresses. gRPC will
75// try to connect to them (in sequence), and stop trying the
76// remainder once one connection is successful.
77//
78// The reconnect backoff will be applied on the list, not a single address.
79// For example, try_on_all_addresses -> backoff -> try_on_all_addresses.
80//
81// All SubConns start in IDLE, and will not try to connect. To trigger
82// the connecting, Balancers must call Connect.
83// When the connection encounters an error, it will reconnect immediately.
84// When the connection becomes IDLE, it will not reconnect unless Connect is
85// called.
86//
87// This interface is to be implemented by gRPC. Users should not need a
88// brand new implementation of this interface. For the situations like
89// testing, the new implementation should embed this interface. This allows
90// gRPC to add new methods to this interface.
91type SubConn interface {
92 // UpdateAddresses updates the addresses used in this SubConn.
93 // gRPC checks if currently-connected address is still in the new list.
94 // If it's in the list, the connection will be kept.
95 // If it's not in the list, the connection will gracefully closed, and
96 // a new connection will be created.
97 //
98 // This will trigger a state transition for the SubConn.
99 UpdateAddresses([]resolver.Address)
100 // Connect starts the connecting for this SubConn.
101 Connect()
102}
103
104// NewSubConnOptions contains options to create new SubConn.
105type NewSubConnOptions struct {
106 // CredsBundle is the credentials bundle that will be used in the created
107 // SubConn. If it's nil, the original creds from grpc DialOptions will be
108 // used.
109 CredsBundle credentials.Bundle
110 // HealthCheckEnabled indicates whether health check service should be
111 // enabled on this SubConn
112 HealthCheckEnabled bool
113}
114
115// ClientConn represents a gRPC ClientConn.
116//
117// This interface is to be implemented by gRPC. Users should not need a
118// brand new implementation of this interface. For the situations like
119// testing, the new implementation should embed this interface. This allows
120// gRPC to add new methods to this interface.
121type ClientConn interface {
122 // NewSubConn is called by balancer to create a new SubConn.
123 // It doesn't block and wait for the connections to be established.
124 // Behaviors of the SubConn can be controlled by options.
125 NewSubConn([]resolver.Address, NewSubConnOptions) (SubConn, error)
126 // RemoveSubConn removes the SubConn from ClientConn.
127 // The SubConn will be shutdown.
128 RemoveSubConn(SubConn)
129
130 // UpdateBalancerState is called by balancer to nofity gRPC that some internal
131 // state in balancer has changed.
132 //
133 // gRPC will update the connectivity state of the ClientConn, and will call pick
134 // on the new picker to pick new SubConn.
135 UpdateBalancerState(s connectivity.State, p Picker)
136
137 // ResolveNow is called by balancer to notify gRPC to do a name resolving.
138 ResolveNow(resolver.ResolveNowOption)
139
140 // Target returns the dial target for this ClientConn.
141 Target() string
142}
143
144// BuildOptions contains additional information for Build.
145type BuildOptions struct {
146 // DialCreds is the transport credential the Balancer implementation can
147 // use to dial to a remote load balancer server. The Balancer implementations
148 // can ignore this if it does not need to talk to another party securely.
149 DialCreds credentials.TransportCredentials
150 // CredsBundle is the credentials bundle that the Balancer can use.
151 CredsBundle credentials.Bundle
152 // Dialer is the custom dialer the Balancer implementation can use to dial
153 // to a remote load balancer server. The Balancer implementations
154 // can ignore this if it doesn't need to talk to remote balancer.
155 Dialer func(context.Context, string) (net.Conn, error)
156 // ChannelzParentID is the entity parent's channelz unique identification number.
157 ChannelzParentID int64
158}
159
160// Builder creates a balancer.
161type Builder interface {
162 // Build creates a new balancer with the ClientConn.
163 Build(cc ClientConn, opts BuildOptions) Balancer
164 // Name returns the name of balancers built by this builder.
165 // It will be used to pick balancers (for example in service config).
166 Name() string
167}
168
169// PickOptions contains addition information for the Pick operation.
170type PickOptions struct {
171 // FullMethodName is the method name that NewClientStream() is called
172 // with. The canonical format is /service/Method.
173 FullMethodName string
174 // Header contains the metadata from the RPC's client header. The metadata
175 // should not be modified; make a copy first if needed.
176 Header metadata.MD
177}
178
179// DoneInfo contains additional information for done.
180type DoneInfo struct {
181 // Err is the rpc error the RPC finished with. It could be nil.
182 Err error
183 // Trailer contains the metadata from the RPC's trailer, if present.
184 Trailer metadata.MD
185 // BytesSent indicates if any bytes have been sent to the server.
186 BytesSent bool
187 // BytesReceived indicates if any byte has been received from the server.
188 BytesReceived bool
189}
190
191var (
192 // ErrNoSubConnAvailable indicates no SubConn is available for pick().
193 // gRPC will block the RPC until a new picker is available via UpdateBalancerState().
194 ErrNoSubConnAvailable = errors.New("no SubConn is available")
195 // ErrTransientFailure indicates all SubConns are in TransientFailure.
196 // WaitForReady RPCs will block, non-WaitForReady RPCs will fail.
197 ErrTransientFailure = errors.New("all SubConns are in TransientFailure")
198)
199
200// Picker is used by gRPC to pick a SubConn to send an RPC.
201// Balancer is expected to generate a new picker from its snapshot every time its
202// internal state has changed.
203//
204// The pickers used by gRPC can be updated by ClientConn.UpdateBalancerState().
205type Picker interface {
206 // Pick returns the SubConn to be used to send the RPC.
207 // The returned SubConn must be one returned by NewSubConn().
208 //
209 // This functions is expected to return:
210 // - a SubConn that is known to be READY;
211 // - ErrNoSubConnAvailable if no SubConn is available, but progress is being
212 // made (for example, some SubConn is in CONNECTING mode);
213 // - other errors if no active connecting is happening (for example, all SubConn
214 // are in TRANSIENT_FAILURE mode).
215 //
216 // If a SubConn is returned:
217 // - If it is READY, gRPC will send the RPC on it;
218 // - If it is not ready, or becomes not ready after it's returned, gRPC will block
219 // until UpdateBalancerState() is called and will call pick on the new picker.
220 //
221 // If the returned error is not nil:
222 // - If the error is ErrNoSubConnAvailable, gRPC will block until UpdateBalancerState()
223 // - If the error is ErrTransientFailure:
224 // - If the RPC is wait-for-ready, gRPC will block until UpdateBalancerState()
225 // is called to pick again;
226 // - Otherwise, RPC will fail with unavailable error.
227 // - Else (error is other non-nil error):
228 // - The RPC will fail with unavailable error.
229 //
230 // The returned done() function will be called once the rpc has finished, with the
231 // final status of that RPC.
232 // done may be nil if balancer doesn't care about the RPC status.
233 Pick(ctx context.Context, opts PickOptions) (conn SubConn, done func(DoneInfo), err error)
234}
235
236// Balancer takes input from gRPC, manages SubConns, and collects and aggregates
237// the connectivity states.
238//
239// It also generates and updates the Picker used by gRPC to pick SubConns for RPCs.
240//
241// HandleSubConnectionStateChange, HandleResolvedAddrs and Close are guaranteed
242// to be called synchronously from the same goroutine.
243// There's no guarantee on picker.Pick, it may be called anytime.
244type Balancer interface {
245 // HandleSubConnStateChange is called by gRPC when the connectivity state
246 // of sc has changed.
247 // Balancer is expected to aggregate all the state of SubConn and report
248 // that back to gRPC.
249 // Balancer should also generate and update Pickers when its internal state has
250 // been changed by the new state.
251 HandleSubConnStateChange(sc SubConn, state connectivity.State)
252 // HandleResolvedAddrs is called by gRPC to send updated resolved addresses to
253 // balancers.
254 // Balancer can create new SubConn or remove SubConn with the addresses.
255 // An empty address slice and a non-nil error will be passed if the resolver returns
256 // non-nil error to gRPC.
257 HandleResolvedAddrs([]resolver.Address, error)
258 // Close closes the balancer. The balancer is not required to call
259 // ClientConn.RemoveSubConn for its existing SubConns.
260 Close()
261}
262
263// ConnectivityStateEvaluator takes the connectivity states of multiple SubConns
264// and returns one aggregated connectivity state.
265//
266// It's not thread safe.
267type ConnectivityStateEvaluator struct {
268 numReady uint64 // Number of addrConns in ready state.
269 numConnecting uint64 // Number of addrConns in connecting state.
270 numTransientFailure uint64 // Number of addrConns in transientFailure.
271}
272
273// RecordTransition records state change happening in subConn and based on that
274// it evaluates what aggregated state should be.
275//
276// - If at least one SubConn in Ready, the aggregated state is Ready;
277// - Else if at least one SubConn in Connecting, the aggregated state is Connecting;
278// - Else the aggregated state is TransientFailure.
279//
280// Idle and Shutdown are not considered.
281func (cse *ConnectivityStateEvaluator) RecordTransition(oldState, newState connectivity.State) connectivity.State {
282 // Update counters.
283 for idx, state := range []connectivity.State{oldState, newState} {
284 updateVal := 2*uint64(idx) - 1 // -1 for oldState and +1 for new.
285 switch state {
286 case connectivity.Ready:
287 cse.numReady += updateVal
288 case connectivity.Connecting:
289 cse.numConnecting += updateVal
290 case connectivity.TransientFailure:
291 cse.numTransientFailure += updateVal
292 }
293 }
294
295 // Evaluate.
296 if cse.numReady > 0 {
297 return connectivity.Ready
298 }
299 if cse.numConnecting > 0 {
300 return connectivity.Connecting
301 }
302 return connectivity.TransientFailure
303}
diff --git a/vendor/google.golang.org/grpc/balancer/base/balancer.go b/vendor/google.golang.org/grpc/balancer/base/balancer.go
new file mode 100644
index 0000000..245785e
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer/base/balancer.go
@@ -0,0 +1,171 @@
1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package base
20
21import (
22 "context"
23
24 "google.golang.org/grpc/balancer"
25 "google.golang.org/grpc/connectivity"
26 "google.golang.org/grpc/grpclog"
27 "google.golang.org/grpc/resolver"
28)
29
30type baseBuilder struct {
31 name string
32 pickerBuilder PickerBuilder
33 config Config
34}
35
36func (bb *baseBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer {
37 return &baseBalancer{
38 cc: cc,
39 pickerBuilder: bb.pickerBuilder,
40
41 subConns: make(map[resolver.Address]balancer.SubConn),
42 scStates: make(map[balancer.SubConn]connectivity.State),
43 csEvltr: &balancer.ConnectivityStateEvaluator{},
44 // Initialize picker to a picker that always return
45 // ErrNoSubConnAvailable, because when state of a SubConn changes, we
46 // may call UpdateBalancerState with this picker.
47 picker: NewErrPicker(balancer.ErrNoSubConnAvailable),
48 config: bb.config,
49 }
50}
51
52func (bb *baseBuilder) Name() string {
53 return bb.name
54}
55
56type baseBalancer struct {
57 cc balancer.ClientConn
58 pickerBuilder PickerBuilder
59
60 csEvltr *balancer.ConnectivityStateEvaluator
61 state connectivity.State
62
63 subConns map[resolver.Address]balancer.SubConn
64 scStates map[balancer.SubConn]connectivity.State
65 picker balancer.Picker
66 config Config
67}
68
69func (b *baseBalancer) HandleResolvedAddrs(addrs []resolver.Address, err error) {
70 if err != nil {
71 grpclog.Infof("base.baseBalancer: HandleResolvedAddrs called with error %v", err)
72 return
73 }
74 grpclog.Infoln("base.baseBalancer: got new resolved addresses: ", addrs)
75 // addrsSet is the set converted from addrs, it's used for quick lookup of an address.
76 addrsSet := make(map[resolver.Address]struct{})
77 for _, a := range addrs {
78 addrsSet[a] = struct{}{}
79 if _, ok := b.subConns[a]; !ok {
80 // a is a new address (not existing in b.subConns).
81 sc, err := b.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{HealthCheckEnabled: b.config.HealthCheck})
82 if err != nil {
83 grpclog.Warningf("base.baseBalancer: failed to create new SubConn: %v", err)
84 continue
85 }
86 b.subConns[a] = sc
87 b.scStates[sc] = connectivity.Idle
88 sc.Connect()
89 }
90 }
91 for a, sc := range b.subConns {
92 // a was removed by resolver.
93 if _, ok := addrsSet[a]; !ok {
94 b.cc.RemoveSubConn(sc)
95 delete(b.subConns, a)
96 // Keep the state of this sc in b.scStates until sc's state becomes Shutdown.
97 // The entry will be deleted in HandleSubConnStateChange.
98 }
99 }
100}
101
102// regeneratePicker takes a snapshot of the balancer, and generates a picker
103// from it. The picker is
104// - errPicker with ErrTransientFailure if the balancer is in TransientFailure,
105// - built by the pickerBuilder with all READY SubConns otherwise.
106func (b *baseBalancer) regeneratePicker() {
107 if b.state == connectivity.TransientFailure {
108 b.picker = NewErrPicker(balancer.ErrTransientFailure)
109 return
110 }
111 readySCs := make(map[resolver.Address]balancer.SubConn)
112
113 // Filter out all ready SCs from full subConn map.
114 for addr, sc := range b.subConns {
115 if st, ok := b.scStates[sc]; ok && st == connectivity.Ready {
116 readySCs[addr] = sc
117 }
118 }
119 b.picker = b.pickerBuilder.Build(readySCs)
120}
121
122func (b *baseBalancer) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
123 grpclog.Infof("base.baseBalancer: handle SubConn state change: %p, %v", sc, s)
124 oldS, ok := b.scStates[sc]
125 if !ok {
126 grpclog.Infof("base.baseBalancer: got state changes for an unknown SubConn: %p, %v", sc, s)
127 return
128 }
129 b.scStates[sc] = s
130 switch s {
131 case connectivity.Idle:
132 sc.Connect()
133 case connectivity.Shutdown:
134 // When an address was removed by resolver, b called RemoveSubConn but
135 // kept the sc's state in scStates. Remove state for this sc here.
136 delete(b.scStates, sc)
137 }
138
139 oldAggrState := b.state
140 b.state = b.csEvltr.RecordTransition(oldS, s)
141
142 // Regenerate picker when one of the following happens:
143 // - this sc became ready from not-ready
144 // - this sc became not-ready from ready
145 // - the aggregated state of balancer became TransientFailure from non-TransientFailure
146 // - the aggregated state of balancer became non-TransientFailure from TransientFailure
147 if (s == connectivity.Ready) != (oldS == connectivity.Ready) ||
148 (b.state == connectivity.TransientFailure) != (oldAggrState == connectivity.TransientFailure) {
149 b.regeneratePicker()
150 }
151
152 b.cc.UpdateBalancerState(b.state, b.picker)
153}
154
155// Close is a nop because base balancer doesn't have internal state to clean up,
156// and it doesn't need to call RemoveSubConn for the SubConns.
157func (b *baseBalancer) Close() {
158}
159
160// NewErrPicker returns a picker that always returns err on Pick().
161func NewErrPicker(err error) balancer.Picker {
162 return &errPicker{err: err}
163}
164
165type errPicker struct {
166 err error // Pick() always returns this err.
167}
168
169func (p *errPicker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
170 return nil, nil, p.err
171}
diff --git a/vendor/google.golang.org/grpc/balancer/base/base.go b/vendor/google.golang.org/grpc/balancer/base/base.go
new file mode 100644
index 0000000..34b1f29
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer/base/base.go
@@ -0,0 +1,64 @@
1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// Package base defines a balancer base that can be used to build balancers with
20// different picking algorithms.
21//
22// The base balancer creates a new SubConn for each resolved address. The
23// provided picker will only be notified about READY SubConns.
24//
25// This package is the base of round_robin balancer, its purpose is to be used
26// to build round_robin like balancers with complex picking algorithms.
27// Balancers with more complicated logic should try to implement a balancer
28// builder from scratch.
29//
30// All APIs in this package are experimental.
31package base
32
33import (
34 "google.golang.org/grpc/balancer"
35 "google.golang.org/grpc/resolver"
36)
37
38// PickerBuilder creates balancer.Picker.
39type PickerBuilder interface {
40 // Build takes a slice of ready SubConns, and returns a picker that will be
41 // used by gRPC to pick a SubConn.
42 Build(readySCs map[resolver.Address]balancer.SubConn) balancer.Picker
43}
44
45// NewBalancerBuilder returns a balancer builder. The balancers
46// built by this builder will use the picker builder to build pickers.
47func NewBalancerBuilder(name string, pb PickerBuilder) balancer.Builder {
48 return NewBalancerBuilderWithConfig(name, pb, Config{})
49}
50
51// Config contains the config info about the base balancer builder.
52type Config struct {
53 // HealthCheck indicates whether health checking should be enabled for this specific balancer.
54 HealthCheck bool
55}
56
57// NewBalancerBuilderWithConfig returns a base balancer builder configured by the provided config.
58func NewBalancerBuilderWithConfig(name string, pb PickerBuilder, config Config) balancer.Builder {
59 return &baseBuilder{
60 name: name,
61 pickerBuilder: pb,
62 config: config,
63 }
64}
diff --git a/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go b/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
new file mode 100644
index 0000000..57aea9f
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
@@ -0,0 +1,79 @@
1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// Package roundrobin defines a roundrobin balancer. Roundrobin balancer is
20// installed as one of the default balancers in gRPC, users don't need to
21// explicitly install this balancer.
22package roundrobin
23
24import (
25 "context"
26 "sync"
27
28 "google.golang.org/grpc/balancer"
29 "google.golang.org/grpc/balancer/base"
30 "google.golang.org/grpc/grpclog"
31 "google.golang.org/grpc/resolver"
32)
33
34// Name is the name of round_robin balancer.
35const Name = "round_robin"
36
37// newBuilder creates a new roundrobin balancer builder.
38func newBuilder() balancer.Builder {
39 return base.NewBalancerBuilderWithConfig(Name, &rrPickerBuilder{}, base.Config{HealthCheck: true})
40}
41
42func init() {
43 balancer.Register(newBuilder())
44}
45
46type rrPickerBuilder struct{}
47
48func (*rrPickerBuilder) Build(readySCs map[resolver.Address]balancer.SubConn) balancer.Picker {
49 grpclog.Infof("roundrobinPicker: newPicker called with readySCs: %v", readySCs)
50 var scs []balancer.SubConn
51 for _, sc := range readySCs {
52 scs = append(scs, sc)
53 }
54 return &rrPicker{
55 subConns: scs,
56 }
57}
58
59type rrPicker struct {
60 // subConns is the snapshot of the roundrobin balancer when this picker was
61 // created. The slice is immutable. Each Get() will do a round robin
62 // selection from it and return the selected SubConn.
63 subConns []balancer.SubConn
64
65 mu sync.Mutex
66 next int
67}
68
69func (p *rrPicker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
70 if len(p.subConns) <= 0 {
71 return nil, nil, balancer.ErrNoSubConnAvailable
72 }
73
74 p.mu.Lock()
75 sc := p.subConns[p.next]
76 p.next = (p.next + 1) % len(p.subConns)
77 p.mu.Unlock()
78 return sc, nil, nil
79}
diff --git a/vendor/google.golang.org/grpc/balancer_conn_wrappers.go b/vendor/google.golang.org/grpc/balancer_conn_wrappers.go
new file mode 100644
index 0000000..7233ade
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer_conn_wrappers.go
@@ -0,0 +1,328 @@
1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package grpc
20
21import (
22 "fmt"
23 "sync"
24
25 "google.golang.org/grpc/balancer"
26 "google.golang.org/grpc/connectivity"
27 "google.golang.org/grpc/grpclog"
28 "google.golang.org/grpc/resolver"
29)
30
31// scStateUpdate contains the subConn and the new state it changed to.
32type scStateUpdate struct {
33 sc balancer.SubConn
34 state connectivity.State
35}
36
37// scStateUpdateBuffer is an unbounded channel for scStateChangeTuple.
38// TODO make a general purpose buffer that uses interface{}.
39type scStateUpdateBuffer struct {
40 c chan *scStateUpdate
41 mu sync.Mutex
42 backlog []*scStateUpdate
43}
44
45func newSCStateUpdateBuffer() *scStateUpdateBuffer {
46 return &scStateUpdateBuffer{
47 c: make(chan *scStateUpdate, 1),
48 }
49}
50
51func (b *scStateUpdateBuffer) put(t *scStateUpdate) {
52 b.mu.Lock()
53 defer b.mu.Unlock()
54 if len(b.backlog) == 0 {
55 select {
56 case b.c <- t:
57 return
58 default:
59 }
60 }
61 b.backlog = append(b.backlog, t)
62}
63
64func (b *scStateUpdateBuffer) load() {
65 b.mu.Lock()
66 defer b.mu.Unlock()
67 if len(b.backlog) > 0 {
68 select {
69 case b.c <- b.backlog[0]:
70 b.backlog[0] = nil
71 b.backlog = b.backlog[1:]
72 default:
73 }
74 }
75}
76
77// get returns the channel that the scStateUpdate will be sent to.
78//
79// Upon receiving, the caller should call load to send another
80// scStateChangeTuple onto the channel if there is any.
81func (b *scStateUpdateBuffer) get() <-chan *scStateUpdate {
82 return b.c
83}
84
85// resolverUpdate contains the new resolved addresses or error if there's
86// any.
87type resolverUpdate struct {
88 addrs []resolver.Address
89 err error
90}
91
92// ccBalancerWrapper is a wrapper on top of cc for balancers.
93// It implements balancer.ClientConn interface.
94type ccBalancerWrapper struct {
95 cc *ClientConn
96 balancer balancer.Balancer
97 stateChangeQueue *scStateUpdateBuffer
98 resolverUpdateCh chan *resolverUpdate
99 done chan struct{}
100
101 mu sync.Mutex
102 subConns map[*acBalancerWrapper]struct{}
103}
104
105func newCCBalancerWrapper(cc *ClientConn, b balancer.Builder, bopts balancer.BuildOptions) *ccBalancerWrapper {
106 ccb := &ccBalancerWrapper{
107 cc: cc,
108 stateChangeQueue: newSCStateUpdateBuffer(),
109 resolverUpdateCh: make(chan *resolverUpdate, 1),
110 done: make(chan struct{}),
111 subConns: make(map[*acBalancerWrapper]struct{}),
112 }
113 go ccb.watcher()
114 ccb.balancer = b.Build(ccb, bopts)
115 return ccb
116}
117
118// watcher balancer functions sequentially, so the balancer can be implemented
119// lock-free.
120func (ccb *ccBalancerWrapper) watcher() {
121 for {
122 select {
123 case t := <-ccb.stateChangeQueue.get():
124 ccb.stateChangeQueue.load()
125 select {
126 case <-ccb.done:
127 ccb.balancer.Close()
128 return
129 default:
130 }
131 ccb.balancer.HandleSubConnStateChange(t.sc, t.state)
132 case t := <-ccb.resolverUpdateCh:
133 select {
134 case <-ccb.done:
135 ccb.balancer.Close()
136 return
137 default:
138 }
139 ccb.balancer.HandleResolvedAddrs(t.addrs, t.err)
140 case <-ccb.done:
141 }
142
143 select {
144 case <-ccb.done:
145 ccb.balancer.Close()
146 ccb.mu.Lock()
147 scs := ccb.subConns
148 ccb.subConns = nil
149 ccb.mu.Unlock()
150 for acbw := range scs {
151 ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
152 }
153 return
154 default:
155 }
156 }
157}
158
159func (ccb *ccBalancerWrapper) close() {
160 close(ccb.done)
161}
162
163func (ccb *ccBalancerWrapper) handleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
164 // When updating addresses for a SubConn, if the address in use is not in
165 // the new addresses, the old ac will be tearDown() and a new ac will be
166 // created. tearDown() generates a state change with Shutdown state, we
167 // don't want the balancer to receive this state change. So before
168 // tearDown() on the old ac, ac.acbw (acWrapper) will be set to nil, and
169 // this function will be called with (nil, Shutdown). We don't need to call
170 // balancer method in this case.
171 if sc == nil {
172 return
173 }
174 ccb.stateChangeQueue.put(&scStateUpdate{
175 sc: sc,
176 state: s,
177 })
178}
179
180func (ccb *ccBalancerWrapper) handleResolvedAddrs(addrs []resolver.Address, err error) {
181 if ccb.cc.curBalancerName != grpclbName {
182 var containsGRPCLB bool
183 for _, a := range addrs {
184 if a.Type == resolver.GRPCLB {
185 containsGRPCLB = true
186 break
187 }
188 }
189 if containsGRPCLB {
190 // The current balancer is not grpclb, but addresses contain grpclb
191 // address. This means we failed to switch to grpclb, most likely
192 // because grpclb is not registered. Filter out all grpclb addresses
193 // from addrs before sending to balancer.
194 tempAddrs := make([]resolver.Address, 0, len(addrs))
195 for _, a := range addrs {
196 if a.Type != resolver.GRPCLB {
197 tempAddrs = append(tempAddrs, a)
198 }
199 }
200 addrs = tempAddrs
201 }
202 }
203 select {
204 case <-ccb.resolverUpdateCh:
205 default:
206 }
207 ccb.resolverUpdateCh <- &resolverUpdate{
208 addrs: addrs,
209 err: err,
210 }
211}
212
213func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
214 if len(addrs) <= 0 {
215 return nil, fmt.Errorf("grpc: cannot create SubConn with empty address list")
216 }
217 ccb.mu.Lock()
218 defer ccb.mu.Unlock()
219 if ccb.subConns == nil {
220 return nil, fmt.Errorf("grpc: ClientConn balancer wrapper was closed")
221 }
222 ac, err := ccb.cc.newAddrConn(addrs, opts)
223 if err != nil {
224 return nil, err
225 }
226 acbw := &acBalancerWrapper{ac: ac}
227 acbw.ac.mu.Lock()
228 ac.acbw = acbw
229 acbw.ac.mu.Unlock()
230 ccb.subConns[acbw] = struct{}{}
231 return acbw, nil
232}
233
234func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) {
235 acbw, ok := sc.(*acBalancerWrapper)
236 if !ok {
237 return
238 }
239 ccb.mu.Lock()
240 defer ccb.mu.Unlock()
241 if ccb.subConns == nil {
242 return
243 }
244 delete(ccb.subConns, acbw)
245 ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
246}
247
248func (ccb *ccBalancerWrapper) UpdateBalancerState(s connectivity.State, p balancer.Picker) {
249 ccb.mu.Lock()
250 defer ccb.mu.Unlock()
251 if ccb.subConns == nil {
252 return
253 }
254 // Update picker before updating state. Even though the ordering here does
255 // not matter, it can lead to multiple calls of Pick in the common start-up
256 // case where we wait for ready and then perform an RPC. If the picker is
257 // updated later, we could call the "connecting" picker when the state is
258 // updated, and then call the "ready" picker after the picker gets updated.
259 ccb.cc.blockingpicker.updatePicker(p)
260 ccb.cc.csMgr.updateState(s)
261}
262
263func (ccb *ccBalancerWrapper) ResolveNow(o resolver.ResolveNowOption) {
264 ccb.cc.resolveNow(o)
265}
266
267func (ccb *ccBalancerWrapper) Target() string {
268 return ccb.cc.target
269}
270
271// acBalancerWrapper is a wrapper on top of ac for balancers.
272// It implements balancer.SubConn interface.
273type acBalancerWrapper struct {
274 mu sync.Mutex
275 ac *addrConn
276}
277
278func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
279 acbw.mu.Lock()
280 defer acbw.mu.Unlock()
281 if len(addrs) <= 0 {
282 acbw.ac.tearDown(errConnDrain)
283 return
284 }
285 if !acbw.ac.tryUpdateAddrs(addrs) {
286 cc := acbw.ac.cc
287 opts := acbw.ac.scopts
288 acbw.ac.mu.Lock()
289 // Set old ac.acbw to nil so the Shutdown state update will be ignored
290 // by balancer.
291 //
292 // TODO(bar) the state transition could be wrong when tearDown() old ac
293 // and creating new ac, fix the transition.
294 acbw.ac.acbw = nil
295 acbw.ac.mu.Unlock()
296 acState := acbw.ac.getState()
297 acbw.ac.tearDown(errConnDrain)
298
299 if acState == connectivity.Shutdown {
300 return
301 }
302
303 ac, err := cc.newAddrConn(addrs, opts)
304 if err != nil {
305 grpclog.Warningf("acBalancerWrapper: UpdateAddresses: failed to newAddrConn: %v", err)
306 return
307 }
308 acbw.ac = ac
309 ac.mu.Lock()
310 ac.acbw = acbw
311 ac.mu.Unlock()
312 if acState != connectivity.Idle {
313 ac.connect()
314 }
315 }
316}
317
318func (acbw *acBalancerWrapper) Connect() {
319 acbw.mu.Lock()
320 defer acbw.mu.Unlock()
321 acbw.ac.connect()
322}
323
324func (acbw *acBalancerWrapper) getAddrConn() *addrConn {
325 acbw.mu.Lock()
326 defer acbw.mu.Unlock()
327 return acbw.ac
328}
diff --git a/vendor/google.golang.org/grpc/balancer_v1_wrapper.go b/vendor/google.golang.org/grpc/balancer_v1_wrapper.go
new file mode 100644
index 0000000..42b60fe
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer_v1_wrapper.go
@@ -0,0 +1,326 @@
1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package grpc
20
21import (
22 "context"
23 "strings"
24 "sync"
25
26 "google.golang.org/grpc/balancer"
27 "google.golang.org/grpc/connectivity"
28 "google.golang.org/grpc/grpclog"
29 "google.golang.org/grpc/resolver"
30)
31
32type balancerWrapperBuilder struct {
33 b Balancer // The v1 balancer.
34}
35
36func (bwb *balancerWrapperBuilder) Build(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.Balancer {
37 targetAddr := cc.Target()
38 targetSplitted := strings.Split(targetAddr, ":///")
39 if len(targetSplitted) >= 2 {
40 targetAddr = targetSplitted[1]
41 }
42
43 bwb.b.Start(targetAddr, BalancerConfig{
44 DialCreds: opts.DialCreds,
45 Dialer: opts.Dialer,
46 })
47 _, pickfirst := bwb.b.(*pickFirst)
48 bw := &balancerWrapper{
49 balancer: bwb.b,
50 pickfirst: pickfirst,
51 cc: cc,
52 targetAddr: targetAddr,
53 startCh: make(chan struct{}),
54 conns: make(map[resolver.Address]balancer.SubConn),
55 connSt: make(map[balancer.SubConn]*scState),
56 csEvltr: &balancer.ConnectivityStateEvaluator{},
57 state: connectivity.Idle,
58 }
59 cc.UpdateBalancerState(connectivity.Idle, bw)
60 go bw.lbWatcher()
61 return bw
62}
63
64func (bwb *balancerWrapperBuilder) Name() string {
65 return "wrapper"
66}
67
68type scState struct {
69 addr Address // The v1 address type.
70 s connectivity.State
71 down func(error)
72}
73
74type balancerWrapper struct {
75 balancer Balancer // The v1 balancer.
76 pickfirst bool
77
78 cc balancer.ClientConn
79 targetAddr string // Target without the scheme.
80
81 mu sync.Mutex
82 conns map[resolver.Address]balancer.SubConn
83 connSt map[balancer.SubConn]*scState
84 // This channel is closed when handling the first resolver result.
85 // lbWatcher blocks until this is closed, to avoid race between
86 // - NewSubConn is created, cc wants to notify balancer of state changes;
87 // - Build hasn't return, cc doesn't have access to balancer.
88 startCh chan struct{}
89
90 // To aggregate the connectivity state.
91 csEvltr *balancer.ConnectivityStateEvaluator
92 state connectivity.State
93}
94
95// lbWatcher watches the Notify channel of the balancer and manages
96// connections accordingly.
97func (bw *balancerWrapper) lbWatcher() {
98 <-bw.startCh
99 notifyCh := bw.balancer.Notify()
100 if notifyCh == nil {
101 // There's no resolver in the balancer. Connect directly.
102 a := resolver.Address{
103 Addr: bw.targetAddr,
104 Type: resolver.Backend,
105 }
106 sc, err := bw.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{})
107 if err != nil {
108 grpclog.Warningf("Error creating connection to %v. Err: %v", a, err)
109 } else {
110 bw.mu.Lock()
111 bw.conns[a] = sc
112 bw.connSt[sc] = &scState{
113 addr: Address{Addr: bw.targetAddr},
114 s: connectivity.Idle,
115 }
116 bw.mu.Unlock()
117 sc.Connect()
118 }
119 return
120 }
121
122 for addrs := range notifyCh {
123 grpclog.Infof("balancerWrapper: got update addr from Notify: %v\n", addrs)
124 if bw.pickfirst {
125 var (
126 oldA resolver.Address
127 oldSC balancer.SubConn
128 )
129 bw.mu.Lock()
130 for oldA, oldSC = range bw.conns {
131 break
132 }
133 bw.mu.Unlock()
134 if len(addrs) <= 0 {
135 if oldSC != nil {
136 // Teardown old sc.
137 bw.mu.Lock()
138 delete(bw.conns, oldA)
139 delete(bw.connSt, oldSC)
140 bw.mu.Unlock()
141 bw.cc.RemoveSubConn(oldSC)
142 }
143 continue
144 }
145
146 var newAddrs []resolver.Address
147 for _, a := range addrs {
148 newAddr := resolver.Address{
149 Addr: a.Addr,
150 Type: resolver.Backend, // All addresses from balancer are all backends.
151 ServerName: "",
152 Metadata: a.Metadata,
153 }
154 newAddrs = append(newAddrs, newAddr)
155 }
156 if oldSC == nil {
157 // Create new sc.
158 sc, err := bw.cc.NewSubConn(newAddrs, balancer.NewSubConnOptions{})
159 if err != nil {
160 grpclog.Warningf("Error creating connection to %v. Err: %v", newAddrs, err)
161 } else {
162 bw.mu.Lock()
163 // For pickfirst, there should be only one SubConn, so the
164 // address doesn't matter. All states updating (up and down)
165 // and picking should all happen on that only SubConn.
166 bw.conns[resolver.Address{}] = sc
167 bw.connSt[sc] = &scState{
168 addr: addrs[0], // Use the first address.
169 s: connectivity.Idle,
170 }
171 bw.mu.Unlock()
172 sc.Connect()
173 }
174 } else {
175 bw.mu.Lock()
176 bw.connSt[oldSC].addr = addrs[0]
177 bw.mu.Unlock()
178 oldSC.UpdateAddresses(newAddrs)
179 }
180 } else {
181 var (
182 add []resolver.Address // Addresses need to setup connections.
183 del []balancer.SubConn // Connections need to tear down.
184 )
185 resAddrs := make(map[resolver.Address]Address)
186 for _, a := range addrs {
187 resAddrs[resolver.Address{
188 Addr: a.Addr,
189 Type: resolver.Backend, // All addresses from balancer are all backends.
190 ServerName: "",
191 Metadata: a.Metadata,
192 }] = a
193 }
194 bw.mu.Lock()
195 for a := range resAddrs {
196 if _, ok := bw.conns[a]; !ok {
197 add = append(add, a)
198 }
199 }
200 for a, c := range bw.conns {
201 if _, ok := resAddrs[a]; !ok {
202 del = append(del, c)
203 delete(bw.conns, a)
204 // Keep the state of this sc in bw.connSt until its state becomes Shutdown.
205 }
206 }
207 bw.mu.Unlock()
208 for _, a := range add {
209 sc, err := bw.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{})
210 if err != nil {
211 grpclog.Warningf("Error creating connection to %v. Err: %v", a, err)
212 } else {
213 bw.mu.Lock()
214 bw.conns[a] = sc
215 bw.connSt[sc] = &scState{
216 addr: resAddrs[a],
217 s: connectivity.Idle,
218 }
219 bw.mu.Unlock()
220 sc.Connect()
221 }
222 }
223 for _, c := range del {
224 bw.cc.RemoveSubConn(c)
225 }
226 }
227 }
228}
229
230func (bw *balancerWrapper) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
231 bw.mu.Lock()
232 defer bw.mu.Unlock()
233 scSt, ok := bw.connSt[sc]
234 if !ok {
235 return
236 }
237 if s == connectivity.Idle {
238 sc.Connect()
239 }
240 oldS := scSt.s
241 scSt.s = s
242 if oldS != connectivity.Ready && s == connectivity.Ready {
243 scSt.down = bw.balancer.Up(scSt.addr)
244 } else if oldS == connectivity.Ready && s != connectivity.Ready {
245 if scSt.down != nil {
246 scSt.down(errConnClosing)
247 }
248 }
249 sa := bw.csEvltr.RecordTransition(oldS, s)
250 if bw.state != sa {
251 bw.state = sa
252 }
253 bw.cc.UpdateBalancerState(bw.state, bw)
254 if s == connectivity.Shutdown {
255 // Remove state for this sc.
256 delete(bw.connSt, sc)
257 }
258}
259
260func (bw *balancerWrapper) HandleResolvedAddrs([]resolver.Address, error) {
261 bw.mu.Lock()
262 defer bw.mu.Unlock()
263 select {
264 case <-bw.startCh:
265 default:
266 close(bw.startCh)
267 }
268 // There should be a resolver inside the balancer.
269 // All updates here, if any, are ignored.
270}
271
272func (bw *balancerWrapper) Close() {
273 bw.mu.Lock()
274 defer bw.mu.Unlock()
275 select {
276 case <-bw.startCh:
277 default:
278 close(bw.startCh)
279 }
280 bw.balancer.Close()
281}
282
283// The picker is the balancerWrapper itself.
284// Pick should never return ErrNoSubConnAvailable.
285// It either blocks or returns error, consistent with v1 balancer Get().
286func (bw *balancerWrapper) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
287 failfast := true // Default failfast is true.
288 if ss, ok := rpcInfoFromContext(ctx); ok {
289 failfast = ss.failfast
290 }
291 a, p, err := bw.balancer.Get(ctx, BalancerGetOptions{BlockingWait: !failfast})
292 if err != nil {
293 return nil, nil, err
294 }
295 var done func(balancer.DoneInfo)
296 if p != nil {
297 done = func(i balancer.DoneInfo) { p() }
298 }
299 var sc balancer.SubConn
300 bw.mu.Lock()
301 defer bw.mu.Unlock()
302 if bw.pickfirst {
303 // Get the first sc in conns.
304 for _, sc = range bw.conns {
305 break
306 }
307 } else {
308 var ok bool
309 sc, ok = bw.conns[resolver.Address{
310 Addr: a.Addr,
311 Type: resolver.Backend,
312 ServerName: "",
313 Metadata: a.Metadata,
314 }]
315 if !ok && failfast {
316 return nil, nil, balancer.ErrTransientFailure
317 }
318 if s, ok := bw.connSt[sc]; failfast && (!ok || s.s != connectivity.Ready) {
319 // If the returned sc is not ready and RPC is failfast,
320 // return error, and this RPC will fail.
321 return nil, nil, balancer.ErrTransientFailure
322 }
323 }
324
325 return sc, done, nil
326}
diff --git a/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go b/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go
new file mode 100644
index 0000000..f393bb6
--- /dev/null
+++ b/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go
@@ -0,0 +1,900 @@
1// Code generated by protoc-gen-go. DO NOT EDIT.
2// source: grpc/binarylog/grpc_binarylog_v1/binarylog.proto
3
4package grpc_binarylog_v1 // import "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
5
6import proto "github.com/golang/protobuf/proto"
7import fmt "fmt"
8import math "math"
9import duration "github.com/golang/protobuf/ptypes/duration"
10import timestamp "github.com/golang/protobuf/ptypes/timestamp"
11
12// Reference imports to suppress errors if they are not otherwise used.
13var _ = proto.Marshal
14var _ = fmt.Errorf
15var _ = math.Inf
16
17// This is a compile-time assertion to ensure that this generated file
18// is compatible with the proto package it is being compiled against.
19// A compilation error at this line likely means your copy of the
20// proto package needs to be updated.
21const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
22
23// Enumerates the type of event
24// Note the terminology is different from the RPC semantics
25// definition, but the same meaning is expressed here.
26type GrpcLogEntry_EventType int32
27
28const (
29 GrpcLogEntry_EVENT_TYPE_UNKNOWN GrpcLogEntry_EventType = 0
30 // Header sent from client to server
31 GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER GrpcLogEntry_EventType = 1
32 // Header sent from server to client
33 GrpcLogEntry_EVENT_TYPE_SERVER_HEADER GrpcLogEntry_EventType = 2
34 // Message sent from client to server
35 GrpcLogEntry_EVENT_TYPE_CLIENT_MESSAGE GrpcLogEntry_EventType = 3
36 // Message sent from server to client
37 GrpcLogEntry_EVENT_TYPE_SERVER_MESSAGE GrpcLogEntry_EventType = 4
38 // A signal that client is done sending
39 GrpcLogEntry_EVENT_TYPE_CLIENT_HALF_CLOSE GrpcLogEntry_EventType = 5
40 // Trailer indicates the end of the RPC.
41 // On client side, this event means a trailer was either received
42 // from the network or the gRPC library locally generated a status
43 // to inform the application about a failure.
44 // On server side, this event means the server application requested
45 // to send a trailer. Note: EVENT_TYPE_CANCEL may still arrive after
46 // this due to races on server side.
47 GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER GrpcLogEntry_EventType = 6
48 // A signal that the RPC is cancelled. On client side, this
49 // indicates the client application requests a cancellation.
50 // On server side, this indicates that cancellation was detected.
51 // Note: This marks the end of the RPC. Events may arrive after
52 // this due to races. For example, on client side a trailer
53 // may arrive even though the application requested to cancel the RPC.
54 GrpcLogEntry_EVENT_TYPE_CANCEL GrpcLogEntry_EventType = 7
55)
56
57var GrpcLogEntry_EventType_name = map[int32]string{
58 0: "EVENT_TYPE_UNKNOWN",
59 1: "EVENT_TYPE_CLIENT_HEADER",
60 2: "EVENT_TYPE_SERVER_HEADER",
61 3: "EVENT_TYPE_CLIENT_MESSAGE",
62 4: "EVENT_TYPE_SERVER_MESSAGE",
63 5: "EVENT_TYPE_CLIENT_HALF_CLOSE",
64 6: "EVENT_TYPE_SERVER_TRAILER",
65 7: "EVENT_TYPE_CANCEL",
66}
67var GrpcLogEntry_EventType_value = map[string]int32{
68 "EVENT_TYPE_UNKNOWN": 0,
69 "EVENT_TYPE_CLIENT_HEADER": 1,
70 "EVENT_TYPE_SERVER_HEADER": 2,
71 "EVENT_TYPE_CLIENT_MESSAGE": 3,
72 "EVENT_TYPE_SERVER_MESSAGE": 4,
73 "EVENT_TYPE_CLIENT_HALF_CLOSE": 5,
74 "EVENT_TYPE_SERVER_TRAILER": 6,
75 "EVENT_TYPE_CANCEL": 7,
76}
77
78func (x GrpcLogEntry_EventType) String() string {
79 return proto.EnumName(GrpcLogEntry_EventType_name, int32(x))
80}
81func (GrpcLogEntry_EventType) EnumDescriptor() ([]byte, []int) {
82 return fileDescriptor_binarylog_264c8c9c551ce911, []int{0, 0}
83}
84
85// Enumerates the entity that generates the log entry
86type GrpcLogEntry_Logger int32
87
88const (
89 GrpcLogEntry_LOGGER_UNKNOWN GrpcLogEntry_Logger = 0
90 GrpcLogEntry_LOGGER_CLIENT GrpcLogEntry_Logger = 1
91 GrpcLogEntry_LOGGER_SERVER GrpcLogEntry_Logger = 2
92)
93
94var GrpcLogEntry_Logger_name = map[int32]string{
95 0: "LOGGER_UNKNOWN",
96 1: "LOGGER_CLIENT",
97 2: "LOGGER_SERVER",
98}
99var GrpcLogEntry_Logger_value = map[string]int32{
100 "LOGGER_UNKNOWN": 0,
101 "LOGGER_CLIENT": 1,
102 "LOGGER_SERVER": 2,
103}
104
105func (x GrpcLogEntry_Logger) String() string {
106 return proto.EnumName(GrpcLogEntry_Logger_name, int32(x))
107}
108func (GrpcLogEntry_Logger) EnumDescriptor() ([]byte, []int) {
109 return fileDescriptor_binarylog_264c8c9c551ce911, []int{0, 1}
110}
111
112type Address_Type int32
113
114const (
115 Address_TYPE_UNKNOWN Address_Type = 0
116 // address is in 1.2.3.4 form
117 Address_TYPE_IPV4 Address_Type = 1
118 // address is in IPv6 canonical form (RFC5952 section 4)
119 // The scope is NOT included in the address string.
120 Address_TYPE_IPV6 Address_Type = 2
121 // address is UDS string
122 Address_TYPE_UNIX Address_Type = 3
123)
124
125var Address_Type_name = map[int32]string{
126 0: "TYPE_UNKNOWN",
127 1: "TYPE_IPV4",
128 2: "TYPE_IPV6",
129 3: "TYPE_UNIX",
130}
131var Address_Type_value = map[string]int32{
132 "TYPE_UNKNOWN": 0,
133 "TYPE_IPV4": 1,
134 "TYPE_IPV6": 2,
135 "TYPE_UNIX": 3,
136}
137
138func (x Address_Type) String() string {
139 return proto.EnumName(Address_Type_name, int32(x))
140}
141func (Address_Type) EnumDescriptor() ([]byte, []int) {
142 return fileDescriptor_binarylog_264c8c9c551ce911, []int{7, 0}
143}
144
145// Log entry we store in binary logs
146type GrpcLogEntry struct {
147 // The timestamp of the binary log message
148 Timestamp *timestamp.Timestamp `protobuf:"bytes,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
149 // Uniquely identifies a call. The value must not be 0 in order to disambiguate
150 // from an unset value.
151 // Each call may have several log entries, they will all have the same call_id.
152 // Nothing is guaranteed about their value other than they are unique across
153 // different RPCs in the same gRPC process.
154 CallId uint64 `protobuf:"varint,2,opt,name=call_id,json=callId,proto3" json:"call_id,omitempty"`
155 // The entry sequence id for this call. The first GrpcLogEntry has a
156 // value of 1, to disambiguate from an unset value. The purpose of
157 // this field is to detect missing entries in environments where
158 // durability or ordering is not guaranteed.
159 SequenceIdWithinCall uint64 `protobuf:"varint,3,opt,name=sequence_id_within_call,json=sequenceIdWithinCall,proto3" json:"sequence_id_within_call,omitempty"`
160 Type GrpcLogEntry_EventType `protobuf:"varint,4,opt,name=type,proto3,enum=grpc.binarylog.v1.GrpcLogEntry_EventType" json:"type,omitempty"`
161 Logger GrpcLogEntry_Logger `protobuf:"varint,5,opt,name=logger,proto3,enum=grpc.binarylog.v1.GrpcLogEntry_Logger" json:"logger,omitempty"`
162 // The logger uses one of the following fields to record the payload,
163 // according to the type of the log entry.
164 //
165 // Types that are valid to be assigned to Payload:
166 // *GrpcLogEntry_ClientHeader
167 // *GrpcLogEntry_ServerHeader
168 // *GrpcLogEntry_Message
169 // *GrpcLogEntry_Trailer
170 Payload isGrpcLogEntry_Payload `protobuf_oneof:"payload"`
171 // true if payload does not represent the full message or metadata.
172 PayloadTruncated bool `protobuf:"varint,10,opt,name=payload_truncated,json=payloadTruncated,proto3" json:"payload_truncated,omitempty"`
173 // Peer address information, will only be recorded on the first
174 // incoming event. On client side, peer is logged on
175 // EVENT_TYPE_SERVER_HEADER normally or EVENT_TYPE_SERVER_TRAILER in
176 // the case of trailers-only. On server side, peer is always
177 // logged on EVENT_TYPE_CLIENT_HEADER.
178 Peer *Address `protobuf:"bytes,11,opt,name=peer,proto3" json:"peer,omitempty"`
179 XXX_NoUnkeyedLiteral struct{} `json:"-"`
180 XXX_unrecognized []byte `json:"-"`
181 XXX_sizecache int32 `json:"-"`
182}
183
184func (m *GrpcLogEntry) Reset() { *m = GrpcLogEntry{} }
185func (m *GrpcLogEntry) String() string { return proto.CompactTextString(m) }
186func (*GrpcLogEntry) ProtoMessage() {}
187func (*GrpcLogEntry) Descriptor() ([]byte, []int) {
188 return fileDescriptor_binarylog_264c8c9c551ce911, []int{0}
189}
190func (m *GrpcLogEntry) XXX_Unmarshal(b []byte) error {
191 return xxx_messageInfo_GrpcLogEntry.Unmarshal(m, b)
192}
193func (m *GrpcLogEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
194 return xxx_messageInfo_GrpcLogEntry.Marshal(b, m, deterministic)
195}
196func (dst *GrpcLogEntry) XXX_Merge(src proto.Message) {
197 xxx_messageInfo_GrpcLogEntry.Merge(dst, src)
198}
199func (m *GrpcLogEntry) XXX_Size() int {
200 return xxx_messageInfo_GrpcLogEntry.Size(m)
201}
202func (m *GrpcLogEntry) XXX_DiscardUnknown() {
203 xxx_messageInfo_GrpcLogEntry.DiscardUnknown(m)
204}
205
206var xxx_messageInfo_GrpcLogEntry proto.InternalMessageInfo
207
208func (m *GrpcLogEntry) GetTimestamp() *timestamp.Timestamp {
209 if m != nil {
210 return m.Timestamp
211 }
212 return nil
213}
214
215func (m *GrpcLogEntry) GetCallId() uint64 {
216 if m != nil {
217 return m.CallId
218 }
219 return 0
220}
221
222func (m *GrpcLogEntry) GetSequenceIdWithinCall() uint64 {
223 if m != nil {
224 return m.SequenceIdWithinCall
225 }
226 return 0
227}
228
229func (m *GrpcLogEntry) GetType() GrpcLogEntry_EventType {
230 if m != nil {
231 return m.Type
232 }
233 return GrpcLogEntry_EVENT_TYPE_UNKNOWN
234}
235
236func (m *GrpcLogEntry) GetLogger() GrpcLogEntry_Logger {
237 if m != nil {
238 return m.Logger
239 }
240 return GrpcLogEntry_LOGGER_UNKNOWN
241}
242
243type isGrpcLogEntry_Payload interface {
244 isGrpcLogEntry_Payload()
245}
246
247type GrpcLogEntry_ClientHeader struct {
248 ClientHeader *ClientHeader `protobuf:"bytes,6,opt,name=client_header,json=clientHeader,proto3,oneof"`
249}
250
251type GrpcLogEntry_ServerHeader struct {
252 ServerHeader *ServerHeader `protobuf:"bytes,7,opt,name=server_header,json=serverHeader,proto3,oneof"`
253}
254
255type GrpcLogEntry_Message struct {
256 Message *Message `protobuf:"bytes,8,opt,name=message,proto3,oneof"`
257}
258
259type GrpcLogEntry_Trailer struct {
260 Trailer *Trailer `protobuf:"bytes,9,opt,name=trailer,proto3,oneof"`
261}
262
263func (*GrpcLogEntry_ClientHeader) isGrpcLogEntry_Payload() {}
264
265func (*GrpcLogEntry_ServerHeader) isGrpcLogEntry_Payload() {}
266
267func (*GrpcLogEntry_Message) isGrpcLogEntry_Payload() {}
268
269func (*GrpcLogEntry_Trailer) isGrpcLogEntry_Payload() {}
270
271func (m *GrpcLogEntry) GetPayload() isGrpcLogEntry_Payload {
272 if m != nil {
273 return m.Payload
274 }
275 return nil
276}
277
278func (m *GrpcLogEntry) GetClientHeader() *ClientHeader {
279 if x, ok := m.GetPayload().(*GrpcLogEntry_ClientHeader); ok {
280 return x.ClientHeader
281 }
282 return nil
283}
284
285func (m *GrpcLogEntry) GetServerHeader() *ServerHeader {
286 if x, ok := m.GetPayload().(*GrpcLogEntry_ServerHeader); ok {
287 return x.ServerHeader
288 }
289 return nil
290}
291
292func (m *GrpcLogEntry) GetMessage() *Message {
293 if x, ok := m.GetPayload().(*GrpcLogEntry_Message); ok {
294 return x.Message
295 }
296 return nil
297}
298
299func (m *GrpcLogEntry) GetTrailer() *Trailer {
300 if x, ok := m.GetPayload().(*GrpcLogEntry_Trailer); ok {
301 return x.Trailer
302 }
303 return nil
304}
305
306func (m *GrpcLogEntry) GetPayloadTruncated() bool {
307 if m != nil {
308 return m.PayloadTruncated
309 }
310 return false
311}
312
313func (m *GrpcLogEntry) GetPeer() *Address {
314 if m != nil {
315 return m.Peer
316 }
317 return nil
318}
319
320// XXX_OneofFuncs is for the internal use of the proto package.
321func (*GrpcLogEntry) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
322 return _GrpcLogEntry_OneofMarshaler, _GrpcLogEntry_OneofUnmarshaler, _GrpcLogEntry_OneofSizer, []interface{}{
323 (*GrpcLogEntry_ClientHeader)(nil),
324 (*GrpcLogEntry_ServerHeader)(nil),
325 (*GrpcLogEntry_Message)(nil),
326 (*GrpcLogEntry_Trailer)(nil),
327 }
328}
329
330func _GrpcLogEntry_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
331 m := msg.(*GrpcLogEntry)
332 // payload
333 switch x := m.Payload.(type) {
334 case *GrpcLogEntry_ClientHeader:
335 b.EncodeVarint(6<<3 | proto.WireBytes)
336 if err := b.EncodeMessage(x.ClientHeader); err != nil {
337 return err
338 }
339 case *GrpcLogEntry_ServerHeader:
340 b.EncodeVarint(7<<3 | proto.WireBytes)
341 if err := b.EncodeMessage(x.ServerHeader); err != nil {
342 return err
343 }
344 case *GrpcLogEntry_Message:
345 b.EncodeVarint(8<<3 | proto.WireBytes)
346 if err := b.EncodeMessage(x.Message); err != nil {
347 return err
348 }
349 case *GrpcLogEntry_Trailer:
350 b.EncodeVarint(9<<3 | proto.WireBytes)
351 if err := b.EncodeMessage(x.Trailer); err != nil {
352 return err
353 }
354 case nil:
355 default:
356 return fmt.Errorf("GrpcLogEntry.Payload has unexpected type %T", x)
357 }
358 return nil
359}
360
361func _GrpcLogEntry_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
362 m := msg.(*GrpcLogEntry)
363 switch tag {
364 case 6: // payload.client_header
365 if wire != proto.WireBytes {
366 return true, proto.ErrInternalBadWireType
367 }
368 msg := new(ClientHeader)
369 err := b.DecodeMessage(msg)
370 m.Payload = &GrpcLogEntry_ClientHeader{msg}
371 return true, err
372 case 7: // payload.server_header
373 if wire != proto.WireBytes {
374 return true, proto.ErrInternalBadWireType
375 }
376 msg := new(ServerHeader)
377 err := b.DecodeMessage(msg)
378 m.Payload = &GrpcLogEntry_ServerHeader{msg}
379 return true, err
380 case 8: // payload.message
381 if wire != proto.WireBytes {
382 return true, proto.ErrInternalBadWireType
383 }
384 msg := new(Message)
385 err := b.DecodeMessage(msg)
386 m.Payload = &GrpcLogEntry_Message{msg}
387 return true, err
388 case 9: // payload.trailer
389 if wire != proto.WireBytes {
390 return true, proto.ErrInternalBadWireType
391 }
392 msg := new(Trailer)
393 err := b.DecodeMessage(msg)
394 m.Payload = &GrpcLogEntry_Trailer{msg}
395 return true, err
396 default:
397 return false, nil
398 }
399}
400
401func _GrpcLogEntry_OneofSizer(msg proto.Message) (n int) {
402 m := msg.(*GrpcLogEntry)
403 // payload
404 switch x := m.Payload.(type) {
405 case *GrpcLogEntry_ClientHeader:
406 s := proto.Size(x.ClientHeader)
407 n += 1 // tag and wire
408 n += proto.SizeVarint(uint64(s))
409 n += s
410 case *GrpcLogEntry_ServerHeader:
411 s := proto.Size(x.ServerHeader)
412 n += 1 // tag and wire
413 n += proto.SizeVarint(uint64(s))
414 n += s
415 case *GrpcLogEntry_Message:
416 s := proto.Size(x.Message)
417 n += 1 // tag and wire
418 n += proto.SizeVarint(uint64(s))
419 n += s
420 case *GrpcLogEntry_Trailer:
421 s := proto.Size(x.Trailer)
422 n += 1 // tag and wire
423 n += proto.SizeVarint(uint64(s))
424 n += s
425 case nil:
426 default:
427 panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
428 }
429 return n
430}
431
432type ClientHeader struct {
433 // This contains only the metadata from the application.
434 Metadata *Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"`
435 // The name of the RPC method, which looks something like:
436 // /<service>/<method>
437 // Note the leading "/" character.
438 MethodName string `protobuf:"bytes,2,opt,name=method_name,json=methodName,proto3" json:"method_name,omitempty"`
439 // A single process may be used to run multiple virtual
440 // servers with different identities.
441 // The authority is the name of such a server identitiy.
442 // It is typically a portion of the URI in the form of
443 // <host> or <host>:<port> .
444 Authority string `protobuf:"bytes,3,opt,name=authority,proto3" json:"authority,omitempty"`
445 // the RPC timeout
446 Timeout *duration.Duration `protobuf:"bytes,4,opt,name=timeout,proto3" json:"timeout,omitempty"`
447 XXX_NoUnkeyedLiteral struct{} `json:"-"`
448 XXX_unrecognized []byte `json:"-"`
449 XXX_sizecache int32 `json:"-"`
450}
451
452func (m *ClientHeader) Reset() { *m = ClientHeader{} }
453func (m *ClientHeader) String() string { return proto.CompactTextString(m) }
454func (*ClientHeader) ProtoMessage() {}
455func (*ClientHeader) Descriptor() ([]byte, []int) {
456 return fileDescriptor_binarylog_264c8c9c551ce911, []int{1}
457}
458func (m *ClientHeader) XXX_Unmarshal(b []byte) error {
459 return xxx_messageInfo_ClientHeader.Unmarshal(m, b)
460}
461func (m *ClientHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
462 return xxx_messageInfo_ClientHeader.Marshal(b, m, deterministic)
463}
464func (dst *ClientHeader) XXX_Merge(src proto.Message) {
465 xxx_messageInfo_ClientHeader.Merge(dst, src)
466}
467func (m *ClientHeader) XXX_Size() int {
468 return xxx_messageInfo_ClientHeader.Size(m)
469}
470func (m *ClientHeader) XXX_DiscardUnknown() {
471 xxx_messageInfo_ClientHeader.DiscardUnknown(m)
472}
473
474var xxx_messageInfo_ClientHeader proto.InternalMessageInfo
475
476func (m *ClientHeader) GetMetadata() *Metadata {
477 if m != nil {
478 return m.Metadata
479 }
480 return nil
481}
482
483func (m *ClientHeader) GetMethodName() string {
484 if m != nil {
485 return m.MethodName
486 }
487 return ""
488}
489
490func (m *ClientHeader) GetAuthority() string {
491 if m != nil {
492 return m.Authority
493 }
494 return ""
495}
496
497func (m *ClientHeader) GetTimeout() *duration.Duration {
498 if m != nil {
499 return m.Timeout
500 }
501 return nil
502}
503
504type ServerHeader struct {
505 // This contains only the metadata from the application.
506 Metadata *Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"`
507 XXX_NoUnkeyedLiteral struct{} `json:"-"`
508 XXX_unrecognized []byte `json:"-"`
509 XXX_sizecache int32 `json:"-"`
510}
511
512func (m *ServerHeader) Reset() { *m = ServerHeader{} }
513func (m *ServerHeader) String() string { return proto.CompactTextString(m) }
514func (*ServerHeader) ProtoMessage() {}
515func (*ServerHeader) Descriptor() ([]byte, []int) {
516 return fileDescriptor_binarylog_264c8c9c551ce911, []int{2}
517}
518func (m *ServerHeader) XXX_Unmarshal(b []byte) error {
519 return xxx_messageInfo_ServerHeader.Unmarshal(m, b)
520}
521func (m *ServerHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
522 return xxx_messageInfo_ServerHeader.Marshal(b, m, deterministic)
523}
524func (dst *ServerHeader) XXX_Merge(src proto.Message) {
525 xxx_messageInfo_ServerHeader.Merge(dst, src)
526}
527func (m *ServerHeader) XXX_Size() int {
528 return xxx_messageInfo_ServerHeader.Size(m)
529}
530func (m *ServerHeader) XXX_DiscardUnknown() {
531 xxx_messageInfo_ServerHeader.DiscardUnknown(m)
532}
533
534var xxx_messageInfo_ServerHeader proto.InternalMessageInfo
535
536func (m *ServerHeader) GetMetadata() *Metadata {
537 if m != nil {
538 return m.Metadata
539 }
540 return nil
541}
542
543type Trailer struct {
544 // This contains only the metadata from the application.
545 Metadata *Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"`
546 // The gRPC status code.
547 StatusCode uint32 `protobuf:"varint,2,opt,name=status_code,json=statusCode,proto3" json:"status_code,omitempty"`
548 // An original status message before any transport specific
549 // encoding.
550 StatusMessage string `protobuf:"bytes,3,opt,name=status_message,json=statusMessage,proto3" json:"status_message,omitempty"`
551 // The value of the 'grpc-status-details-bin' metadata key. If
552 // present, this is always an encoded 'google.rpc.Status' message.
553 StatusDetails []byte `protobuf:"bytes,4,opt,name=status_details,json=statusDetails,proto3" json:"status_details,omitempty"`
554 XXX_NoUnkeyedLiteral struct{} `json:"-"`
555 XXX_unrecognized []byte `json:"-"`
556 XXX_sizecache int32 `json:"-"`
557}
558
559func (m *Trailer) Reset() { *m = Trailer{} }
560func (m *Trailer) String() string { return proto.CompactTextString(m) }
561func (*Trailer) ProtoMessage() {}
562func (*Trailer) Descriptor() ([]byte, []int) {
563 return fileDescriptor_binarylog_264c8c9c551ce911, []int{3}
564}
565func (m *Trailer) XXX_Unmarshal(b []byte) error {
566 return xxx_messageInfo_Trailer.Unmarshal(m, b)
567}
568func (m *Trailer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
569 return xxx_messageInfo_Trailer.Marshal(b, m, deterministic)
570}
571func (dst *Trailer) XXX_Merge(src proto.Message) {
572 xxx_messageInfo_Trailer.Merge(dst, src)
573}
574func (m *Trailer) XXX_Size() int {
575 return xxx_messageInfo_Trailer.Size(m)
576}
577func (m *Trailer) XXX_DiscardUnknown() {
578 xxx_messageInfo_Trailer.DiscardUnknown(m)
579}
580
581var xxx_messageInfo_Trailer proto.InternalMessageInfo
582
583func (m *Trailer) GetMetadata() *Metadata {
584 if m != nil {
585 return m.Metadata
586 }
587 return nil
588}
589
590func (m *Trailer) GetStatusCode() uint32 {
591 if m != nil {
592 return m.StatusCode
593 }
594 return 0
595}
596
597func (m *Trailer) GetStatusMessage() string {
598 if m != nil {
599 return m.StatusMessage
600 }
601 return ""
602}
603
604func (m *Trailer) GetStatusDetails() []byte {
605 if m != nil {
606 return m.StatusDetails
607 }
608 return nil
609}
610
611// Message payload, used by CLIENT_MESSAGE and SERVER_MESSAGE
612type Message struct {
613 // Length of the message. It may not be the same as the length of the
614 // data field, as the logging payload can be truncated or omitted.
615 Length uint32 `protobuf:"varint,1,opt,name=length,proto3" json:"length,omitempty"`
616 // May be truncated or omitted.
617 Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
618 XXX_NoUnkeyedLiteral struct{} `json:"-"`
619 XXX_unrecognized []byte `json:"-"`
620 XXX_sizecache int32 `json:"-"`
621}
622
623func (m *Message) Reset() { *m = Message{} }
624func (m *Message) String() string { return proto.CompactTextString(m) }
625func (*Message) ProtoMessage() {}
626func (*Message) Descriptor() ([]byte, []int) {
627 return fileDescriptor_binarylog_264c8c9c551ce911, []int{4}
628}
629func (m *Message) XXX_Unmarshal(b []byte) error {
630 return xxx_messageInfo_Message.Unmarshal(m, b)
631}
632func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
633 return xxx_messageInfo_Message.Marshal(b, m, deterministic)
634}
635func (dst *Message) XXX_Merge(src proto.Message) {
636 xxx_messageInfo_Message.Merge(dst, src)
637}
638func (m *Message) XXX_Size() int {
639 return xxx_messageInfo_Message.Size(m)
640}
641func (m *Message) XXX_DiscardUnknown() {
642 xxx_messageInfo_Message.DiscardUnknown(m)
643}
644
645var xxx_messageInfo_Message proto.InternalMessageInfo
646
647func (m *Message) GetLength() uint32 {
648 if m != nil {
649 return m.Length
650 }
651 return 0
652}
653
654func (m *Message) GetData() []byte {
655 if m != nil {
656 return m.Data
657 }
658 return nil
659}
660
661// A list of metadata pairs, used in the payload of client header,
662// server header, and server trailer.
663// Implementations may omit some entries to honor the header limits
664// of GRPC_BINARY_LOG_CONFIG.
665//
666// Header keys added by gRPC are omitted. To be more specific,
667// implementations will not log the following entries, and this is
668// not to be treated as a truncation:
669// - entries handled by grpc that are not user visible, such as those
670// that begin with 'grpc-' (with exception of grpc-trace-bin)
671// or keys like 'lb-token'
672// - transport specific entries, including but not limited to:
673// ':path', ':authority', 'content-encoding', 'user-agent', 'te', etc
674// - entries added for call credentials
675//
676// Implementations must always log grpc-trace-bin if it is present.
677// Practically speaking it will only be visible on server side because
678// grpc-trace-bin is managed by low level client side mechanisms
679// inaccessible from the application level. On server side, the
680// header is just a normal metadata key.
681// The pair will not count towards the size limit.
682type Metadata struct {
683 Entry []*MetadataEntry `protobuf:"bytes,1,rep,name=entry,proto3" json:"entry,omitempty"`
684 XXX_NoUnkeyedLiteral struct{} `json:"-"`
685 XXX_unrecognized []byte `json:"-"`
686 XXX_sizecache int32 `json:"-"`
687}
688
689func (m *Metadata) Reset() { *m = Metadata{} }
690func (m *Metadata) String() string { return proto.CompactTextString(m) }
691func (*Metadata) ProtoMessage() {}
692func (*Metadata) Descriptor() ([]byte, []int) {
693 return fileDescriptor_binarylog_264c8c9c551ce911, []int{5}
694}
695func (m *Metadata) XXX_Unmarshal(b []byte) error {
696 return xxx_messageInfo_Metadata.Unmarshal(m, b)
697}
698func (m *Metadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
699 return xxx_messageInfo_Metadata.Marshal(b, m, deterministic)
700}
701func (dst *Metadata) XXX_Merge(src proto.Message) {
702 xxx_messageInfo_Metadata.Merge(dst, src)
703}
704func (m *Metadata) XXX_Size() int {
705 return xxx_messageInfo_Metadata.Size(m)
706}
707func (m *Metadata) XXX_DiscardUnknown() {
708 xxx_messageInfo_Metadata.DiscardUnknown(m)
709}
710
711var xxx_messageInfo_Metadata proto.InternalMessageInfo
712
713func (m *Metadata) GetEntry() []*MetadataEntry {
714 if m != nil {
715 return m.Entry
716 }
717 return nil
718}
719
720// A metadata key value pair
721type MetadataEntry struct {
722 Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
723 Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
724 XXX_NoUnkeyedLiteral struct{} `json:"-"`
725 XXX_unrecognized []byte `json:"-"`
726 XXX_sizecache int32 `json:"-"`
727}
728
729func (m *MetadataEntry) Reset() { *m = MetadataEntry{} }
730func (m *MetadataEntry) String() string { return proto.CompactTextString(m) }
731func (*MetadataEntry) ProtoMessage() {}
732func (*MetadataEntry) Descriptor() ([]byte, []int) {
733 return fileDescriptor_binarylog_264c8c9c551ce911, []int{6}
734}
735func (m *MetadataEntry) XXX_Unmarshal(b []byte) error {
736 return xxx_messageInfo_MetadataEntry.Unmarshal(m, b)
737}
738func (m *MetadataEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
739 return xxx_messageInfo_MetadataEntry.Marshal(b, m, deterministic)
740}
741func (dst *MetadataEntry) XXX_Merge(src proto.Message) {
742 xxx_messageInfo_MetadataEntry.Merge(dst, src)
743}
744func (m *MetadataEntry) XXX_Size() int {
745 return xxx_messageInfo_MetadataEntry.Size(m)
746}
747func (m *MetadataEntry) XXX_DiscardUnknown() {
748 xxx_messageInfo_MetadataEntry.DiscardUnknown(m)
749}
750
751var xxx_messageInfo_MetadataEntry proto.InternalMessageInfo
752
753func (m *MetadataEntry) GetKey() string {
754 if m != nil {
755 return m.Key
756 }
757 return ""
758}
759
760func (m *MetadataEntry) GetValue() []byte {
761 if m != nil {
762 return m.Value
763 }
764 return nil
765}
766
767// Address information
768type Address struct {
769 Type Address_Type `protobuf:"varint,1,opt,name=type,proto3,enum=grpc.binarylog.v1.Address_Type" json:"type,omitempty"`
770 Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"`
771 // only for TYPE_IPV4 and TYPE_IPV6
772 IpPort uint32 `protobuf:"varint,3,opt,name=ip_port,json=ipPort,proto3" json:"ip_port,omitempty"`
773 XXX_NoUnkeyedLiteral struct{} `json:"-"`
774 XXX_unrecognized []byte `json:"-"`
775 XXX_sizecache int32 `json:"-"`
776}
777
778func (m *Address) Reset() { *m = Address{} }
779func (m *Address) String() string { return proto.CompactTextString(m) }
780func (*Address) ProtoMessage() {}
781func (*Address) Descriptor() ([]byte, []int) {
782 return fileDescriptor_binarylog_264c8c9c551ce911, []int{7}
783}
784func (m *Address) XXX_Unmarshal(b []byte) error {
785 return xxx_messageInfo_Address.Unmarshal(m, b)
786}
787func (m *Address) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
788 return xxx_messageInfo_Address.Marshal(b, m, deterministic)
789}
790func (dst *Address) XXX_Merge(src proto.Message) {
791 xxx_messageInfo_Address.Merge(dst, src)
792}
793func (m *Address) XXX_Size() int {
794 return xxx_messageInfo_Address.Size(m)
795}
796func (m *Address) XXX_DiscardUnknown() {
797 xxx_messageInfo_Address.DiscardUnknown(m)
798}
799
800var xxx_messageInfo_Address proto.InternalMessageInfo
801
802func (m *Address) GetType() Address_Type {
803 if m != nil {
804 return m.Type
805 }
806 return Address_TYPE_UNKNOWN
807}
808
809func (m *Address) GetAddress() string {
810 if m != nil {
811 return m.Address
812 }
813 return ""
814}
815
816func (m *Address) GetIpPort() uint32 {
817 if m != nil {
818 return m.IpPort
819 }
820 return 0
821}
822
823func init() {
824 proto.RegisterType((*GrpcLogEntry)(nil), "grpc.binarylog.v1.GrpcLogEntry")
825 proto.RegisterType((*ClientHeader)(nil), "grpc.binarylog.v1.ClientHeader")
826 proto.RegisterType((*ServerHeader)(nil), "grpc.binarylog.v1.ServerHeader")
827 proto.RegisterType((*Trailer)(nil), "grpc.binarylog.v1.Trailer")
828 proto.RegisterType((*Message)(nil), "grpc.binarylog.v1.Message")
829 proto.RegisterType((*Metadata)(nil), "grpc.binarylog.v1.Metadata")
830 proto.RegisterType((*MetadataEntry)(nil), "grpc.binarylog.v1.MetadataEntry")
831 proto.RegisterType((*Address)(nil), "grpc.binarylog.v1.Address")
832 proto.RegisterEnum("grpc.binarylog.v1.GrpcLogEntry_EventType", GrpcLogEntry_EventType_name, GrpcLogEntry_EventType_value)
833 proto.RegisterEnum("grpc.binarylog.v1.GrpcLogEntry_Logger", GrpcLogEntry_Logger_name, GrpcLogEntry_Logger_value)
834 proto.RegisterEnum("grpc.binarylog.v1.Address_Type", Address_Type_name, Address_Type_value)
835}
836
837func init() {
838 proto.RegisterFile("grpc/binarylog/grpc_binarylog_v1/binarylog.proto", fileDescriptor_binarylog_264c8c9c551ce911)
839}
840
841var fileDescriptor_binarylog_264c8c9c551ce911 = []byte{
842 // 900 bytes of a gzipped FileDescriptorProto
843 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0x51, 0x6f, 0xe3, 0x44,
844 0x10, 0x3e, 0x37, 0x69, 0xdc, 0x4c, 0x92, 0xca, 0x5d, 0x95, 0x3b, 0x5f, 0x29, 0x34, 0xb2, 0x04,
845 0x0a, 0x42, 0x72, 0xb9, 0x94, 0xeb, 0xf1, 0x02, 0x52, 0x92, 0xfa, 0xd2, 0x88, 0x5c, 0x1a, 0x6d,
846 0x72, 0x3d, 0x40, 0x48, 0xd6, 0x36, 0x5e, 0x1c, 0x0b, 0xc7, 0x6b, 0xd6, 0x9b, 0xa0, 0xfc, 0x2c,
847 0xde, 0x90, 0xee, 0x77, 0xf1, 0x8e, 0xbc, 0x6b, 0x27, 0xa6, 0x69, 0x0f, 0x09, 0xde, 0x3c, 0xdf,
848 0x7c, 0xf3, 0xcd, 0xee, 0x78, 0x66, 0x16, 0xbe, 0xf2, 0x79, 0x3c, 0x3b, 0xbf, 0x0b, 0x22, 0xc2,
849 0xd7, 0x21, 0xf3, 0xcf, 0x53, 0xd3, 0xdd, 0x98, 0xee, 0xea, 0xc5, 0xd6, 0x67, 0xc7, 0x9c, 0x09,
850 0x86, 0x8e, 0x52, 0x8a, 0xbd, 0x45, 0x57, 0x2f, 0x4e, 0x3e, 0xf5, 0x19, 0xf3, 0x43, 0x7a, 0x2e,
851 0x09, 0x77, 0xcb, 0x5f, 0xce, 0xbd, 0x25, 0x27, 0x22, 0x60, 0x91, 0x0a, 0x39, 0x39, 0xbb, 0xef,
852 0x17, 0xc1, 0x82, 0x26, 0x82, 0x2c, 0x62, 0x45, 0xb0, 0xde, 0xeb, 0x50, 0xef, 0xf3, 0x78, 0x36,
853 0x64, 0xbe, 0x13, 0x09, 0xbe, 0x46, 0xdf, 0x40, 0x75, 0xc3, 0x31, 0xb5, 0xa6, 0xd6, 0xaa, 0xb5,
854 0x4f, 0x6c, 0xa5, 0x62, 0xe7, 0x2a, 0xf6, 0x34, 0x67, 0xe0, 0x2d, 0x19, 0x3d, 0x03, 0x7d, 0x46,
855 0xc2, 0xd0, 0x0d, 0x3c, 0x73, 0xaf, 0xa9, 0xb5, 0xca, 0xb8, 0x92, 0x9a, 0x03, 0x0f, 0xbd, 0x84,
856 0x67, 0x09, 0xfd, 0x6d, 0x49, 0xa3, 0x19, 0x75, 0x03, 0xcf, 0xfd, 0x3d, 0x10, 0xf3, 0x20, 0x72,
857 0x53, 0xa7, 0x59, 0x92, 0xc4, 0xe3, 0xdc, 0x3d, 0xf0, 0xde, 0x49, 0x67, 0x8f, 0x84, 0x21, 0xfa,
858 0x16, 0xca, 0x62, 0x1d, 0x53, 0xb3, 0xdc, 0xd4, 0x5a, 0x87, 0xed, 0x2f, 0xec, 0x9d, 0xdb, 0xdb,
859 0xc5, 0x83, 0xdb, 0xce, 0x8a, 0x46, 0x62, 0xba, 0x8e, 0x29, 0x96, 0x61, 0xe8, 0x3b, 0xa8, 0x84,
860 0xcc, 0xf7, 0x29, 0x37, 0xf7, 0xa5, 0xc0, 0xe7, 0xff, 0x26, 0x30, 0x94, 0x6c, 0x9c, 0x45, 0xa1,
861 0xd7, 0xd0, 0x98, 0x85, 0x01, 0x8d, 0x84, 0x3b, 0xa7, 0xc4, 0xa3, 0xdc, 0xac, 0xc8, 0x62, 0x9c,
862 0x3d, 0x20, 0xd3, 0x93, 0xbc, 0x6b, 0x49, 0xbb, 0x7e, 0x82, 0xeb, 0xb3, 0x82, 0x9d, 0xea, 0x24,
863 0x94, 0xaf, 0x28, 0xcf, 0x75, 0xf4, 0x47, 0x75, 0x26, 0x92, 0xb7, 0xd5, 0x49, 0x0a, 0x36, 0xba,
864 0x04, 0x7d, 0x41, 0x93, 0x84, 0xf8, 0xd4, 0x3c, 0xc8, 0x7f, 0xcb, 0x8e, 0xc2, 0x1b, 0xc5, 0xb8,
865 0x7e, 0x82, 0x73, 0x72, 0x1a, 0x27, 0x38, 0x09, 0x42, 0xca, 0xcd, 0xea, 0xa3, 0x71, 0x53, 0xc5,
866 0x48, 0xe3, 0x32, 0x32, 0xfa, 0x12, 0x8e, 0x62, 0xb2, 0x0e, 0x19, 0xf1, 0x5c, 0xc1, 0x97, 0xd1,
867 0x8c, 0x08, 0xea, 0x99, 0xd0, 0xd4, 0x5a, 0x07, 0xd8, 0xc8, 0x1c, 0xd3, 0x1c, 0x47, 0x36, 0x94,
868 0x63, 0x4a, 0xb9, 0x59, 0x7b, 0x34, 0x43, 0xc7, 0xf3, 0x38, 0x4d, 0x12, 0x2c, 0x79, 0xd6, 0x5f,
869 0x1a, 0x54, 0x37, 0x3f, 0x0c, 0x3d, 0x05, 0xe4, 0xdc, 0x3a, 0xa3, 0xa9, 0x3b, 0xfd, 0x71, 0xec,
870 0xb8, 0x6f, 0x47, 0xdf, 0x8f, 0x6e, 0xde, 0x8d, 0x8c, 0x27, 0xe8, 0x14, 0xcc, 0x02, 0xde, 0x1b,
871 0x0e, 0xd2, 0xef, 0x6b, 0xa7, 0x73, 0xe5, 0x60, 0x43, 0xbb, 0xe7, 0x9d, 0x38, 0xf8, 0xd6, 0xc1,
872 0xb9, 0x77, 0x0f, 0x7d, 0x02, 0xcf, 0x77, 0x63, 0xdf, 0x38, 0x93, 0x49, 0xa7, 0xef, 0x18, 0xa5,
873 0x7b, 0xee, 0x2c, 0x38, 0x77, 0x97, 0x51, 0x13, 0x4e, 0x1f, 0xc8, 0xdc, 0x19, 0xbe, 0x76, 0x7b,
874 0xc3, 0x9b, 0x89, 0x63, 0xec, 0x3f, 0x2c, 0x30, 0xc5, 0x9d, 0xc1, 0xd0, 0xc1, 0x46, 0x05, 0x7d,
875 0x04, 0x47, 0x45, 0x81, 0xce, 0xa8, 0xe7, 0x0c, 0x0d, 0xdd, 0xea, 0x42, 0x45, 0xb5, 0x19, 0x42,
876 0x70, 0x38, 0xbc, 0xe9, 0xf7, 0x1d, 0x5c, 0xb8, 0xef, 0x11, 0x34, 0x32, 0x4c, 0x65, 0x34, 0xb4,
877 0x02, 0xa4, 0x52, 0x18, 0x7b, 0xdd, 0x2a, 0xe8, 0x59, 0xfd, 0xad, 0xf7, 0x1a, 0xd4, 0x8b, 0xcd,
878 0x87, 0x5e, 0xc1, 0xc1, 0x82, 0x0a, 0xe2, 0x11, 0x41, 0xb2, 0xe1, 0xfd, 0xf8, 0xc1, 0x2e, 0x51,
879 0x14, 0xbc, 0x21, 0xa3, 0x33, 0xa8, 0x2d, 0xa8, 0x98, 0x33, 0xcf, 0x8d, 0xc8, 0x82, 0xca, 0x01,
880 0xae, 0x62, 0x50, 0xd0, 0x88, 0x2c, 0x28, 0x3a, 0x85, 0x2a, 0x59, 0x8a, 0x39, 0xe3, 0x81, 0x58,
881 0xcb, 0xb1, 0xad, 0xe2, 0x2d, 0x80, 0x2e, 0x40, 0x4f, 0x17, 0x01, 0x5b, 0x0a, 0x39, 0xae, 0xb5,
882 0xf6, 0xf3, 0x9d, 0x9d, 0x71, 0x95, 0x6d, 0x26, 0x9c, 0x33, 0xad, 0x3e, 0xd4, 0x8b, 0x1d, 0xff,
883 0x9f, 0x0f, 0x6f, 0xfd, 0xa1, 0x81, 0x9e, 0x75, 0xf0, 0xff, 0xaa, 0x40, 0x22, 0x88, 0x58, 0x26,
884 0xee, 0x8c, 0x79, 0xaa, 0x02, 0x0d, 0x0c, 0x0a, 0xea, 0x31, 0x8f, 0xa2, 0xcf, 0xe0, 0x30, 0x23,
885 0xe4, 0x73, 0xa8, 0xca, 0xd0, 0x50, 0x68, 0x36, 0x7a, 0x05, 0x9a, 0x47, 0x05, 0x09, 0xc2, 0x44,
886 0x56, 0xa4, 0x9e, 0xd3, 0xae, 0x14, 0x68, 0xbd, 0x04, 0x3d, 0x8f, 0x78, 0x0a, 0x95, 0x90, 0x46,
887 0xbe, 0x98, 0xcb, 0x03, 0x37, 0x70, 0x66, 0x21, 0x04, 0x65, 0x79, 0x8d, 0x3d, 0x19, 0x2f, 0xbf,
888 0xad, 0x2e, 0x1c, 0xe4, 0x67, 0x47, 0x97, 0xb0, 0x4f, 0xd3, 0xcd, 0x65, 0x6a, 0xcd, 0x52, 0xab,
889 0xd6, 0x6e, 0x7e, 0xe0, 0x9e, 0x72, 0xc3, 0x61, 0x45, 0xb7, 0x5e, 0x41, 0xe3, 0x1f, 0x38, 0x32,
890 0xa0, 0xf4, 0x2b, 0x5d, 0xcb, 0xec, 0x55, 0x9c, 0x7e, 0xa2, 0x63, 0xd8, 0x5f, 0x91, 0x70, 0x49,
891 0xb3, 0xdc, 0xca, 0xb0, 0xfe, 0xd4, 0x40, 0xcf, 0xe6, 0x18, 0x5d, 0x64, 0xdb, 0x59, 0x93, 0xcb,
892 0xf5, 0xec, 0xf1, 0x89, 0xb7, 0x0b, 0x3b, 0xd9, 0x04, 0x9d, 0x28, 0x34, 0xeb, 0xb0, 0xdc, 0x4c,
893 0x1f, 0x8f, 0x20, 0x76, 0x63, 0xc6, 0x85, 0xac, 0x6a, 0x03, 0x57, 0x82, 0x78, 0xcc, 0xb8, 0xb0,
894 0x1c, 0x28, 0xcb, 0x1d, 0x61, 0x40, 0xfd, 0xde, 0x76, 0x68, 0x40, 0x55, 0x22, 0x83, 0xf1, 0xed,
895 0xd7, 0x86, 0x56, 0x34, 0x2f, 0x8d, 0xbd, 0x8d, 0xf9, 0x76, 0x34, 0xf8, 0xc1, 0x28, 0x75, 0x7f,
896 0x86, 0xe3, 0x80, 0xed, 0x1e, 0xb2, 0x7b, 0xd8, 0x95, 0xd6, 0x90, 0xf9, 0xe3, 0xb4, 0x51, 0xc7,
897 0xda, 0x4f, 0xed, 0xac, 0x71, 0x7d, 0x16, 0x92, 0xc8, 0xb7, 0x19, 0x57, 0x4f, 0xf3, 0x87, 0x5e,
898 0xea, 0xbb, 0x8a, 0xec, 0xf2, 0x8b, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xe7, 0xf6, 0x4b, 0x50,
899 0xd4, 0x07, 0x00, 0x00,
900}
diff --git a/vendor/google.golang.org/grpc/call.go b/vendor/google.golang.org/grpc/call.go
index 797190f..100f05d 100644
--- a/vendor/google.golang.org/grpc/call.go
+++ b/vendor/google.golang.org/grpc/call.go
@@ -19,291 +19,56 @@
19package grpc 19package grpc
20 20
21import ( 21import (
22 "bytes" 22 "context"
23 "io"
24 "time"
25
26 "golang.org/x/net/context"
27 "golang.org/x/net/trace"
28 "google.golang.org/grpc/codes"
29 "google.golang.org/grpc/peer"
30 "google.golang.org/grpc/stats"
31 "google.golang.org/grpc/status"
32 "google.golang.org/grpc/transport"
33) 23)
34 24
35// recvResponse receives and parses an RPC response. 25// Invoke sends the RPC request on the wire and returns after response is
36// On error, it returns the error and indicates whether the call should be retried. 26// received. This is typically called by generated code.
37// 27//
38// TODO(zhaoq): Check whether the received message sequence is valid. 28// All errors returned by Invoke are compatible with the status package.
39// TODO ctx is used for stats collection and processing. It is the context passed from the application. 29func (cc *ClientConn) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...CallOption) error {
40func recvResponse(ctx context.Context, dopts dialOptions, t transport.ClientTransport, c *callInfo, stream *transport.Stream, reply interface{}) (err error) { 30 // allow interceptor to see all applicable call options, which means those
41 // Try to acquire header metadata from the server if there is any. 31 // configured as defaults from dial option as well as per-call options
42 defer func() { 32 opts = combine(cc.dopts.callOptions, opts)
43 if err != nil {
44 if _, ok := err.(transport.ConnectionError); !ok {
45 t.CloseStream(stream, err)
46 }
47 }
48 }()
49 c.headerMD, err = stream.Header()
50 if err != nil {
51 return
52 }
53 p := &parser{r: stream}
54 var inPayload *stats.InPayload
55 if dopts.copts.StatsHandler != nil {
56 inPayload = &stats.InPayload{
57 Client: true,
58 }
59 }
60 for {
61 if c.maxReceiveMessageSize == nil {
62 return Errorf(codes.Internal, "callInfo maxReceiveMessageSize field uninitialized(nil)")
63 }
64 if err = recv(p, dopts.codec, stream, dopts.dc, reply, *c.maxReceiveMessageSize, inPayload); err != nil {
65 if err == io.EOF {
66 break
67 }
68 return
69 }
70 }
71 if inPayload != nil && err == io.EOF && stream.Status().Code() == codes.OK {
72 // TODO in the current implementation, inTrailer may be handled before inPayload in some cases.
73 // Fix the order if necessary.
74 dopts.copts.StatsHandler.HandleRPC(ctx, inPayload)
75 }
76 c.trailerMD = stream.Trailer()
77 return nil
78}
79
80// sendRequest writes out various information of an RPC such as Context and Message.
81func sendRequest(ctx context.Context, dopts dialOptions, compressor Compressor, c *callInfo, callHdr *transport.CallHdr, stream *transport.Stream, t transport.ClientTransport, args interface{}, opts *transport.Options) (err error) {
82 defer func() {
83 if err != nil {
84 // If err is connection error, t will be closed, no need to close stream here.
85 if _, ok := err.(transport.ConnectionError); !ok {
86 t.CloseStream(stream, err)
87 }
88 }
89 }()
90 var (
91 cbuf *bytes.Buffer
92 outPayload *stats.OutPayload
93 )
94 if compressor != nil {
95 cbuf = new(bytes.Buffer)
96 }
97 if dopts.copts.StatsHandler != nil {
98 outPayload = &stats.OutPayload{
99 Client: true,
100 }
101 }
102 outBuf, err := encode(dopts.codec, args, compressor, cbuf, outPayload)
103 if err != nil {
104 return err
105 }
106 if c.maxSendMessageSize == nil {
107 return Errorf(codes.Internal, "callInfo maxSendMessageSize field uninitialized(nil)")
108 }
109 if len(outBuf) > *c.maxSendMessageSize {
110 return Errorf(codes.ResourceExhausted, "grpc: trying to send message larger than max (%d vs. %d)", len(outBuf), *c.maxSendMessageSize)
111 }
112 err = t.Write(stream, outBuf, opts)
113 if err == nil && outPayload != nil {
114 outPayload.SentTime = time.Now()
115 dopts.copts.StatsHandler.HandleRPC(ctx, outPayload)
116 }
117 // t.NewStream(...) could lead to an early rejection of the RPC (e.g., the service/method
118 // does not exist.) so that t.Write could get io.EOF from wait(...). Leave the following
119 // recvResponse to get the final status.
120 if err != nil && err != io.EOF {
121 return err
122 }
123 // Sent successfully.
124 return nil
125}
126 33
127// Invoke sends the RPC request on the wire and returns after response is received.
128// Invoke is called by generated code. Also users can call Invoke directly when it
129// is really needed in their use cases.
130func Invoke(ctx context.Context, method string, args, reply interface{}, cc *ClientConn, opts ...CallOption) error {
131 if cc.dopts.unaryInt != nil { 34 if cc.dopts.unaryInt != nil {
132 return cc.dopts.unaryInt(ctx, method, args, reply, cc, invoke, opts...) 35 return cc.dopts.unaryInt(ctx, method, args, reply, cc, invoke, opts...)
133 } 36 }
134 return invoke(ctx, method, args, reply, cc, opts...) 37 return invoke(ctx, method, args, reply, cc, opts...)
135} 38}
136 39
137func invoke(ctx context.Context, method string, args, reply interface{}, cc *ClientConn, opts ...CallOption) (e error) { 40func combine(o1 []CallOption, o2 []CallOption) []CallOption {
138 c := defaultCallInfo 41 // we don't use append because o1 could have extra capacity whose
139 mc := cc.GetMethodConfig(method) 42 // elements would be overwritten, which could cause inadvertent
140 if mc.WaitForReady != nil { 43 // sharing (and race connditions) between concurrent calls
141 c.failFast = !*mc.WaitForReady 44 if len(o1) == 0 {
142 } 45 return o2
143 46 } else if len(o2) == 0 {
144 if mc.Timeout != nil && *mc.Timeout >= 0 { 47 return o1
145 var cancel context.CancelFunc 48 }
146 ctx, cancel = context.WithTimeout(ctx, *mc.Timeout) 49 ret := make([]CallOption, len(o1)+len(o2))
147 defer cancel() 50 copy(ret, o1)
148 } 51 copy(ret[len(o1):], o2)
52 return ret
53}
149 54
150 opts = append(cc.dopts.callOptions, opts...) 55// Invoke sends the RPC request on the wire and returns after response is
151 for _, o := range opts { 56// received. This is typically called by generated code.
152 if err := o.before(&c); err != nil { 57//
153 return toRPCErr(err) 58// DEPRECATED: Use ClientConn.Invoke instead.
154 } 59func Invoke(ctx context.Context, method string, args, reply interface{}, cc *ClientConn, opts ...CallOption) error {
155 } 60 return cc.Invoke(ctx, method, args, reply, opts...)
156 defer func() { 61}
157 for _, o := range opts {
158 o.after(&c)
159 }
160 }()
161 62
162 c.maxSendMessageSize = getMaxSize(mc.MaxReqSize, c.maxSendMessageSize, defaultClientMaxSendMessageSize) 63var unaryStreamDesc = &StreamDesc{ServerStreams: false, ClientStreams: false}
163 c.maxReceiveMessageSize = getMaxSize(mc.MaxRespSize, c.maxReceiveMessageSize, defaultClientMaxReceiveMessageSize)
164 64
165 if EnableTracing { 65func invoke(ctx context.Context, method string, req, reply interface{}, cc *ClientConn, opts ...CallOption) error {
166 c.traceInfo.tr = trace.New("grpc.Sent."+methodFamily(method), method) 66 cs, err := newClientStream(ctx, unaryStreamDesc, cc, method, opts...)
167 defer c.traceInfo.tr.Finish() 67 if err != nil {
168 c.traceInfo.firstLine.client = true 68 return err
169 if deadline, ok := ctx.Deadline(); ok {
170 c.traceInfo.firstLine.deadline = deadline.Sub(time.Now())
171 }
172 c.traceInfo.tr.LazyLog(&c.traceInfo.firstLine, false)
173 // TODO(dsymonds): Arrange for c.traceInfo.firstLine.remoteAddr to be set.
174 defer func() {
175 if e != nil {
176 c.traceInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{e}}, true)
177 c.traceInfo.tr.SetError()
178 }
179 }()
180 }
181 ctx = newContextWithRPCInfo(ctx)
182 sh := cc.dopts.copts.StatsHandler
183 if sh != nil {
184 ctx = sh.TagRPC(ctx, &stats.RPCTagInfo{FullMethodName: method, FailFast: c.failFast})
185 begin := &stats.Begin{
186 Client: true,
187 BeginTime: time.Now(),
188 FailFast: c.failFast,
189 }
190 sh.HandleRPC(ctx, begin)
191 defer func() {
192 end := &stats.End{
193 Client: true,
194 EndTime: time.Now(),
195 Error: e,
196 }
197 sh.HandleRPC(ctx, end)
198 }()
199 }
200 topts := &transport.Options{
201 Last: true,
202 Delay: false,
203 } 69 }
204 for { 70 if err := cs.SendMsg(req); err != nil {
205 var ( 71 return err
206 err error
207 t transport.ClientTransport
208 stream *transport.Stream
209 // Record the put handler from Balancer.Get(...). It is called once the
210 // RPC has completed or failed.
211 put func()
212 )
213 // TODO(zhaoq): Need a formal spec of fail-fast.
214 callHdr := &transport.CallHdr{
215 Host: cc.authority,
216 Method: method,
217 }
218 if cc.dopts.cp != nil {
219 callHdr.SendCompress = cc.dopts.cp.Type()
220 }
221 if c.creds != nil {
222 callHdr.Creds = c.creds
223 }
224
225 gopts := BalancerGetOptions{
226 BlockingWait: !c.failFast,
227 }
228 t, put, err = cc.getTransport(ctx, gopts)
229 if err != nil {
230 // TODO(zhaoq): Probably revisit the error handling.
231 if _, ok := status.FromError(err); ok {
232 return err
233 }
234 if err == errConnClosing || err == errConnUnavailable {
235 if c.failFast {
236 return Errorf(codes.Unavailable, "%v", err)
237 }
238 continue
239 }
240 // All the other errors are treated as Internal errors.
241 return Errorf(codes.Internal, "%v", err)
242 }
243 if c.traceInfo.tr != nil {
244 c.traceInfo.tr.LazyLog(&payload{sent: true, msg: args}, true)
245 }
246 stream, err = t.NewStream(ctx, callHdr)
247 if err != nil {
248 if put != nil {
249 if _, ok := err.(transport.ConnectionError); ok {
250 // If error is connection error, transport was sending data on wire,
251 // and we are not sure if anything has been sent on wire.
252 // If error is not connection error, we are sure nothing has been sent.
253 updateRPCInfoInContext(ctx, rpcInfo{bytesSent: true, bytesReceived: false})
254 }
255 put()
256 }
257 if _, ok := err.(transport.ConnectionError); (ok || err == transport.ErrStreamDrain) && !c.failFast {
258 continue
259 }
260 return toRPCErr(err)
261 }
262 if peer, ok := peer.FromContext(stream.Context()); ok {
263 c.peer = peer
264 }
265 err = sendRequest(ctx, cc.dopts, cc.dopts.cp, &c, callHdr, stream, t, args, topts)
266 if err != nil {
267 if put != nil {
268 updateRPCInfoInContext(ctx, rpcInfo{
269 bytesSent: stream.BytesSent(),
270 bytesReceived: stream.BytesReceived(),
271 })
272 put()
273 }
274 // Retry a non-failfast RPC when
275 // i) there is a connection error; or
276 // ii) the server started to drain before this RPC was initiated.
277 if _, ok := err.(transport.ConnectionError); (ok || err == transport.ErrStreamDrain) && !c.failFast {
278 continue
279 }
280 return toRPCErr(err)
281 }
282 err = recvResponse(ctx, cc.dopts, t, &c, stream, reply)
283 if err != nil {
284 if put != nil {
285 updateRPCInfoInContext(ctx, rpcInfo{
286 bytesSent: stream.BytesSent(),
287 bytesReceived: stream.BytesReceived(),
288 })
289 put()
290 }
291 if _, ok := err.(transport.ConnectionError); (ok || err == transport.ErrStreamDrain) && !c.failFast {
292 continue
293 }
294 return toRPCErr(err)
295 }
296 if c.traceInfo.tr != nil {
297 c.traceInfo.tr.LazyLog(&payload{sent: false, msg: reply}, true)
298 }
299 t.CloseStream(stream, nil)
300 if put != nil {
301 updateRPCInfoInContext(ctx, rpcInfo{
302 bytesSent: stream.BytesSent(),
303 bytesReceived: stream.BytesReceived(),
304 })
305 put()
306 }
307 return stream.Status().Err()
308 } 72 }
73 return cs.RecvMsg(reply)
309} 74}
diff --git a/vendor/google.golang.org/grpc/clientconn.go b/vendor/google.golang.org/grpc/clientconn.go
index e3f6cb1..56d0bf7 100644
--- a/vendor/google.golang.org/grpc/clientconn.go
+++ b/vendor/google.golang.org/grpc/clientconn.go
@@ -19,35 +19,72 @@
19package grpc 19package grpc
20 20
21import ( 21import (
22 "context"
22 "errors" 23 "errors"
24 "fmt"
25 "math"
23 "net" 26 "net"
27 "reflect"
24 "strings" 28 "strings"
25 "sync" 29 "sync"
30 "sync/atomic"
26 "time" 31 "time"
27 32
28 "golang.org/x/net/context" 33 "google.golang.org/grpc/balancer"
29 "golang.org/x/net/trace" 34 _ "google.golang.org/grpc/balancer/roundrobin" // To register roundrobin.
35 "google.golang.org/grpc/codes"
30 "google.golang.org/grpc/connectivity" 36 "google.golang.org/grpc/connectivity"
31 "google.golang.org/grpc/credentials" 37 "google.golang.org/grpc/credentials"
32 "google.golang.org/grpc/grpclog" 38 "google.golang.org/grpc/grpclog"
39 "google.golang.org/grpc/internal/backoff"
40 "google.golang.org/grpc/internal/channelz"
41 "google.golang.org/grpc/internal/envconfig"
42 "google.golang.org/grpc/internal/grpcsync"
43 "google.golang.org/grpc/internal/transport"
33 "google.golang.org/grpc/keepalive" 44 "google.golang.org/grpc/keepalive"
34 "google.golang.org/grpc/stats" 45 "google.golang.org/grpc/metadata"
35 "google.golang.org/grpc/transport" 46 "google.golang.org/grpc/resolver"
47 _ "google.golang.org/grpc/resolver/dns" // To register dns resolver.
48 _ "google.golang.org/grpc/resolver/passthrough" // To register passthrough resolver.
49 "google.golang.org/grpc/status"
50)
51
52const (
53 // minimum time to give a connection to complete
54 minConnectTimeout = 20 * time.Second
55 // must match grpclbName in grpclb/grpclb.go
56 grpclbName = "grpclb"
36) 57)
37 58
38var ( 59var (
39 // ErrClientConnClosing indicates that the operation is illegal because 60 // ErrClientConnClosing indicates that the operation is illegal because
40 // the ClientConn is closing. 61 // the ClientConn is closing.
41 ErrClientConnClosing = errors.New("grpc: the client connection is closing") 62 //
42 // ErrClientConnTimeout indicates that the ClientConn cannot establish the 63 // Deprecated: this error should not be relied upon by users; use the status
43 // underlying connections within the specified timeout. 64 // code of Canceled instead.
44 // DEPRECATED: Please use context.DeadlineExceeded instead. 65 ErrClientConnClosing = status.Error(codes.Canceled, "grpc: the client connection is closing")
45 ErrClientConnTimeout = errors.New("grpc: timed out when dialing") 66 // errConnDrain indicates that the connection starts to be drained and does not accept any new RPCs.
67 errConnDrain = errors.New("grpc: the connection is drained")
68 // errConnClosing indicates that the connection is closing.
69 errConnClosing = errors.New("grpc: the connection is closing")
70 // errBalancerClosed indicates that the balancer is closed.
71 errBalancerClosed = errors.New("grpc: balancer is closed")
72 // We use an accessor so that minConnectTimeout can be
73 // atomically read and updated while testing.
74 getMinConnectTimeout = func() time.Duration {
75 return minConnectTimeout
76 }
77)
46 78
79// The following errors are returned from Dial and DialContext
80var (
47 // errNoTransportSecurity indicates that there is no transport security 81 // errNoTransportSecurity indicates that there is no transport security
48 // being set for ClientConn. Users should either set one or explicitly 82 // being set for ClientConn. Users should either set one or explicitly
49 // call WithInsecure DialOption to disable security. 83 // call WithInsecure DialOption to disable security.
50 errNoTransportSecurity = errors.New("grpc: no transport security set (use grpc.WithInsecure() explicitly or set credentials)") 84 errNoTransportSecurity = errors.New("grpc: no transport security set (use grpc.WithInsecure() explicitly or set credentials)")
85 // errTransportCredsAndBundle indicates that creds bundle is used together
86 // with other individual Transport Credentials.
87 errTransportCredsAndBundle = errors.New("grpc: credentials.Bundle may not be used with individual TransportCredentials")
51 // errTransportCredentialsMissing indicates that users want to transmit security 88 // errTransportCredentialsMissing indicates that users want to transmit security
52 // information (e.g., oauth2 token) which requires secure connection on an insecure 89 // information (e.g., oauth2 token) which requires secure connection on an insecure
53 // connection. 90 // connection.
@@ -55,278 +92,100 @@ var (
55 // errCredentialsConflict indicates that grpc.WithTransportCredentials() 92 // errCredentialsConflict indicates that grpc.WithTransportCredentials()
56 // and grpc.WithInsecure() are both called for a connection. 93 // and grpc.WithInsecure() are both called for a connection.
57 errCredentialsConflict = errors.New("grpc: transport credentials are set for an insecure connection (grpc.WithTransportCredentials() and grpc.WithInsecure() are both called)") 94 errCredentialsConflict = errors.New("grpc: transport credentials are set for an insecure connection (grpc.WithTransportCredentials() and grpc.WithInsecure() are both called)")
58 // errNetworkIO indicates that the connection is down due to some network I/O error.
59 errNetworkIO = errors.New("grpc: failed with network I/O error")
60 // errConnDrain indicates that the connection starts to be drained and does not accept any new RPCs.
61 errConnDrain = errors.New("grpc: the connection is drained")
62 // errConnClosing indicates that the connection is closing.
63 errConnClosing = errors.New("grpc: the connection is closing")
64 // errConnUnavailable indicates that the connection is unavailable.
65 errConnUnavailable = errors.New("grpc: the connection is unavailable")
66 // errBalancerClosed indicates that the balancer is closed.
67 errBalancerClosed = errors.New("grpc: balancer is closed")
68 // minimum time to give a connection to complete
69 minConnectTimeout = 20 * time.Second
70) 95)
71 96
72// dialOptions configure a Dial call. dialOptions are set by the DialOption
73// values passed to Dial.
74type dialOptions struct {
75 unaryInt UnaryClientInterceptor
76 streamInt StreamClientInterceptor
77 codec Codec
78 cp Compressor
79 dc Decompressor
80 bs backoffStrategy
81 balancer Balancer
82 block bool
83 insecure bool
84 timeout time.Duration
85 scChan <-chan ServiceConfig
86 copts transport.ConnectOptions
87 callOptions []CallOption
88}
89
90const ( 97const (
91 defaultClientMaxReceiveMessageSize = 1024 * 1024 * 4 98 defaultClientMaxReceiveMessageSize = 1024 * 1024 * 4
92 defaultClientMaxSendMessageSize = 1024 * 1024 * 4 99 defaultClientMaxSendMessageSize = math.MaxInt32
100 // http2IOBufSize specifies the buffer size for sending frames.
101 defaultWriteBufSize = 32 * 1024
102 defaultReadBufSize = 32 * 1024
93) 103)
94 104
95// DialOption configures how we set up the connection.
96type DialOption func(*dialOptions)
97
98// WithInitialWindowSize returns a DialOption which sets the value for initial window size on a stream.
99// The lower bound for window size is 64K and any value smaller than that will be ignored.
100func WithInitialWindowSize(s int32) DialOption {
101 return func(o *dialOptions) {
102 o.copts.InitialWindowSize = s
103 }
104}
105
106// WithInitialConnWindowSize returns a DialOption which sets the value for initial window size on a connection.
107// The lower bound for window size is 64K and any value smaller than that will be ignored.
108func WithInitialConnWindowSize(s int32) DialOption {
109 return func(o *dialOptions) {
110 o.copts.InitialConnWindowSize = s
111 }
112}
113
114// WithMaxMsgSize returns a DialOption which sets the maximum message size the client can receive. Deprecated: use WithDefaultCallOptions(MaxCallRecvMsgSize(s)) instead.
115func WithMaxMsgSize(s int) DialOption {
116 return WithDefaultCallOptions(MaxCallRecvMsgSize(s))
117}
118
119// WithDefaultCallOptions returns a DialOption which sets the default CallOptions for calls over the connection.
120func WithDefaultCallOptions(cos ...CallOption) DialOption {
121 return func(o *dialOptions) {
122 o.callOptions = append(o.callOptions, cos...)
123 }
124}
125
126// WithCodec returns a DialOption which sets a codec for message marshaling and unmarshaling.
127func WithCodec(c Codec) DialOption {
128 return func(o *dialOptions) {
129 o.codec = c
130 }
131}
132
133// WithCompressor returns a DialOption which sets a CompressorGenerator for generating message
134// compressor.
135func WithCompressor(cp Compressor) DialOption {
136 return func(o *dialOptions) {
137 o.cp = cp
138 }
139}
140
141// WithDecompressor returns a DialOption which sets a DecompressorGenerator for generating
142// message decompressor.
143func WithDecompressor(dc Decompressor) DialOption {
144 return func(o *dialOptions) {
145 o.dc = dc
146 }
147}
148
149// WithBalancer returns a DialOption which sets a load balancer.
150func WithBalancer(b Balancer) DialOption {
151 return func(o *dialOptions) {
152 o.balancer = b
153 }
154}
155
156// WithServiceConfig returns a DialOption which has a channel to read the service configuration.
157func WithServiceConfig(c <-chan ServiceConfig) DialOption {
158 return func(o *dialOptions) {
159 o.scChan = c
160 }
161}
162
163// WithBackoffMaxDelay configures the dialer to use the provided maximum delay
164// when backing off after failed connection attempts.
165func WithBackoffMaxDelay(md time.Duration) DialOption {
166 return WithBackoffConfig(BackoffConfig{MaxDelay: md})
167}
168
169// WithBackoffConfig configures the dialer to use the provided backoff
170// parameters after connection failures.
171//
172// Use WithBackoffMaxDelay until more parameters on BackoffConfig are opened up
173// for use.
174func WithBackoffConfig(b BackoffConfig) DialOption {
175 // Set defaults to ensure that provided BackoffConfig is valid and
176 // unexported fields get default values.
177 setDefaults(&b)
178 return withBackoff(b)
179}
180
181// withBackoff sets the backoff strategy used for retries after a
182// failed connection attempt.
183//
184// This can be exported if arbitrary backoff strategies are allowed by gRPC.
185func withBackoff(bs backoffStrategy) DialOption {
186 return func(o *dialOptions) {
187 o.bs = bs
188 }
189}
190
191// WithBlock returns a DialOption which makes caller of Dial blocks until the underlying
192// connection is up. Without this, Dial returns immediately and connecting the server
193// happens in background.
194func WithBlock() DialOption {
195 return func(o *dialOptions) {
196 o.block = true
197 }
198}
199
200// WithInsecure returns a DialOption which disables transport security for this ClientConn.
201// Note that transport security is required unless WithInsecure is set.
202func WithInsecure() DialOption {
203 return func(o *dialOptions) {
204 o.insecure = true
205 }
206}
207
208// WithTransportCredentials returns a DialOption which configures a
209// connection level security credentials (e.g., TLS/SSL).
210func WithTransportCredentials(creds credentials.TransportCredentials) DialOption {
211 return func(o *dialOptions) {
212 o.copts.TransportCredentials = creds
213 }
214}
215
216// WithPerRPCCredentials returns a DialOption which sets
217// credentials and places auth state on each outbound RPC.
218func WithPerRPCCredentials(creds credentials.PerRPCCredentials) DialOption {
219 return func(o *dialOptions) {
220 o.copts.PerRPCCredentials = append(o.copts.PerRPCCredentials, creds)
221 }
222}
223
224// WithTimeout returns a DialOption that configures a timeout for dialing a ClientConn
225// initially. This is valid if and only if WithBlock() is present.
226// Deprecated: use DialContext and context.WithTimeout instead.
227func WithTimeout(d time.Duration) DialOption {
228 return func(o *dialOptions) {
229 o.timeout = d
230 }
231}
232
233// WithDialer returns a DialOption that specifies a function to use for dialing network addresses.
234// If FailOnNonTempDialError() is set to true, and an error is returned by f, gRPC checks the error's
235// Temporary() method to decide if it should try to reconnect to the network address.
236func WithDialer(f func(string, time.Duration) (net.Conn, error)) DialOption {
237 return func(o *dialOptions) {
238 o.copts.Dialer = func(ctx context.Context, addr string) (net.Conn, error) {
239 if deadline, ok := ctx.Deadline(); ok {
240 return f(addr, deadline.Sub(time.Now()))
241 }
242 return f(addr, 0)
243 }
244 }
245}
246
247// WithStatsHandler returns a DialOption that specifies the stats handler
248// for all the RPCs and underlying network connections in this ClientConn.
249func WithStatsHandler(h stats.Handler) DialOption {
250 return func(o *dialOptions) {
251 o.copts.StatsHandler = h
252 }
253}
254
255// FailOnNonTempDialError returns a DialOption that specifies if gRPC fails on non-temporary dial errors.
256// If f is true, and dialer returns a non-temporary error, gRPC will fail the connection to the network
257// address and won't try to reconnect.
258// The default value of FailOnNonTempDialError is false.
259// This is an EXPERIMENTAL API.
260func FailOnNonTempDialError(f bool) DialOption {
261 return func(o *dialOptions) {
262 o.copts.FailOnNonTempDialError = f
263 }
264}
265
266// WithUserAgent returns a DialOption that specifies a user agent string for all the RPCs.
267func WithUserAgent(s string) DialOption {
268 return func(o *dialOptions) {
269 o.copts.UserAgent = s
270 }
271}
272
273// WithKeepaliveParams returns a DialOption that specifies keepalive paramaters for the client transport.
274func WithKeepaliveParams(kp keepalive.ClientParameters) DialOption {
275 return func(o *dialOptions) {
276 o.copts.KeepaliveParams = kp
277 }
278}
279
280// WithUnaryInterceptor returns a DialOption that specifies the interceptor for unary RPCs.
281func WithUnaryInterceptor(f UnaryClientInterceptor) DialOption {
282 return func(o *dialOptions) {
283 o.unaryInt = f
284 }
285}
286
287// WithStreamInterceptor returns a DialOption that specifies the interceptor for streaming RPCs.
288func WithStreamInterceptor(f StreamClientInterceptor) DialOption {
289 return func(o *dialOptions) {
290 o.streamInt = f
291 }
292}
293
294// WithAuthority returns a DialOption that specifies the value to be used as
295// the :authority pseudo-header. This value only works with WithInsecure and
296// has no effect if TransportCredentials are present.
297func WithAuthority(a string) DialOption {
298 return func(o *dialOptions) {
299 o.copts.Authority = a
300 }
301}
302
303// Dial creates a client connection to the given target. 105// Dial creates a client connection to the given target.
304func Dial(target string, opts ...DialOption) (*ClientConn, error) { 106func Dial(target string, opts ...DialOption) (*ClientConn, error) {
305 return DialContext(context.Background(), target, opts...) 107 return DialContext(context.Background(), target, opts...)
306} 108}
307 109
308// DialContext creates a client connection to the given target. ctx can be used to 110// DialContext creates a client connection to the given target. By default, it's
309// cancel or expire the pending connection. Once this function returns, the 111// a non-blocking dial (the function won't wait for connections to be
310// cancellation and expiration of ctx will be noop. Users should call ClientConn.Close 112// established, and connecting happens in the background). To make it a blocking
311// to terminate all the pending operations after this function returns. 113// dial, use WithBlock() dial option.
114//
115// In the non-blocking case, the ctx does not act against the connection. It
116// only controls the setup steps.
117//
118// In the blocking case, ctx can be used to cancel or expire the pending
119// connection. Once this function returns, the cancellation and expiration of
120// ctx will be noop. Users should call ClientConn.Close to terminate all the
121// pending operations after this function returns.
122//
123// The target name syntax is defined in
124// https://github.com/grpc/grpc/blob/master/doc/naming.md.
125// e.g. to use dns resolver, a "dns:///" prefix should be applied to the target.
312func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *ClientConn, err error) { 126func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *ClientConn, err error) {
313 cc := &ClientConn{ 127 cc := &ClientConn{
314 target: target, 128 target: target,
315 csMgr: &connectivityStateManager{}, 129 csMgr: &connectivityStateManager{},
316 conns: make(map[Address]*addrConn), 130 conns: make(map[*addrConn]struct{}),
317 } 131 dopts: defaultDialOptions(),
318 cc.csEvltr = &connectivityStateEvaluator{csMgr: cc.csMgr} 132 blockingpicker: newPickerWrapper(),
133 czData: new(channelzData),
134 firstResolveEvent: grpcsync.NewEvent(),
135 }
136 cc.retryThrottler.Store((*retryThrottler)(nil))
319 cc.ctx, cc.cancel = context.WithCancel(context.Background()) 137 cc.ctx, cc.cancel = context.WithCancel(context.Background())
320 138
321 for _, opt := range opts { 139 for _, opt := range opts {
322 opt(&cc.dopts) 140 opt.apply(&cc.dopts)
141 }
142
143 if channelz.IsOn() {
144 if cc.dopts.channelzParentID != 0 {
145 cc.channelzID = channelz.RegisterChannel(&channelzChannel{cc}, cc.dopts.channelzParentID, target)
146 channelz.AddTraceEvent(cc.channelzID, &channelz.TraceEventDesc{
147 Desc: "Channel Created",
148 Severity: channelz.CtINFO,
149 Parent: &channelz.TraceEventDesc{
150 Desc: fmt.Sprintf("Nested Channel(id:%d) created", cc.channelzID),
151 Severity: channelz.CtINFO,
152 },
153 })
154 } else {
155 cc.channelzID = channelz.RegisterChannel(&channelzChannel{cc}, 0, target)
156 channelz.AddTraceEvent(cc.channelzID, &channelz.TraceEventDesc{
157 Desc: "Channel Created",
158 Severity: channelz.CtINFO,
159 })
160 }
161 cc.csMgr.channelzID = cc.channelzID
323 } 162 }
163
164 if !cc.dopts.insecure {
165 if cc.dopts.copts.TransportCredentials == nil && cc.dopts.copts.CredsBundle == nil {
166 return nil, errNoTransportSecurity
167 }
168 if cc.dopts.copts.TransportCredentials != nil && cc.dopts.copts.CredsBundle != nil {
169 return nil, errTransportCredsAndBundle
170 }
171 } else {
172 if cc.dopts.copts.TransportCredentials != nil || cc.dopts.copts.CredsBundle != nil {
173 return nil, errCredentialsConflict
174 }
175 for _, cd := range cc.dopts.copts.PerRPCCredentials {
176 if cd.RequireTransportSecurity() {
177 return nil, errTransportCredentialsMissing
178 }
179 }
180 }
181
324 cc.mkp = cc.dopts.copts.KeepaliveParams 182 cc.mkp = cc.dopts.copts.KeepaliveParams
325 183
326 if cc.dopts.copts.Dialer == nil { 184 if cc.dopts.copts.Dialer == nil {
327 cc.dopts.copts.Dialer = newProxyDialer( 185 cc.dopts.copts.Dialer = newProxyDialer(
328 func(ctx context.Context, addr string) (net.Conn, error) { 186 func(ctx context.Context, addr string) (net.Conn, error) {
329 return dialContext(ctx, "tcp", addr) 187 network, addr := parseDialTarget(addr)
188 return (&net.Dialer{}).DialContext(ctx, network, addr)
330 }, 189 },
331 ) 190 )
332 } 191 }
@@ -367,66 +226,41 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
367 default: 226 default:
368 } 227 }
369 } 228 }
370 // Set defaults.
371 if cc.dopts.codec == nil {
372 cc.dopts.codec = protoCodec{}
373 }
374 if cc.dopts.bs == nil { 229 if cc.dopts.bs == nil {
375 cc.dopts.bs = DefaultBackoffConfig 230 cc.dopts.bs = backoff.Exponential{
231 MaxDelay: DefaultBackoffConfig.MaxDelay,
232 }
233 }
234 if cc.dopts.resolverBuilder == nil {
235 // Only try to parse target when resolver builder is not already set.
236 cc.parsedTarget = parseTarget(cc.target)
237 grpclog.Infof("parsed scheme: %q", cc.parsedTarget.Scheme)
238 cc.dopts.resolverBuilder = resolver.Get(cc.parsedTarget.Scheme)
239 if cc.dopts.resolverBuilder == nil {
240 // If resolver builder is still nil, the parse target's scheme is
241 // not registered. Fallback to default resolver and set Endpoint to
242 // the original unparsed target.
243 grpclog.Infof("scheme %q not registered, fallback to default scheme", cc.parsedTarget.Scheme)
244 cc.parsedTarget = resolver.Target{
245 Scheme: resolver.GetDefaultScheme(),
246 Endpoint: target,
247 }
248 cc.dopts.resolverBuilder = resolver.Get(cc.parsedTarget.Scheme)
249 }
250 } else {
251 cc.parsedTarget = resolver.Target{Endpoint: target}
376 } 252 }
377 creds := cc.dopts.copts.TransportCredentials 253 creds := cc.dopts.copts.TransportCredentials
378 if creds != nil && creds.Info().ServerName != "" { 254 if creds != nil && creds.Info().ServerName != "" {
379 cc.authority = creds.Info().ServerName 255 cc.authority = creds.Info().ServerName
380 } else if cc.dopts.insecure && cc.dopts.copts.Authority != "" { 256 } else if cc.dopts.insecure && cc.dopts.authority != "" {
381 cc.authority = cc.dopts.copts.Authority 257 cc.authority = cc.dopts.authority
382 } else { 258 } else {
383 cc.authority = target 259 // Use endpoint from "scheme://authority/endpoint" as the default
384 } 260 // authority for ClientConn.
385 waitC := make(chan error, 1) 261 cc.authority = cc.parsedTarget.Endpoint
386 go func() {
387 defer close(waitC)
388 if cc.dopts.balancer == nil && cc.sc.LB != nil {
389 cc.dopts.balancer = cc.sc.LB
390 }
391 if cc.dopts.balancer != nil {
392 var credsClone credentials.TransportCredentials
393 if creds != nil {
394 credsClone = creds.Clone()
395 }
396 config := BalancerConfig{
397 DialCreds: credsClone,
398 Dialer: cc.dopts.copts.Dialer,
399 }
400 if err := cc.dopts.balancer.Start(target, config); err != nil {
401 waitC <- err
402 return
403 }
404 ch := cc.dopts.balancer.Notify()
405 if ch != nil {
406 if cc.dopts.block {
407 doneChan := make(chan struct{})
408 go cc.lbWatcher(doneChan)
409 <-doneChan
410 } else {
411 go cc.lbWatcher(nil)
412 }
413 return
414 }
415 }
416 // No balancer, or no resolver within the balancer. Connect directly.
417 if err := cc.resetAddrConn(Address{Addr: target}, cc.dopts.block, nil); err != nil {
418 waitC <- err
419 return
420 }
421 }()
422 select {
423 case <-ctx.Done():
424 return nil, ctx.Err()
425 case err := <-waitC:
426 if err != nil {
427 return nil, err
428 }
429 } 262 }
263
430 if cc.dopts.scChan != nil && !scSet { 264 if cc.dopts.scChan != nil && !scSet {
431 // Blocking wait for the initial service config. 265 // Blocking wait for the initial service config.
432 select { 266 select {
@@ -442,55 +276,50 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
442 go cc.scWatcher() 276 go cc.scWatcher()
443 } 277 }
444 278
445 return cc, nil 279 var credsClone credentials.TransportCredentials
446} 280 if creds := cc.dopts.copts.TransportCredentials; creds != nil {
281 credsClone = creds.Clone()
282 }
283 cc.balancerBuildOpts = balancer.BuildOptions{
284 DialCreds: credsClone,
285 CredsBundle: cc.dopts.copts.CredsBundle,
286 Dialer: cc.dopts.copts.Dialer,
287 ChannelzParentID: cc.channelzID,
288 }
447 289
448// connectivityStateEvaluator gets updated by addrConns when their 290 // Build the resolver.
449// states transition, based on which it evaluates the state of 291 rWrapper, err := newCCResolverWrapper(cc)
450// ClientConn. 292 if err != nil {
451// Note: This code will eventually sit in the balancer in the new design. 293 return nil, fmt.Errorf("failed to build resolver: %v", err)
452type connectivityStateEvaluator struct { 294 }
453 csMgr *connectivityStateManager
454 mu sync.Mutex
455 numReady uint64 // Number of addrConns in ready state.
456 numConnecting uint64 // Number of addrConns in connecting state.
457 numTransientFailure uint64 // Number of addrConns in transientFailure.
458}
459 295
460// recordTransition records state change happening in every addrConn and based on 296 cc.mu.Lock()
461// that it evaluates what state the ClientConn is in. 297 cc.resolverWrapper = rWrapper
462// It can only transition between connectivity.Ready, connectivity.Connecting and connectivity.TransientFailure. Other states, 298 cc.mu.Unlock()
463// Idle and connectivity.Shutdown are transitioned into by ClientConn; in the begining of the connection 299 // A blocking dial blocks until the clientConn is ready.
464// before any addrConn is created ClientConn is in idle state. In the end when ClientConn 300 if cc.dopts.block {
465// closes it is in connectivity.Shutdown state. 301 for {
466// TODO Note that in later releases, a ClientConn with no activity will be put into an Idle state. 302 s := cc.GetState()
467func (cse *connectivityStateEvaluator) recordTransition(oldState, newState connectivity.State) { 303 if s == connectivity.Ready {
468 cse.mu.Lock() 304 break
469 defer cse.mu.Unlock() 305 } else if cc.dopts.copts.FailOnNonTempDialError && s == connectivity.TransientFailure {
470 306 if err = cc.blockingpicker.connectionError(); err != nil {
471 // Update counters. 307 terr, ok := err.(interface {
472 for idx, state := range []connectivity.State{oldState, newState} { 308 Temporary() bool
473 updateVal := 2*uint64(idx) - 1 // -1 for oldState and +1 for new. 309 })
474 switch state { 310 if ok && !terr.Temporary() {
475 case connectivity.Ready: 311 return nil, err
476 cse.numReady += updateVal 312 }
477 case connectivity.Connecting: 313 }
478 cse.numConnecting += updateVal 314 }
479 case connectivity.TransientFailure: 315 if !cc.WaitForStateChange(ctx, s) {
480 cse.numTransientFailure += updateVal 316 // ctx got timeout or canceled.
317 return nil, ctx.Err()
318 }
481 } 319 }
482 } 320 }
483 321
484 // Evaluate. 322 return cc, nil
485 if cse.numReady > 0 {
486 cse.csMgr.updateState(connectivity.Ready)
487 return
488 }
489 if cse.numConnecting > 0 {
490 cse.csMgr.updateState(connectivity.Connecting)
491 return
492 }
493 cse.csMgr.updateState(connectivity.TransientFailure)
494} 323}
495 324
496// connectivityStateManager keeps the connectivity.State of ClientConn. 325// connectivityStateManager keeps the connectivity.State of ClientConn.
@@ -499,6 +328,7 @@ type connectivityStateManager struct {
499 mu sync.Mutex 328 mu sync.Mutex
500 state connectivity.State 329 state connectivity.State
501 notifyChan chan struct{} 330 notifyChan chan struct{}
331 channelzID int64
502} 332}
503 333
504// updateState updates the connectivity.State of ClientConn. 334// updateState updates the connectivity.State of ClientConn.
@@ -514,6 +344,12 @@ func (csm *connectivityStateManager) updateState(state connectivity.State) {
514 return 344 return
515 } 345 }
516 csm.state = state 346 csm.state = state
347 if channelz.IsOn() {
348 channelz.AddTraceEvent(csm.channelzID, &channelz.TraceEventDesc{
349 Desc: fmt.Sprintf("Channel Connectivity change to %v", state),
350 Severity: channelz.CtINFO,
351 })
352 }
517 if csm.notifyChan != nil { 353 if csm.notifyChan != nil {
518 // There are other goroutines waiting on this channel. 354 // There are other goroutines waiting on this channel.
519 close(csm.notifyChan) 355 close(csm.notifyChan)
@@ -541,17 +377,32 @@ type ClientConn struct {
541 ctx context.Context 377 ctx context.Context
542 cancel context.CancelFunc 378 cancel context.CancelFunc
543 379
544 target string 380 target string
545 authority string 381 parsedTarget resolver.Target
546 dopts dialOptions 382 authority string
547 csMgr *connectivityStateManager 383 dopts dialOptions
548 csEvltr *connectivityStateEvaluator // This will eventually be part of balancer. 384 csMgr *connectivityStateManager
549 385
550 mu sync.RWMutex 386 balancerBuildOpts balancer.BuildOptions
551 sc ServiceConfig 387 blockingpicker *pickerWrapper
552 conns map[Address]*addrConn 388
389 mu sync.RWMutex
390 resolverWrapper *ccResolverWrapper
391 sc ServiceConfig
392 scRaw string
393 conns map[*addrConn]struct{}
553 // Keepalive parameter can be updated if a GoAway is received. 394 // Keepalive parameter can be updated if a GoAway is received.
554 mkp keepalive.ClientParameters 395 mkp keepalive.ClientParameters
396 curBalancerName string
397 preBalancerName string // previous balancer name.
398 curAddresses []resolver.Address
399 balancerWrapper *ccBalancerWrapper
400 retryThrottler atomic.Value
401
402 firstResolveEvent *grpcsync.Event
403
404 channelzID int64 // channelz unique identification number
405 czData *channelzData
555} 406}
556 407
557// WaitForStateChange waits until the connectivity.State of ClientConn changes from sourceState or 408// WaitForStateChange waits until the connectivity.State of ClientConn changes from sourceState or
@@ -576,65 +427,6 @@ func (cc *ClientConn) GetState() connectivity.State {
576 return cc.csMgr.getState() 427 return cc.csMgr.getState()
577} 428}
578 429
579// lbWatcher watches the Notify channel of the balancer in cc and manages
580// connections accordingly. If doneChan is not nil, it is closed after the
581// first successfull connection is made.
582func (cc *ClientConn) lbWatcher(doneChan chan struct{}) {
583 defer func() {
584 // In case channel from cc.dopts.balancer.Notify() gets closed before a
585 // successful connection gets established, don't forget to notify the
586 // caller.
587 if doneChan != nil {
588 close(doneChan)
589 }
590 }()
591
592 for addrs := range cc.dopts.balancer.Notify() {
593 var (
594 add []Address // Addresses need to setup connections.
595 del []*addrConn // Connections need to tear down.
596 )
597 cc.mu.Lock()
598 for _, a := range addrs {
599 if _, ok := cc.conns[a]; !ok {
600 add = append(add, a)
601 }
602 }
603 for k, c := range cc.conns {
604 var keep bool
605 for _, a := range addrs {
606 if k == a {
607 keep = true
608 break
609 }
610 }
611 if !keep {
612 del = append(del, c)
613 delete(cc.conns, c.addr)
614 }
615 }
616 cc.mu.Unlock()
617 for _, a := range add {
618 var err error
619 if doneChan != nil {
620 err = cc.resetAddrConn(a, true, nil)
621 if err == nil {
622 close(doneChan)
623 doneChan = nil
624 }
625 } else {
626 err = cc.resetAddrConn(a, false, nil)
627 }
628 if err != nil {
629 grpclog.Warningf("Error creating connection to %v. Err: %v", a, err)
630 }
631 }
632 for _, c := range del {
633 c.tearDown(errConnDrain)
634 }
635 }
636}
637
638func (cc *ClientConn) scWatcher() { 430func (cc *ClientConn) scWatcher() {
639 for { 431 for {
640 select { 432 select {
@@ -646,6 +438,7 @@ func (cc *ClientConn) scWatcher() {
646 // TODO: load balance policy runtime change is ignored. 438 // TODO: load balance policy runtime change is ignored.
647 // We may revist this decision in the future. 439 // We may revist this decision in the future.
648 cc.sc = sc 440 cc.sc = sc
441 cc.scRaw = ""
649 cc.mu.Unlock() 442 cc.mu.Unlock()
650 case <-cc.ctx.Done(): 443 case <-cc.ctx.Done():
651 return 444 return
@@ -653,99 +446,287 @@ func (cc *ClientConn) scWatcher() {
653 } 446 }
654} 447}
655 448
656// resetAddrConn creates an addrConn for addr and adds it to cc.conns. 449// waitForResolvedAddrs blocks until the resolver has provided addresses or the
657// If there is an old addrConn for addr, it will be torn down, using tearDownErr as the reason. 450// context expires. Returns nil unless the context expires first; otherwise
658// If tearDownErr is nil, errConnDrain will be used instead. 451// returns a status error based on the context.
659// 452func (cc *ClientConn) waitForResolvedAddrs(ctx context.Context) error {
660// We should never need to replace an addrConn with a new one. This function is only used 453 // This is on the RPC path, so we use a fast path to avoid the
661// as newAddrConn to create new addrConn. 454 // more-expensive "select" below after the resolver has returned once.
662// TODO rename this function and clean up the code. 455 if cc.firstResolveEvent.HasFired() {
663func (cc *ClientConn) resetAddrConn(addr Address, block bool, tearDownErr error) error { 456 return nil
664 ac := &addrConn{
665 cc: cc,
666 addr: addr,
667 dopts: cc.dopts,
668 } 457 }
669 ac.ctx, ac.cancel = context.WithCancel(cc.ctx) 458 select {
670 ac.csEvltr = cc.csEvltr 459 case <-cc.firstResolveEvent.Done():
671 if EnableTracing { 460 return nil
672 ac.events = trace.NewEventLog("grpc.ClientConn", ac.addr.Addr) 461 case <-ctx.Done():
462 return status.FromContextError(ctx.Err()).Err()
463 case <-cc.ctx.Done():
464 return ErrClientConnClosing
673 } 465 }
674 if !ac.dopts.insecure { 466}
675 if ac.dopts.copts.TransportCredentials == nil { 467
676 return errNoTransportSecurity 468func (cc *ClientConn) handleResolvedAddrs(addrs []resolver.Address, err error) {
677 } 469 cc.mu.Lock()
678 } else { 470 defer cc.mu.Unlock()
679 if ac.dopts.copts.TransportCredentials != nil { 471 if cc.conns == nil {
680 return errCredentialsConflict 472 // cc was closed.
473 return
474 }
475
476 if reflect.DeepEqual(cc.curAddresses, addrs) {
477 return
478 }
479
480 cc.curAddresses = addrs
481 cc.firstResolveEvent.Fire()
482
483 if cc.dopts.balancerBuilder == nil {
484 // Only look at balancer types and switch balancer if balancer dial
485 // option is not set.
486 var isGRPCLB bool
487 for _, a := range addrs {
488 if a.Type == resolver.GRPCLB {
489 isGRPCLB = true
490 break
491 }
681 } 492 }
682 for _, cd := range ac.dopts.copts.PerRPCCredentials { 493 var newBalancerName string
683 if cd.RequireTransportSecurity() { 494 if isGRPCLB {
684 return errTransportCredentialsMissing 495 newBalancerName = grpclbName
496 } else {
497 // Address list doesn't contain grpclb address. Try to pick a
498 // non-grpclb balancer.
499 newBalancerName = cc.curBalancerName
500 // If current balancer is grpclb, switch to the previous one.
501 if newBalancerName == grpclbName {
502 newBalancerName = cc.preBalancerName
503 }
504 // The following could be true in two cases:
505 // - the first time handling resolved addresses
506 // (curBalancerName="")
507 // - the first time handling non-grpclb addresses
508 // (curBalancerName="grpclb", preBalancerName="")
509 if newBalancerName == "" {
510 newBalancerName = PickFirstBalancerName
685 } 511 }
686 } 512 }
513 cc.switchBalancer(newBalancerName)
514 } else if cc.balancerWrapper == nil {
515 // Balancer dial option was set, and this is the first time handling
516 // resolved addresses. Build a balancer with dopts.balancerBuilder.
517 cc.balancerWrapper = newCCBalancerWrapper(cc, cc.dopts.balancerBuilder, cc.balancerBuildOpts)
687 } 518 }
519
520 cc.balancerWrapper.handleResolvedAddrs(addrs, nil)
521}
522
523// switchBalancer starts the switching from current balancer to the balancer
524// with the given name.
525//
526// It will NOT send the current address list to the new balancer. If needed,
527// caller of this function should send address list to the new balancer after
528// this function returns.
529//
530// Caller must hold cc.mu.
531func (cc *ClientConn) switchBalancer(name string) {
532 if cc.conns == nil {
533 return
534 }
535
536 if strings.ToLower(cc.curBalancerName) == strings.ToLower(name) {
537 return
538 }
539
540 grpclog.Infof("ClientConn switching balancer to %q", name)
541 if cc.dopts.balancerBuilder != nil {
542 grpclog.Infoln("ignoring balancer switching: Balancer DialOption used instead")
543 return
544 }
545 // TODO(bar switching) change this to two steps: drain and close.
546 // Keep track of sc in wrapper.
547 if cc.balancerWrapper != nil {
548 cc.balancerWrapper.close()
549 }
550
551 builder := balancer.Get(name)
552 // TODO(yuxuanli): If user send a service config that does not contain a valid balancer name, should
553 // we reuse previous one?
554 if channelz.IsOn() {
555 if builder == nil {
556 channelz.AddTraceEvent(cc.channelzID, &channelz.TraceEventDesc{
557 Desc: fmt.Sprintf("Channel switches to new LB policy %q due to fallback from invalid balancer name", PickFirstBalancerName),
558 Severity: channelz.CtWarning,
559 })
560 } else {
561 channelz.AddTraceEvent(cc.channelzID, &channelz.TraceEventDesc{
562 Desc: fmt.Sprintf("Channel switches to new LB policy %q", name),
563 Severity: channelz.CtINFO,
564 })
565 }
566 }
567 if builder == nil {
568 grpclog.Infof("failed to get balancer builder for: %v, using pick_first instead", name)
569 builder = newPickfirstBuilder()
570 }
571
572 cc.preBalancerName = cc.curBalancerName
573 cc.curBalancerName = builder.Name()
574 cc.balancerWrapper = newCCBalancerWrapper(cc, builder, cc.balancerBuildOpts)
575}
576
577func (cc *ClientConn) handleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
578 cc.mu.Lock()
579 if cc.conns == nil {
580 cc.mu.Unlock()
581 return
582 }
583 // TODO(bar switching) send updates to all balancer wrappers when balancer
584 // gracefully switching is supported.
585 cc.balancerWrapper.handleSubConnStateChange(sc, s)
586 cc.mu.Unlock()
587}
588
589// newAddrConn creates an addrConn for addrs and adds it to cc.conns.
590//
591// Caller needs to make sure len(addrs) > 0.
592func (cc *ClientConn) newAddrConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (*addrConn, error) {
593 ac := &addrConn{
594 cc: cc,
595 addrs: addrs,
596 scopts: opts,
597 dopts: cc.dopts,
598 czData: new(channelzData),
599 resetBackoff: make(chan struct{}),
600 }
601 ac.ctx, ac.cancel = context.WithCancel(cc.ctx)
688 // Track ac in cc. This needs to be done before any getTransport(...) is called. 602 // Track ac in cc. This needs to be done before any getTransport(...) is called.
689 cc.mu.Lock() 603 cc.mu.Lock()
690 if cc.conns == nil { 604 if cc.conns == nil {
691 cc.mu.Unlock() 605 cc.mu.Unlock()
692 return ErrClientConnClosing 606 return nil, ErrClientConnClosing
607 }
608 if channelz.IsOn() {
609 ac.channelzID = channelz.RegisterSubChannel(ac, cc.channelzID, "")
610 channelz.AddTraceEvent(ac.channelzID, &channelz.TraceEventDesc{
611 Desc: "Subchannel Created",
612 Severity: channelz.CtINFO,
613 Parent: &channelz.TraceEventDesc{
614 Desc: fmt.Sprintf("Subchannel(id:%d) created", ac.channelzID),
615 Severity: channelz.CtINFO,
616 },
617 })
693 } 618 }
694 stale := cc.conns[ac.addr] 619 cc.conns[ac] = struct{}{}
695 cc.conns[ac.addr] = ac
696 cc.mu.Unlock() 620 cc.mu.Unlock()
697 if stale != nil { 621 return ac, nil
698 // There is an addrConn alive on ac.addr already. This could be due to 622}
699 // a buggy Balancer that reports duplicated Addresses. 623
700 if tearDownErr == nil { 624// removeAddrConn removes the addrConn in the subConn from clientConn.
701 // tearDownErr is nil if resetAddrConn is called by 625// It also tears down the ac with the given error.
702 // 1) Dial 626func (cc *ClientConn) removeAddrConn(ac *addrConn, err error) {
703 // 2) lbWatcher 627 cc.mu.Lock()
704 // In both cases, the stale ac should drain, not close. 628 if cc.conns == nil {
705 stale.tearDown(errConnDrain) 629 cc.mu.Unlock()
706 } else { 630 return
707 stale.tearDown(tearDownErr)
708 }
709 } 631 }
710 if block { 632 delete(cc.conns, ac)
711 if err := ac.resetTransport(false); err != nil { 633 cc.mu.Unlock()
712 if err != errConnClosing { 634 ac.tearDown(err)
713 // Tear down ac and delete it from cc.conns. 635}
714 cc.mu.Lock() 636
715 delete(cc.conns, ac.addr) 637func (cc *ClientConn) channelzMetric() *channelz.ChannelInternalMetric {
716 cc.mu.Unlock() 638 return &channelz.ChannelInternalMetric{
717 ac.tearDown(err) 639 State: cc.GetState(),
718 } 640 Target: cc.target,
719 if e, ok := err.(transport.ConnectionError); ok && !e.Temporary() { 641 CallsStarted: atomic.LoadInt64(&cc.czData.callsStarted),
720 return e.Origin() 642 CallsSucceeded: atomic.LoadInt64(&cc.czData.callsSucceeded),
721 } 643 CallsFailed: atomic.LoadInt64(&cc.czData.callsFailed),
722 return err 644 LastCallStartedTimestamp: time.Unix(0, atomic.LoadInt64(&cc.czData.lastCallStartedTime)),
723 } 645 }
724 // Start to monitor the error status of transport. 646}
725 go ac.transportMonitor() 647
726 } else { 648// Target returns the target string of the ClientConn.
727 // Start a goroutine connecting to the server asynchronously. 649// This is an EXPERIMENTAL API.
728 go func() { 650func (cc *ClientConn) Target() string {
729 if err := ac.resetTransport(false); err != nil { 651 return cc.target
730 grpclog.Warningf("Failed to dial %s: %v; please retry.", ac.addr.Addr, err) 652}
731 if err != errConnClosing { 653
732 // Keep this ac in cc.conns, to get the reason it's torn down. 654func (cc *ClientConn) incrCallsStarted() {
733 ac.tearDown(err) 655 atomic.AddInt64(&cc.czData.callsStarted, 1)
734 } 656 atomic.StoreInt64(&cc.czData.lastCallStartedTime, time.Now().UnixNano())
735 return 657}
736 } 658
737 ac.transportMonitor() 659func (cc *ClientConn) incrCallsSucceeded() {
738 }() 660 atomic.AddInt64(&cc.czData.callsSucceeded, 1)
661}
662
663func (cc *ClientConn) incrCallsFailed() {
664 atomic.AddInt64(&cc.czData.callsFailed, 1)
665}
666
667// connect starts creating a transport.
668// It does nothing if the ac is not IDLE.
669// TODO(bar) Move this to the addrConn section.
670func (ac *addrConn) connect() error {
671 ac.mu.Lock()
672 if ac.state == connectivity.Shutdown {
673 ac.mu.Unlock()
674 return errConnClosing
675 }
676 if ac.state != connectivity.Idle {
677 ac.mu.Unlock()
678 return nil
739 } 679 }
680 ac.updateConnectivityState(connectivity.Connecting)
681 ac.mu.Unlock()
682
683 // Start a goroutine connecting to the server asynchronously.
684 go ac.resetTransport()
740 return nil 685 return nil
741} 686}
742 687
688// tryUpdateAddrs tries to update ac.addrs with the new addresses list.
689//
690// It checks whether current connected address of ac is in the new addrs list.
691// - If true, it updates ac.addrs and returns true. The ac will keep using
692// the existing connection.
693// - If false, it does nothing and returns false.
694func (ac *addrConn) tryUpdateAddrs(addrs []resolver.Address) bool {
695 ac.mu.Lock()
696 defer ac.mu.Unlock()
697 grpclog.Infof("addrConn: tryUpdateAddrs curAddr: %v, addrs: %v", ac.curAddr, addrs)
698 if ac.state == connectivity.Shutdown {
699 ac.addrs = addrs
700 return true
701 }
702
703 // Unless we're busy reconnecting already, let's reconnect from the top of
704 // the list.
705 if ac.state != connectivity.Ready {
706 return false
707 }
708
709 var curAddrFound bool
710 for _, a := range addrs {
711 if reflect.DeepEqual(ac.curAddr, a) {
712 curAddrFound = true
713 break
714 }
715 }
716 grpclog.Infof("addrConn: tryUpdateAddrs curAddrFound: %v", curAddrFound)
717 if curAddrFound {
718 ac.addrs = addrs
719 }
720
721 return curAddrFound
722}
723
743// GetMethodConfig gets the method config of the input method. 724// GetMethodConfig gets the method config of the input method.
744// If there's an exact match for input method (i.e. /service/method), we return 725// If there's an exact match for input method (i.e. /service/method), we return
745// the corresponding MethodConfig. 726// the corresponding MethodConfig.
746// If there isn't an exact match for the input method, we look for the default config 727// If there isn't an exact match for the input method, we look for the default config
747// under the service (i.e /service/). If there is a default MethodConfig for 728// under the service (i.e /service/). If there is a default MethodConfig for
748// the serivce, we return it. 729// the service, we return it.
749// Otherwise, we return an empty MethodConfig. 730// Otherwise, we return an empty MethodConfig.
750func (cc *ClientConn) GetMethodConfig(method string) MethodConfig { 731func (cc *ClientConn) GetMethodConfig(method string) MethodConfig {
751 // TODO: Avoid the locking here. 732 // TODO: Avoid the locking here.
@@ -754,68 +735,122 @@ func (cc *ClientConn) GetMethodConfig(method string) MethodConfig {
754 m, ok := cc.sc.Methods[method] 735 m, ok := cc.sc.Methods[method]
755 if !ok { 736 if !ok {
756 i := strings.LastIndex(method, "/") 737 i := strings.LastIndex(method, "/")
757 m, _ = cc.sc.Methods[method[:i+1]] 738 m = cc.sc.Methods[method[:i+1]]
758 } 739 }
759 return m 740 return m
760} 741}
761 742
762func (cc *ClientConn) getTransport(ctx context.Context, opts BalancerGetOptions) (transport.ClientTransport, func(), error) { 743func (cc *ClientConn) healthCheckConfig() *healthCheckConfig {
763 var ( 744 cc.mu.RLock()
764 ac *addrConn 745 defer cc.mu.RUnlock()
765 ok bool 746 return cc.sc.healthCheckConfig
766 put func() 747}
767 ) 748
768 if cc.dopts.balancer == nil { 749func (cc *ClientConn) getTransport(ctx context.Context, failfast bool, method string) (transport.ClientTransport, func(balancer.DoneInfo), error) {
769 // If balancer is nil, there should be only one addrConn available. 750 hdr, _ := metadata.FromOutgoingContext(ctx)
770 cc.mu.RLock() 751 t, done, err := cc.blockingpicker.pick(ctx, failfast, balancer.PickOptions{
771 if cc.conns == nil { 752 FullMethodName: method,
772 cc.mu.RUnlock() 753 Header: hdr,
773 return nil, nil, toRPCErr(ErrClientConnClosing) 754 })
774 } 755 if err != nil {
775 for _, ac = range cc.conns { 756 return nil, nil, toRPCErr(err)
776 // Break after the first iteration to get the first addrConn. 757 }
777 ok = true 758 return t, done, nil
778 break 759}
760
761// handleServiceConfig parses the service config string in JSON format to Go native
762// struct ServiceConfig, and store both the struct and the JSON string in ClientConn.
763func (cc *ClientConn) handleServiceConfig(js string) error {
764 if cc.dopts.disableServiceConfig {
765 return nil
766 }
767 if cc.scRaw == js {
768 return nil
769 }
770 if channelz.IsOn() {
771 channelz.AddTraceEvent(cc.channelzID, &channelz.TraceEventDesc{
772 // The special formatting of \"%s\" instead of %q is to provide nice printing of service config
773 // for human consumption.
774 Desc: fmt.Sprintf("Channel has a new service config \"%s\"", js),
775 Severity: channelz.CtINFO,
776 })
777 }
778 sc, err := parseServiceConfig(js)
779 if err != nil {
780 return err
781 }
782 cc.mu.Lock()
783 // Check if the ClientConn is already closed. Some fields (e.g.
784 // balancerWrapper) are set to nil when closing the ClientConn, and could
785 // cause nil pointer panic if we don't have this check.
786 if cc.conns == nil {
787 cc.mu.Unlock()
788 return nil
789 }
790 cc.scRaw = js
791 cc.sc = sc
792
793 if sc.retryThrottling != nil {
794 newThrottler := &retryThrottler{
795 tokens: sc.retryThrottling.MaxTokens,
796 max: sc.retryThrottling.MaxTokens,
797 thresh: sc.retryThrottling.MaxTokens / 2,
798 ratio: sc.retryThrottling.TokenRatio,
779 } 799 }
780 cc.mu.RUnlock() 800 cc.retryThrottler.Store(newThrottler)
781 } else { 801 } else {
782 var ( 802 cc.retryThrottler.Store((*retryThrottler)(nil))
783 addr Address
784 err error
785 )
786 addr, put, err = cc.dopts.balancer.Get(ctx, opts)
787 if err != nil {
788 return nil, nil, toRPCErr(err)
789 }
790 cc.mu.RLock()
791 if cc.conns == nil {
792 cc.mu.RUnlock()
793 return nil, nil, toRPCErr(ErrClientConnClosing)
794 }
795 ac, ok = cc.conns[addr]
796 cc.mu.RUnlock()
797 } 803 }
798 if !ok { 804
799 if put != nil { 805 if sc.LB != nil && *sc.LB != grpclbName { // "grpclb" is not a valid balancer option in service config.
800 updateRPCInfoInContext(ctx, rpcInfo{bytesSent: false, bytesReceived: false}) 806 if cc.curBalancerName == grpclbName {
801 put() 807 // If current balancer is grpclb, there's at least one grpclb
808 // balancer address in the resolved list. Don't switch the balancer,
809 // but change the previous balancer name, so if a new resolved
810 // address list doesn't contain grpclb address, balancer will be
811 // switched to *sc.LB.
812 cc.preBalancerName = *sc.LB
813 } else {
814 cc.switchBalancer(*sc.LB)
815 cc.balancerWrapper.handleResolvedAddrs(cc.curAddresses, nil)
802 } 816 }
803 return nil, nil, errConnClosing
804 } 817 }
805 t, err := ac.wait(ctx, cc.dopts.balancer != nil, !opts.BlockingWait) 818
806 if err != nil { 819 cc.mu.Unlock()
807 if put != nil { 820 return nil
808 updateRPCInfoInContext(ctx, rpcInfo{bytesSent: false, bytesReceived: false}) 821}
809 put() 822
810 } 823func (cc *ClientConn) resolveNow(o resolver.ResolveNowOption) {
811 return nil, nil, err 824 cc.mu.RLock()
825 r := cc.resolverWrapper
826 cc.mu.RUnlock()
827 if r == nil {
828 return
829 }
830 go r.resolveNow(o)
831}
832
833// ResetConnectBackoff wakes up all subchannels in transient failure and causes
834// them to attempt another connection immediately. It also resets the backoff
835// times used for subsequent attempts regardless of the current state.
836//
837// In general, this function should not be used. Typical service or network
838// outages result in a reasonable client reconnection strategy by default.
839// However, if a previously unavailable network becomes available, this may be
840// used to trigger an immediate reconnect.
841//
842// This API is EXPERIMENTAL.
843func (cc *ClientConn) ResetConnectBackoff() {
844 cc.mu.Lock()
845 defer cc.mu.Unlock()
846 for ac := range cc.conns {
847 ac.resetConnectBackoff()
812 } 848 }
813 return t, put, nil
814} 849}
815 850
816// Close tears down the ClientConn and all underlying connections. 851// Close tears down the ClientConn and all underlying connections.
817func (cc *ClientConn) Close() error { 852func (cc *ClientConn) Close() error {
818 cc.cancel() 853 defer cc.cancel()
819 854
820 cc.mu.Lock() 855 cc.mu.Lock()
821 if cc.conns == nil { 856 if cc.conns == nil {
@@ -825,13 +860,41 @@ func (cc *ClientConn) Close() error {
825 conns := cc.conns 860 conns := cc.conns
826 cc.conns = nil 861 cc.conns = nil
827 cc.csMgr.updateState(connectivity.Shutdown) 862 cc.csMgr.updateState(connectivity.Shutdown)
863
864 rWrapper := cc.resolverWrapper
865 cc.resolverWrapper = nil
866 bWrapper := cc.balancerWrapper
867 cc.balancerWrapper = nil
828 cc.mu.Unlock() 868 cc.mu.Unlock()
829 if cc.dopts.balancer != nil { 869
830 cc.dopts.balancer.Close() 870 cc.blockingpicker.close()
871
872 if rWrapper != nil {
873 rWrapper.close()
831 } 874 }
832 for _, ac := range conns { 875 if bWrapper != nil {
876 bWrapper.close()
877 }
878
879 for ac := range conns {
833 ac.tearDown(ErrClientConnClosing) 880 ac.tearDown(ErrClientConnClosing)
834 } 881 }
882 if channelz.IsOn() {
883 ted := &channelz.TraceEventDesc{
884 Desc: "Channel Deleted",
885 Severity: channelz.CtINFO,
886 }
887 if cc.dopts.channelzParentID != 0 {
888 ted.Parent = &channelz.TraceEventDesc{
889 Desc: fmt.Sprintf("Nested channel(id:%d) deleted", cc.channelzID),
890 Severity: channelz.CtINFO,
891 }
892 }
893 channelz.AddTraceEvent(cc.channelzID, ted)
894 // TraceEvent needs to be called before RemoveEntry, as TraceEvent may add trace reference to
895 // the entity beng deleted, and thus prevent it from being deleted right away.
896 channelz.RemoveEntry(cc.channelzID)
897 }
835 return nil 898 return nil
836} 899}
837 900
@@ -841,29 +904,56 @@ type addrConn struct {
841 cancel context.CancelFunc 904 cancel context.CancelFunc
842 905
843 cc *ClientConn 906 cc *ClientConn
844 addr Address
845 dopts dialOptions 907 dopts dialOptions
846 events trace.EventLog 908 acbw balancer.SubConn
909 scopts balancer.NewSubConnOptions
910
911 // transport is set when there's a viable transport (note: ac state may not be READY as LB channel
912 // health checking may require server to report healthy to set ac to READY), and is reset
913 // to nil when the current transport should no longer be used to create a stream (e.g. after GoAway
914 // is received, transport is closed, ac has been torn down).
915 transport transport.ClientTransport // The current transport.
847 916
848 csEvltr *connectivityStateEvaluator 917 mu sync.Mutex
918 curAddr resolver.Address // The current address.
919 addrs []resolver.Address // All addresses that the resolver resolved to.
849 920
850 mu sync.Mutex 921 // Use updateConnectivityState for updating addrConn's connectivity state.
851 state connectivity.State 922 state connectivity.State
852 down func(error) // the handler called when a connection is down. 923
853 // ready is closed and becomes nil when a new transport is up or failed 924 tearDownErr error // The reason this addrConn is torn down.
854 // due to timeout. 925
855 ready chan struct{} 926 backoffIdx int // Needs to be stateful for resetConnectBackoff.
856 transport transport.ClientTransport 927 resetBackoff chan struct{}
857 928
858 // The reason this addrConn is torn down. 929 channelzID int64 // channelz unique identification number.
859 tearDownErr error 930 czData *channelzData
931 healthCheckEnabled bool
932}
933
934// Note: this requires a lock on ac.mu.
935func (ac *addrConn) updateConnectivityState(s connectivity.State) {
936 if ac.state == s {
937 return
938 }
939
940 updateMsg := fmt.Sprintf("Subchannel Connectivity change to %v", s)
941 grpclog.Infof(updateMsg)
942 ac.state = s
943 if channelz.IsOn() {
944 channelz.AddTraceEvent(ac.channelzID, &channelz.TraceEventDesc{
945 Desc: updateMsg,
946 Severity: channelz.CtINFO,
947 })
948 }
949 ac.cc.handleSubConnStateChange(ac.acbw, s)
860} 950}
861 951
862// adjustParams updates parameters used to create transports upon 952// adjustParams updates parameters used to create transports upon
863// receiving a GoAway. 953// receiving a GoAway.
864func (ac *addrConn) adjustParams(r transport.GoAwayReason) { 954func (ac *addrConn) adjustParams(r transport.GoAwayReason) {
865 switch r { 955 switch r {
866 case transport.TooManyPings: 956 case transport.GoAwayTooManyPings:
867 v := 2 * ac.dopts.copts.KeepaliveParams.Time 957 v := 2 * ac.dopts.copts.KeepaliveParams.Time
868 ac.cc.mu.Lock() 958 ac.cc.mu.Lock()
869 if v > ac.cc.mkp.Time { 959 if v > ac.cc.mkp.Time {
@@ -873,246 +963,359 @@ func (ac *addrConn) adjustParams(r transport.GoAwayReason) {
873 } 963 }
874} 964}
875 965
876// printf records an event in ac's event log, unless ac has been closed. 966func (ac *addrConn) resetTransport() {
877// REQUIRES ac.mu is held. 967 for i := 0; ; i++ {
878func (ac *addrConn) printf(format string, a ...interface{}) { 968 tryNextAddrFromStart := grpcsync.NewEvent()
879 if ac.events != nil {
880 ac.events.Printf(format, a...)
881 }
882}
883 969
884// errorf records an error in ac's event log, unless ac has been closed.
885// REQUIRES ac.mu is held.
886func (ac *addrConn) errorf(format string, a ...interface{}) {
887 if ac.events != nil {
888 ac.events.Errorf(format, a...)
889 }
890}
891
892// resetTransport recreates a transport to the address for ac.
893// For the old transport:
894// - if drain is true, it will be gracefully closed.
895// - otherwise, it will be closed.
896func (ac *addrConn) resetTransport(drain bool) error {
897 ac.mu.Lock()
898 if ac.state == connectivity.Shutdown {
899 ac.mu.Unlock()
900 return errConnClosing
901 }
902 ac.printf("connecting")
903 if ac.down != nil {
904 ac.down(downErrorf(false, true, "%v", errNetworkIO))
905 ac.down = nil
906 }
907 oldState := ac.state
908 ac.state = connectivity.Connecting
909 ac.csEvltr.recordTransition(oldState, ac.state)
910 t := ac.transport
911 ac.transport = nil
912 ac.mu.Unlock()
913 if t != nil && !drain {
914 t.Close()
915 }
916 ac.cc.mu.RLock()
917 ac.dopts.copts.KeepaliveParams = ac.cc.mkp
918 ac.cc.mu.RUnlock()
919 for retries := 0; ; retries++ {
920 ac.mu.Lock() 970 ac.mu.Lock()
921 if ac.state == connectivity.Shutdown { 971 if i > 0 {
922 // ac.tearDown(...) has been invoked. 972 ac.cc.resolveNow(resolver.ResolveNowOption{})
923 ac.mu.Unlock()
924 return errConnClosing
925 } 973 }
974 addrs := ac.addrs
975 backoffFor := ac.dopts.bs.Backoff(ac.backoffIdx)
926 ac.mu.Unlock() 976 ac.mu.Unlock()
927 sleepTime := ac.dopts.bs.backoff(retries)
928 timeout := minConnectTimeout
929 if timeout < sleepTime {
930 timeout = sleepTime
931 }
932 ctx, cancel := context.WithTimeout(ac.ctx, timeout)
933 connectTime := time.Now()
934 sinfo := transport.TargetInfo{
935 Addr: ac.addr.Addr,
936 Metadata: ac.addr.Metadata,
937 }
938 newTransport, err := transport.NewClientTransport(ctx, sinfo, ac.dopts.copts)
939 // Don't call cancel in success path due to a race in Go 1.6:
940 // https://github.com/golang/go/issues/15078.
941 if err != nil {
942 cancel()
943 977
944 if e, ok := err.(transport.ConnectionError); ok && !e.Temporary() { 978 addrLoop:
945 return err 979 for _, addr := range addrs {
980 ac.mu.Lock()
981
982 if ac.state == connectivity.Shutdown {
983 ac.mu.Unlock()
984 return
985 }
986 ac.updateConnectivityState(connectivity.Connecting)
987 ac.transport = nil
988 ac.mu.Unlock()
989
990 // This will be the duration that dial gets to finish.
991 dialDuration := getMinConnectTimeout()
992 if dialDuration < backoffFor {
993 // Give dial more time as we keep failing to connect.
994 dialDuration = backoffFor
946 } 995 }
947 grpclog.Warningf("grpc: addrConn.resetTransport failed to create client transport: %v; Reconnecting to %v", err, ac.addr) 996 connectDeadline := time.Now().Add(dialDuration)
997
948 ac.mu.Lock() 998 ac.mu.Lock()
999 ac.cc.mu.RLock()
1000 ac.dopts.copts.KeepaliveParams = ac.cc.mkp
1001 ac.cc.mu.RUnlock()
1002
949 if ac.state == connectivity.Shutdown { 1003 if ac.state == connectivity.Shutdown {
950 // ac.tearDown(...) has been invoked.
951 ac.mu.Unlock() 1004 ac.mu.Unlock()
952 return errConnClosing 1005 return
953 } 1006 }
954 ac.errorf("transient failure: %v", err) 1007
955 oldState = ac.state 1008 copts := ac.dopts.copts
956 ac.state = connectivity.TransientFailure 1009 if ac.scopts.CredsBundle != nil {
957 ac.csEvltr.recordTransition(oldState, ac.state) 1010 copts.CredsBundle = ac.scopts.CredsBundle
958 if ac.ready != nil {
959 close(ac.ready)
960 ac.ready = nil
961 } 1011 }
1012 hctx, hcancel := context.WithCancel(ac.ctx)
1013 defer hcancel()
962 ac.mu.Unlock() 1014 ac.mu.Unlock()
963 timer := time.NewTimer(sleepTime - time.Since(connectTime)) 1015
964 select { 1016 if channelz.IsOn() {
965 case <-timer.C: 1017 channelz.AddTraceEvent(ac.channelzID, &channelz.TraceEventDesc{
966 case <-ac.ctx.Done(): 1018 Desc: fmt.Sprintf("Subchannel picks a new address %q to connect", addr.Addr),
967 timer.Stop() 1019 Severity: channelz.CtINFO,
968 return ac.ctx.Err() 1020 })
1021 }
1022
1023 reconnect := grpcsync.NewEvent()
1024 prefaceReceived := make(chan struct{})
1025 newTr, err := ac.createTransport(addr, copts, connectDeadline, reconnect, prefaceReceived)
1026 if err == nil {
1027 ac.mu.Lock()
1028 ac.curAddr = addr
1029 ac.transport = newTr
1030 ac.mu.Unlock()
1031
1032 healthCheckConfig := ac.cc.healthCheckConfig()
1033 // LB channel health checking is only enabled when all the four requirements below are met:
1034 // 1. it is not disabled by the user with the WithDisableHealthCheck DialOption,
1035 // 2. the internal.HealthCheckFunc is set by importing the grpc/healthcheck package,
1036 // 3. a service config with non-empty healthCheckConfig field is provided,
1037 // 4. the current load balancer allows it.
1038 healthcheckManagingState := false
1039 if !ac.cc.dopts.disableHealthCheck && healthCheckConfig != nil && ac.scopts.HealthCheckEnabled {
1040 if ac.cc.dopts.healthCheckFunc == nil {
1041 // TODO: add a link to the health check doc in the error message.
1042 grpclog.Error("the client side LB channel health check function has not been set.")
1043 } else {
1044 // TODO(deklerk) refactor to just return transport
1045 go ac.startHealthCheck(hctx, newTr, addr, healthCheckConfig.ServiceName)
1046 healthcheckManagingState = true
1047 }
1048 }
1049 if !healthcheckManagingState {
1050 ac.mu.Lock()
1051 ac.updateConnectivityState(connectivity.Ready)
1052 ac.mu.Unlock()
1053 }
1054 } else {
1055 hcancel()
1056 if err == errConnClosing {
1057 return
1058 }
1059
1060 if tryNextAddrFromStart.HasFired() {
1061 break addrLoop
1062 }
1063 continue
1064 }
1065
1066 ac.mu.Lock()
1067 reqHandshake := ac.dopts.reqHandshake
1068 ac.mu.Unlock()
1069
1070 <-reconnect.Done()
1071 hcancel()
1072
1073 if reqHandshake == envconfig.RequireHandshakeHybrid {
1074 // In RequireHandshakeHybrid mode, we must check to see whether
1075 // server preface has arrived yet to decide whether to start
1076 // reconnecting at the top of the list (server preface received)
1077 // or continue with the next addr in the list as if the
1078 // connection were not successful (server preface not received).
1079 select {
1080 case <-prefaceReceived:
1081 // We received a server preface - huzzah! We consider this
1082 // a success and restart from the top of the addr list.
1083 ac.mu.Lock()
1084 ac.backoffIdx = 0
1085 ac.mu.Unlock()
1086 break addrLoop
1087 default:
1088 // Despite having set state to READY, in hybrid mode we
1089 // consider this a failure and continue connecting at the
1090 // next addr in the list.
1091 ac.mu.Lock()
1092 if ac.state == connectivity.Shutdown {
1093 ac.mu.Unlock()
1094 return
1095 }
1096
1097 ac.updateConnectivityState(connectivity.TransientFailure)
1098 ac.mu.Unlock()
1099
1100 if tryNextAddrFromStart.HasFired() {
1101 break addrLoop
1102 }
1103 }
1104 } else {
1105 // In RequireHandshakeOn mode, we would have already waited for
1106 // the server preface, so we consider this a success and restart
1107 // from the top of the addr list. In RequireHandshakeOff mode,
1108 // we don't care to wait for the server preface before
1109 // considering this a success, so we also restart from the top
1110 // of the addr list.
1111 ac.mu.Lock()
1112 ac.backoffIdx = 0
1113 ac.mu.Unlock()
1114 break addrLoop
969 } 1115 }
970 timer.Stop()
971 continue
972 } 1116 }
1117
1118 // After exhausting all addresses, or after need to reconnect after a
1119 // READY, the addrConn enters TRANSIENT_FAILURE.
973 ac.mu.Lock() 1120 ac.mu.Lock()
974 ac.printf("ready")
975 if ac.state == connectivity.Shutdown { 1121 if ac.state == connectivity.Shutdown {
976 // ac.tearDown(...) has been invoked.
977 ac.mu.Unlock() 1122 ac.mu.Unlock()
978 newTransport.Close() 1123 return
979 return errConnClosing
980 }
981 oldState = ac.state
982 ac.state = connectivity.Ready
983 ac.csEvltr.recordTransition(oldState, ac.state)
984 ac.transport = newTransport
985 if ac.ready != nil {
986 close(ac.ready)
987 ac.ready = nil
988 }
989 if ac.cc.dopts.balancer != nil {
990 ac.down = ac.cc.dopts.balancer.Up(ac.addr)
991 } 1124 }
1125 ac.updateConnectivityState(connectivity.TransientFailure)
1126
1127 // Backoff.
1128 b := ac.resetBackoff
1129 timer := time.NewTimer(backoffFor)
1130 acctx := ac.ctx
992 ac.mu.Unlock() 1131 ac.mu.Unlock()
993 return nil 1132
1133 select {
1134 case <-timer.C:
1135 ac.mu.Lock()
1136 ac.backoffIdx++
1137 ac.mu.Unlock()
1138 case <-b:
1139 timer.Stop()
1140 case <-acctx.Done():
1141 timer.Stop()
1142 return
1143 }
994 } 1144 }
995} 1145}
996 1146
997// Run in a goroutine to track the error in transport and create the 1147// createTransport creates a connection to one of the backends in addrs. It
998// new transport if an error happens. It returns when the channel is closing. 1148// sets ac.transport in the success case, or it returns an error if it was
999func (ac *addrConn) transportMonitor() { 1149// unable to successfully create a transport.
1000 for { 1150//
1151// If waitForHandshake is enabled, it blocks until server preface arrives.
1152func (ac *addrConn) createTransport(addr resolver.Address, copts transport.ConnectOptions, connectDeadline time.Time, reconnect *grpcsync.Event, prefaceReceived chan struct{}) (transport.ClientTransport, error) {
1153 onCloseCalled := make(chan struct{})
1154
1155 target := transport.TargetInfo{
1156 Addr: addr.Addr,
1157 Metadata: addr.Metadata,
1158 Authority: ac.cc.authority,
1159 }
1160
1161 prefaceTimer := time.NewTimer(connectDeadline.Sub(time.Now()))
1162
1163 onGoAway := func(r transport.GoAwayReason) {
1001 ac.mu.Lock() 1164 ac.mu.Lock()
1002 t := ac.transport 1165 ac.adjustParams(r)
1003 ac.mu.Unlock() 1166 ac.mu.Unlock()
1004 select { 1167 reconnect.Fire()
1005 // This is needed to detect the teardown when 1168 }
1006 // the addrConn is idle (i.e., no RPC in flight). 1169
1007 case <-ac.ctx.Done(): 1170 onClose := func() {
1008 select { 1171 close(onCloseCalled)
1009 case <-t.Error(): 1172 prefaceTimer.Stop()
1010 t.Close() 1173 reconnect.Fire()
1011 default: 1174 }
1012 } 1175
1013 return 1176 onPrefaceReceipt := func() {
1014 case <-t.GoAway(): 1177 close(prefaceReceived)
1015 ac.adjustParams(t.GetGoAwayReason()) 1178 prefaceTimer.Stop()
1016 // If GoAway happens without any network I/O error, the underlying transport 1179 }
1017 // will be gracefully closed, and a new transport will be created. 1180
1018 // (The transport will be closed when all the pending RPCs finished or failed.) 1181 connectCtx, cancel := context.WithDeadline(ac.ctx, connectDeadline)
1019 // If GoAway and some network I/O error happen concurrently, the underlying transport 1182 defer cancel()
1020 // will be closed, and a new transport will be created. 1183 if channelz.IsOn() {
1021 var drain bool 1184 copts.ChannelzParentID = ac.channelzID
1185 }
1186
1187 newTr, err := transport.NewClientTransport(connectCtx, ac.cc.ctx, target, copts, onPrefaceReceipt, onGoAway, onClose)
1188
1189 if err == nil {
1190 if ac.dopts.reqHandshake == envconfig.RequireHandshakeOn {
1022 select { 1191 select {
1023 case <-t.Error(): 1192 case <-prefaceTimer.C:
1024 default: 1193 // We didn't get the preface in time.
1025 drain = true 1194 newTr.Close()
1026 } 1195 err = errors.New("timed out waiting for server handshake")
1027 if err := ac.resetTransport(drain); err != nil { 1196 case <-prefaceReceived:
1028 grpclog.Infof("get error from resetTransport %v, transportMonitor returning", err) 1197 // We got the preface - huzzah! things are good.
1029 if err != errConnClosing { 1198 case <-onCloseCalled:
1030 // Keep this ac in cc.conns, to get the reason it's torn down. 1199 // The transport has already closed - noop.
1031 ac.tearDown(err) 1200 return nil, errors.New("connection closed")
1032 }
1033 return
1034 } 1201 }
1035 case <-t.Error(): 1202 } else if ac.dopts.reqHandshake == envconfig.RequireHandshakeHybrid {
1036 select { 1203 go func() {
1037 case <-ac.ctx.Done(): 1204 select {
1038 t.Close() 1205 case <-prefaceTimer.C:
1039 return 1206 // We didn't get the preface in time.
1040 case <-t.GoAway(): 1207 newTr.Close()
1041 ac.adjustParams(t.GetGoAwayReason()) 1208 case <-prefaceReceived:
1042 if err := ac.resetTransport(false); err != nil { 1209 // We got the preface just in the nick of time - huzzah!
1043 grpclog.Infof("get error from resetTransport %v, transportMonitor returning", err) 1210 case <-onCloseCalled:
1044 if err != errConnClosing { 1211 // The transport has already closed - noop.
1045 // Keep this ac in cc.conns, to get the reason it's torn down.
1046 ac.tearDown(err)
1047 }
1048 return
1049 } 1212 }
1050 default: 1213 }()
1051 }
1052 ac.mu.Lock()
1053 if ac.state == connectivity.Shutdown {
1054 // ac has been shutdown.
1055 ac.mu.Unlock()
1056 return
1057 }
1058 oldState := ac.state
1059 ac.state = connectivity.TransientFailure
1060 ac.csEvltr.recordTransition(oldState, ac.state)
1061 ac.mu.Unlock()
1062 if err := ac.resetTransport(false); err != nil {
1063 grpclog.Infof("get error from resetTransport %v, transportMonitor returning", err)
1064 ac.mu.Lock()
1065 ac.printf("transport exiting: %v", err)
1066 ac.mu.Unlock()
1067 grpclog.Warningf("grpc: addrConn.transportMonitor exits due to: %v", err)
1068 if err != errConnClosing {
1069 // Keep this ac in cc.conns, to get the reason it's torn down.
1070 ac.tearDown(err)
1071 }
1072 return
1073 }
1074 } 1214 }
1075 } 1215 }
1076}
1077 1216
1078// wait blocks until i) the new transport is up or ii) ctx is done or iii) ac is closed or 1217 if err != nil {
1079// iv) transport is in connectivity.TransientFailure and there is a balancer/failfast is true. 1218 // newTr is either nil, or closed.
1080func (ac *addrConn) wait(ctx context.Context, hasBalancer, failfast bool) (transport.ClientTransport, error) { 1219 ac.cc.blockingpicker.updateConnectionError(err)
1081 for {
1082 ac.mu.Lock() 1220 ac.mu.Lock()
1083 switch { 1221 if ac.state == connectivity.Shutdown {
1084 case ac.state == connectivity.Shutdown: 1222 // ac.tearDown(...) has been invoked.
1085 if failfast || !hasBalancer {
1086 // RPC is failfast or balancer is nil. This RPC should fail with ac.tearDownErr.
1087 err := ac.tearDownErr
1088 ac.mu.Unlock()
1089 return nil, err
1090 }
1091 ac.mu.Unlock() 1223 ac.mu.Unlock()
1224
1092 return nil, errConnClosing 1225 return nil, errConnClosing
1093 case ac.state == connectivity.Ready: 1226 }
1094 ct := ac.transport 1227 ac.mu.Unlock()
1095 ac.mu.Unlock() 1228 grpclog.Warningf("grpc: addrConn.createTransport failed to connect to %v. Err :%v. Reconnecting...", addr, err)
1096 return ct, nil 1229 return nil, err
1097 case ac.state == connectivity.TransientFailure: 1230 }
1098 if failfast || hasBalancer { 1231
1099 ac.mu.Unlock() 1232 // Now there is a viable transport to be use, so set ac.transport to reflect the new viable transport.
1100 return nil, errConnUnavailable 1233 ac.mu.Lock()
1234 if ac.state == connectivity.Shutdown {
1235 ac.mu.Unlock()
1236 newTr.Close()
1237 return nil, errConnClosing
1238 }
1239 ac.mu.Unlock()
1240
1241 // Now there is a viable transport to be use, so set ac.transport to reflect the new viable transport.
1242 ac.mu.Lock()
1243 if ac.state == connectivity.Shutdown {
1244 ac.mu.Unlock()
1245 newTr.Close()
1246 return nil, errConnClosing
1247 }
1248 ac.mu.Unlock()
1249
1250 return newTr, nil
1251}
1252
1253func (ac *addrConn) startHealthCheck(ctx context.Context, newTr transport.ClientTransport, addr resolver.Address, serviceName string) {
1254 // Set up the health check helper functions
1255 newStream := func() (interface{}, error) {
1256 return ac.newClientStream(ctx, &StreamDesc{ServerStreams: true}, "/grpc.health.v1.Health/Watch", newTr)
1257 }
1258 firstReady := true
1259 reportHealth := func(ok bool) {
1260 ac.mu.Lock()
1261 defer ac.mu.Unlock()
1262 if ac.transport != newTr {
1263 return
1264 }
1265 if ok {
1266 if firstReady {
1267 firstReady = false
1268 ac.curAddr = addr
1101 } 1269 }
1270 ac.updateConnectivityState(connectivity.Ready)
1271 } else {
1272 ac.updateConnectivityState(connectivity.TransientFailure)
1102 } 1273 }
1103 ready := ac.ready 1274 }
1104 if ready == nil { 1275 err := ac.cc.dopts.healthCheckFunc(ctx, newStream, reportHealth, serviceName)
1105 ready = make(chan struct{}) 1276 if err != nil {
1106 ac.ready = ready 1277 if status.Code(err) == codes.Unimplemented {
1278 if channelz.IsOn() {
1279 channelz.AddTraceEvent(ac.channelzID, &channelz.TraceEventDesc{
1280 Desc: "Subchannel health check is unimplemented at server side, thus health check is disabled",
1281 Severity: channelz.CtError,
1282 })
1283 }
1284 grpclog.Error("Subchannel health check is unimplemented at server side, thus health check is disabled")
1285 } else {
1286 grpclog.Errorf("HealthCheckFunc exits with unexpected error %v", err)
1107 } 1287 }
1288 }
1289}
1290
1291func (ac *addrConn) resetConnectBackoff() {
1292 ac.mu.Lock()
1293 close(ac.resetBackoff)
1294 ac.backoffIdx = 0
1295 ac.resetBackoff = make(chan struct{})
1296 ac.mu.Unlock()
1297}
1298
1299// getReadyTransport returns the transport if ac's state is READY.
1300// Otherwise it returns nil, false.
1301// If ac's state is IDLE, it will trigger ac to connect.
1302func (ac *addrConn) getReadyTransport() (transport.ClientTransport, bool) {
1303 ac.mu.Lock()
1304 if ac.state == connectivity.Ready && ac.transport != nil {
1305 t := ac.transport
1108 ac.mu.Unlock() 1306 ac.mu.Unlock()
1109 select { 1307 return t, true
1110 case <-ctx.Done(): 1308 }
1111 return nil, toRPCErr(ctx.Err()) 1309 var idle bool
1112 // Wait until the new transport is ready or failed. 1310 if ac.state == connectivity.Idle {
1113 case <-ready: 1311 idle = true
1114 }
1115 } 1312 }
1313 ac.mu.Unlock()
1314 // Trigger idle ac to connect.
1315 if idle {
1316 ac.connect()
1317 }
1318 return nil, false
1116} 1319}
1117 1320
1118// tearDown starts to tear down the addrConn. 1321// tearDown starts to tear down the addrConn.
@@ -1121,38 +1324,126 @@ func (ac *addrConn) wait(ctx context.Context, hasBalancer, failfast bool) (trans
1121// tight loop. 1324// tight loop.
1122// tearDown doesn't remove ac from ac.cc.conns. 1325// tearDown doesn't remove ac from ac.cc.conns.
1123func (ac *addrConn) tearDown(err error) { 1326func (ac *addrConn) tearDown(err error) {
1124 ac.cancel()
1125
1126 ac.mu.Lock() 1327 ac.mu.Lock()
1127 defer ac.mu.Unlock() 1328 if ac.state == connectivity.Shutdown {
1128 if ac.down != nil { 1329 ac.mu.Unlock()
1129 ac.down(downErrorf(false, false, "%v", err)) 1330 return
1130 ac.down = nil
1131 } 1331 }
1132 if err == errConnDrain && ac.transport != nil { 1332 curTr := ac.transport
1333 ac.transport = nil
1334 // We have to set the state to Shutdown before anything else to prevent races
1335 // between setting the state and logic that waits on context cancelation / etc.
1336 ac.updateConnectivityState(connectivity.Shutdown)
1337 ac.cancel()
1338 ac.tearDownErr = err
1339 ac.curAddr = resolver.Address{}
1340 if err == errConnDrain && curTr != nil {
1133 // GracefulClose(...) may be executed multiple times when 1341 // GracefulClose(...) may be executed multiple times when
1134 // i) receiving multiple GoAway frames from the server; or 1342 // i) receiving multiple GoAway frames from the server; or
1135 // ii) there are concurrent name resolver/Balancer triggered 1343 // ii) there are concurrent name resolver/Balancer triggered
1136 // address removal and GoAway. 1344 // address removal and GoAway.
1137 ac.transport.GracefulClose() 1345 // We have to unlock and re-lock here because GracefulClose => Close => onClose, which requires locking ac.mu.
1346 ac.mu.Unlock()
1347 curTr.GracefulClose()
1348 ac.mu.Lock()
1138 } 1349 }
1139 if ac.state == connectivity.Shutdown { 1350 if channelz.IsOn() {
1140 return 1351 channelz.AddTraceEvent(ac.channelzID, &channelz.TraceEventDesc{
1352 Desc: "Subchannel Deleted",
1353 Severity: channelz.CtINFO,
1354 Parent: &channelz.TraceEventDesc{
1355 Desc: fmt.Sprintf("Subchanel(id:%d) deleted", ac.channelzID),
1356 Severity: channelz.CtINFO,
1357 },
1358 })
1359 // TraceEvent needs to be called before RemoveEntry, as TraceEvent may add trace reference to
1360 // the entity beng deleted, and thus prevent it from being deleted right away.
1361 channelz.RemoveEntry(ac.channelzID)
1141 } 1362 }
1142 oldState := ac.state 1363 ac.mu.Unlock()
1143 ac.state = connectivity.Shutdown 1364}
1144 ac.tearDownErr = err 1365
1145 ac.csEvltr.recordTransition(oldState, ac.state) 1366func (ac *addrConn) getState() connectivity.State {
1146 if ac.events != nil { 1367 ac.mu.Lock()
1147 ac.events.Finish() 1368 defer ac.mu.Unlock()
1148 ac.events = nil 1369 return ac.state
1370}
1371
1372func (ac *addrConn) ChannelzMetric() *channelz.ChannelInternalMetric {
1373 ac.mu.Lock()
1374 addr := ac.curAddr.Addr
1375 ac.mu.Unlock()
1376 return &channelz.ChannelInternalMetric{
1377 State: ac.getState(),
1378 Target: addr,
1379 CallsStarted: atomic.LoadInt64(&ac.czData.callsStarted),
1380 CallsSucceeded: atomic.LoadInt64(&ac.czData.callsSucceeded),
1381 CallsFailed: atomic.LoadInt64(&ac.czData.callsFailed),
1382 LastCallStartedTimestamp: time.Unix(0, atomic.LoadInt64(&ac.czData.lastCallStartedTime)),
1383 }
1384}
1385
1386func (ac *addrConn) incrCallsStarted() {
1387 atomic.AddInt64(&ac.czData.callsStarted, 1)
1388 atomic.StoreInt64(&ac.czData.lastCallStartedTime, time.Now().UnixNano())
1389}
1390
1391func (ac *addrConn) incrCallsSucceeded() {
1392 atomic.AddInt64(&ac.czData.callsSucceeded, 1)
1393}
1394
1395func (ac *addrConn) incrCallsFailed() {
1396 atomic.AddInt64(&ac.czData.callsFailed, 1)
1397}
1398
1399type retryThrottler struct {
1400 max float64
1401 thresh float64
1402 ratio float64
1403
1404 mu sync.Mutex
1405 tokens float64 // TODO(dfawley): replace with atomic and remove lock.
1406}
1407
1408// throttle subtracts a retry token from the pool and returns whether a retry
1409// should be throttled (disallowed) based upon the retry throttling policy in
1410// the service config.
1411func (rt *retryThrottler) throttle() bool {
1412 if rt == nil {
1413 return false
1414 }
1415 rt.mu.Lock()
1416 defer rt.mu.Unlock()
1417 rt.tokens--
1418 if rt.tokens < 0 {
1419 rt.tokens = 0
1149 } 1420 }
1150 if ac.ready != nil { 1421 return rt.tokens <= rt.thresh
1151 close(ac.ready) 1422}
1152 ac.ready = nil 1423
1424func (rt *retryThrottler) successfulRPC() {
1425 if rt == nil {
1426 return
1153 } 1427 }
1154 if ac.transport != nil && err != errConnDrain { 1428 rt.mu.Lock()
1155 ac.transport.Close() 1429 defer rt.mu.Unlock()
1430 rt.tokens += rt.ratio
1431 if rt.tokens > rt.max {
1432 rt.tokens = rt.max
1156 } 1433 }
1157 return
1158} 1434}
1435
1436type channelzChannel struct {
1437 cc *ClientConn
1438}
1439
1440func (c *channelzChannel) ChannelzMetric() *channelz.ChannelInternalMetric {
1441 return c.cc.channelzMetric()
1442}
1443
1444// ErrClientConnTimeout indicates that the ClientConn cannot establish the
1445// underlying connections within the specified timeout.
1446//
1447// Deprecated: This error is never returned by grpc and should not be
1448// referenced by users.
1449var ErrClientConnTimeout = errors.New("grpc: timed out when dialing")
diff --git a/vendor/google.golang.org/grpc/codec.go b/vendor/google.golang.org/grpc/codec.go
index 905b048..1297765 100644
--- a/vendor/google.golang.org/grpc/codec.go
+++ b/vendor/google.golang.org/grpc/codec.go
@@ -19,86 +19,32 @@
19package grpc 19package grpc
20 20
21import ( 21import (
22 "math" 22 "google.golang.org/grpc/encoding"
23 "sync" 23 _ "google.golang.org/grpc/encoding/proto" // to register the Codec for "proto"
24
25 "github.com/golang/protobuf/proto"
26) 24)
27 25
26// baseCodec contains the functionality of both Codec and encoding.Codec, but
27// omits the name/string, which vary between the two and are not needed for
28// anything besides the registry in the encoding package.
29type baseCodec interface {
30 Marshal(v interface{}) ([]byte, error)
31 Unmarshal(data []byte, v interface{}) error
32}
33
34var _ baseCodec = Codec(nil)
35var _ baseCodec = encoding.Codec(nil)
36
28// Codec defines the interface gRPC uses to encode and decode messages. 37// Codec defines the interface gRPC uses to encode and decode messages.
29// Note that implementations of this interface must be thread safe; 38// Note that implementations of this interface must be thread safe;
30// a Codec's methods can be called from concurrent goroutines. 39// a Codec's methods can be called from concurrent goroutines.
40//
41// Deprecated: use encoding.Codec instead.
31type Codec interface { 42type Codec interface {
32 // Marshal returns the wire format of v. 43 // Marshal returns the wire format of v.
33 Marshal(v interface{}) ([]byte, error) 44 Marshal(v interface{}) ([]byte, error)
34 // Unmarshal parses the wire format into v. 45 // Unmarshal parses the wire format into v.
35 Unmarshal(data []byte, v interface{}) error 46 Unmarshal(data []byte, v interface{}) error
36 // String returns the name of the Codec implementation. The returned 47 // String returns the name of the Codec implementation. This is unused by
37 // string will be used as part of content type in transmission. 48 // gRPC.
38 String() string 49 String() string
39} 50}
40
41// protoCodec is a Codec implementation with protobuf. It is the default codec for gRPC.
42type protoCodec struct {
43}
44
45type cachedProtoBuffer struct {
46 lastMarshaledSize uint32
47 proto.Buffer
48}
49
50func capToMaxInt32(val int) uint32 {
51 if val > math.MaxInt32 {
52 return uint32(math.MaxInt32)
53 }
54 return uint32(val)
55}
56
57func (p protoCodec) marshal(v interface{}, cb *cachedProtoBuffer) ([]byte, error) {
58 protoMsg := v.(proto.Message)
59 newSlice := make([]byte, 0, cb.lastMarshaledSize)
60
61 cb.SetBuf(newSlice)
62 cb.Reset()
63 if err := cb.Marshal(protoMsg); err != nil {
64 return nil, err
65 }
66 out := cb.Bytes()
67 cb.lastMarshaledSize = capToMaxInt32(len(out))
68 return out, nil
69}
70
71func (p protoCodec) Marshal(v interface{}) ([]byte, error) {
72 cb := protoBufferPool.Get().(*cachedProtoBuffer)
73 out, err := p.marshal(v, cb)
74
75 // put back buffer and lose the ref to the slice
76 cb.SetBuf(nil)
77 protoBufferPool.Put(cb)
78 return out, err
79}
80
81func (p protoCodec) Unmarshal(data []byte, v interface{}) error {
82 cb := protoBufferPool.Get().(*cachedProtoBuffer)
83 cb.SetBuf(data)
84 v.(proto.Message).Reset()
85 err := cb.Unmarshal(v.(proto.Message))
86 cb.SetBuf(nil)
87 protoBufferPool.Put(cb)
88 return err
89}
90
91func (protoCodec) String() string {
92 return "proto"
93}
94
95var (
96 protoBufferPool = &sync.Pool{
97 New: func() interface{} {
98 return &cachedProtoBuffer{
99 Buffer: proto.Buffer{},
100 lastMarshaledSize: 16,
101 }
102 },
103 }
104)
diff --git a/vendor/google.golang.org/grpc/codes/code_string.go b/vendor/google.golang.org/grpc/codes/code_string.go
index e6762d0..0b206a5 100644
--- a/vendor/google.golang.org/grpc/codes/code_string.go
+++ b/vendor/google.golang.org/grpc/codes/code_string.go
@@ -1,16 +1,62 @@
1// generated by stringer -type=Code; DO NOT EDIT 1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
2 18
3package codes 19package codes
4 20
5import "fmt" 21import "strconv"
6 22
7const _Code_name = "OKCanceledUnknownInvalidArgumentDeadlineExceededNotFoundAlreadyExistsPermissionDeniedResourceExhaustedFailedPreconditionAbortedOutOfRangeUnimplementedInternalUnavailableDataLossUnauthenticated" 23func (c Code) String() string {
8 24 switch c {
9var _Code_index = [...]uint8{0, 2, 10, 17, 32, 48, 56, 69, 85, 102, 120, 127, 137, 150, 158, 169, 177, 192} 25 case OK:
10 26 return "OK"
11func (i Code) String() string { 27 case Canceled:
12 if i+1 >= Code(len(_Code_index)) { 28 return "Canceled"
13 return fmt.Sprintf("Code(%d)", i) 29 case Unknown:
30 return "Unknown"
31 case InvalidArgument:
32 return "InvalidArgument"
33 case DeadlineExceeded:
34 return "DeadlineExceeded"
35 case NotFound:
36 return "NotFound"
37 case AlreadyExists:
38 return "AlreadyExists"
39 case PermissionDenied:
40 return "PermissionDenied"
41 case ResourceExhausted:
42 return "ResourceExhausted"
43 case FailedPrecondition:
44 return "FailedPrecondition"
45 case Aborted:
46 return "Aborted"
47 case OutOfRange:
48 return "OutOfRange"
49 case Unimplemented:
50 return "Unimplemented"
51 case Internal:
52 return "Internal"
53 case Unavailable:
54 return "Unavailable"
55 case DataLoss:
56 return "DataLoss"
57 case Unauthenticated:
58 return "Unauthenticated"
59 default:
60 return "Code(" + strconv.FormatInt(int64(c), 10) + ")"
14 } 61 }
15 return _Code_name[_Code_index[i]:_Code_index[i+1]]
16} 62}
diff --git a/vendor/google.golang.org/grpc/codes/codes.go b/vendor/google.golang.org/grpc/codes/codes.go
index 21e7733..d9b9d57 100644
--- a/vendor/google.golang.org/grpc/codes/codes.go
+++ b/vendor/google.golang.org/grpc/codes/codes.go
@@ -20,11 +20,14 @@
20// consistent across various languages. 20// consistent across various languages.
21package codes // import "google.golang.org/grpc/codes" 21package codes // import "google.golang.org/grpc/codes"
22 22
23import (
24 "fmt"
25 "strconv"
26)
27
23// A Code is an unsigned 32-bit error code as defined in the gRPC spec. 28// A Code is an unsigned 32-bit error code as defined in the gRPC spec.
24type Code uint32 29type Code uint32
25 30
26//go:generate stringer -type=Code
27
28const ( 31const (
29 // OK is returned on success. 32 // OK is returned on success.
30 OK Code = 0 33 OK Code = 0
@@ -32,9 +35,9 @@ const (
32 // Canceled indicates the operation was canceled (typically by the caller). 35 // Canceled indicates the operation was canceled (typically by the caller).
33 Canceled Code = 1 36 Canceled Code = 1
34 37
35 // Unknown error. An example of where this error may be returned is 38 // Unknown error. An example of where this error may be returned is
36 // if a Status value received from another address space belongs to 39 // if a Status value received from another address space belongs to
37 // an error-space that is not known in this address space. Also 40 // an error-space that is not known in this address space. Also
38 // errors raised by APIs that do not return enough error information 41 // errors raised by APIs that do not return enough error information
39 // may be converted to this error. 42 // may be converted to this error.
40 Unknown Code = 2 43 Unknown Code = 2
@@ -63,15 +66,11 @@ const (
63 // PermissionDenied indicates the caller does not have permission to 66 // PermissionDenied indicates the caller does not have permission to
64 // execute the specified operation. It must not be used for rejections 67 // execute the specified operation. It must not be used for rejections
65 // caused by exhausting some resource (use ResourceExhausted 68 // caused by exhausting some resource (use ResourceExhausted
66 // instead for those errors). It must not be 69 // instead for those errors). It must not be
67 // used if the caller cannot be identified (use Unauthenticated 70 // used if the caller cannot be identified (use Unauthenticated
68 // instead for those errors). 71 // instead for those errors).
69 PermissionDenied Code = 7 72 PermissionDenied Code = 7
70 73
71 // Unauthenticated indicates the request does not have valid
72 // authentication credentials for the operation.
73 Unauthenticated Code = 16
74
75 // ResourceExhausted indicates some resource has been exhausted, perhaps 74 // ResourceExhausted indicates some resource has been exhausted, perhaps
76 // a per-user quota, or perhaps the entire file system is out of space. 75 // a per-user quota, or perhaps the entire file system is out of space.
77 ResourceExhausted Code = 8 76 ResourceExhausted Code = 8
@@ -87,7 +86,7 @@ const (
87 // (b) Use Aborted if the client should retry at a higher-level 86 // (b) Use Aborted if the client should retry at a higher-level
88 // (e.g., restarting a read-modify-write sequence). 87 // (e.g., restarting a read-modify-write sequence).
89 // (c) Use FailedPrecondition if the client should not retry until 88 // (c) Use FailedPrecondition if the client should not retry until
90 // the system state has been explicitly fixed. E.g., if an "rmdir" 89 // the system state has been explicitly fixed. E.g., if an "rmdir"
91 // fails because the directory is non-empty, FailedPrecondition 90 // fails because the directory is non-empty, FailedPrecondition
92 // should be returned since the client should not retry unless 91 // should be returned since the client should not retry unless
93 // they have first fixed up the directory by deleting files from it. 92 // they have first fixed up the directory by deleting files from it.
@@ -116,7 +115,7 @@ const (
116 // file size. 115 // file size.
117 // 116 //
118 // There is a fair bit of overlap between FailedPrecondition and 117 // There is a fair bit of overlap between FailedPrecondition and
119 // OutOfRange. We recommend using OutOfRange (the more specific 118 // OutOfRange. We recommend using OutOfRange (the more specific
120 // error) when it applies so that callers who are iterating through 119 // error) when it applies so that callers who are iterating through
121 // a space can easily look for an OutOfRange error to detect when 120 // a space can easily look for an OutOfRange error to detect when
122 // they are done. 121 // they are done.
@@ -126,8 +125,8 @@ const (
126 // supported/enabled in this service. 125 // supported/enabled in this service.
127 Unimplemented Code = 12 126 Unimplemented Code = 12
128 127
129 // Internal errors. Means some invariants expected by underlying 128 // Internal errors. Means some invariants expected by underlying
130 // system has been broken. If you see one of these errors, 129 // system has been broken. If you see one of these errors,
131 // something is very broken. 130 // something is very broken.
132 Internal Code = 13 131 Internal Code = 13
133 132
@@ -141,4 +140,58 @@ const (
141 140
142 // DataLoss indicates unrecoverable data loss or corruption. 141 // DataLoss indicates unrecoverable data loss or corruption.
143 DataLoss Code = 15 142 DataLoss Code = 15
143
144 // Unauthenticated indicates the request does not have valid
145 // authentication credentials for the operation.
146 Unauthenticated Code = 16
147
148 _maxCode = 17
144) 149)
150
151var strToCode = map[string]Code{
152 `"OK"`: OK,
153 `"CANCELLED"`:/* [sic] */ Canceled,
154 `"UNKNOWN"`: Unknown,
155 `"INVALID_ARGUMENT"`: InvalidArgument,
156 `"DEADLINE_EXCEEDED"`: DeadlineExceeded,
157 `"NOT_FOUND"`: NotFound,
158 `"ALREADY_EXISTS"`: AlreadyExists,
159 `"PERMISSION_DENIED"`: PermissionDenied,
160 `"RESOURCE_EXHAUSTED"`: ResourceExhausted,
161 `"FAILED_PRECONDITION"`: FailedPrecondition,
162 `"ABORTED"`: Aborted,
163 `"OUT_OF_RANGE"`: OutOfRange,
164 `"UNIMPLEMENTED"`: Unimplemented,
165 `"INTERNAL"`: Internal,
166 `"UNAVAILABLE"`: Unavailable,
167 `"DATA_LOSS"`: DataLoss,
168 `"UNAUTHENTICATED"`: Unauthenticated,
169}
170
171// UnmarshalJSON unmarshals b into the Code.
172func (c *Code) UnmarshalJSON(b []byte) error {
173 // From json.Unmarshaler: By convention, to approximate the behavior of
174 // Unmarshal itself, Unmarshalers implement UnmarshalJSON([]byte("null")) as
175 // a no-op.
176 if string(b) == "null" {
177 return nil
178 }
179 if c == nil {
180 return fmt.Errorf("nil receiver passed to UnmarshalJSON")
181 }
182
183 if ci, err := strconv.ParseUint(string(b), 10, 32); err == nil {
184 if ci >= _maxCode {
185 return fmt.Errorf("invalid code: %q", ci)
186 }
187
188 *c = Code(ci)
189 return nil
190 }
191
192 if jc, ok := strToCode[string(b)]; ok {
193 *c = jc
194 return nil
195 }
196 return fmt.Errorf("invalid code: %q", string(b))
197}
diff --git a/vendor/google.golang.org/grpc/connectivity/connectivity.go b/vendor/google.golang.org/grpc/connectivity/connectivity.go
index 568ef5d..b1d7dbc 100644
--- a/vendor/google.golang.org/grpc/connectivity/connectivity.go
+++ b/vendor/google.golang.org/grpc/connectivity/connectivity.go
@@ -22,7 +22,8 @@
22package connectivity 22package connectivity
23 23
24import ( 24import (
25 "golang.org/x/net/context" 25 "context"
26
26 "google.golang.org/grpc/grpclog" 27 "google.golang.org/grpc/grpclog"
27) 28)
28 29
diff --git a/vendor/google.golang.org/grpc/coverage.sh b/vendor/google.golang.org/grpc/coverage.sh
deleted file mode 100644
index b85f918..0000000
--- a/vendor/google.golang.org/grpc/coverage.sh
+++ /dev/null
@@ -1,48 +0,0 @@
1#!/usr/bin/env bash
2
3
4set -e
5
6workdir=.cover
7profile="$workdir/cover.out"
8mode=set
9end2endtest="google.golang.org/grpc/test"
10
11generate_cover_data() {
12 rm -rf "$workdir"
13 mkdir "$workdir"
14
15 for pkg in "$@"; do
16 if [ $pkg == "google.golang.org/grpc" -o $pkg == "google.golang.org/grpc/transport" -o $pkg == "google.golang.org/grpc/metadata" -o $pkg == "google.golang.org/grpc/credentials" ]
17 then
18 f="$workdir/$(echo $pkg | tr / -)"
19 go test -covermode="$mode" -coverprofile="$f.cover" "$pkg"
20 go test -covermode="$mode" -coverpkg "$pkg" -coverprofile="$f.e2e.cover" "$end2endtest"
21 fi
22 done
23
24 echo "mode: $mode" >"$profile"
25 grep -h -v "^mode:" "$workdir"/*.cover >>"$profile"
26}
27
28show_cover_report() {
29 go tool cover -${1}="$profile"
30}
31
32push_to_coveralls() {
33 goveralls -coverprofile="$profile"
34}
35
36generate_cover_data $(go list ./...)
37show_cover_report func
38case "$1" in
39"")
40 ;;
41--html)
42 show_cover_report html ;;
43--coveralls)
44 push_to_coveralls ;;
45*)
46 echo >&2 "error: invalid option: $1" ;;
47esac
48rm -rf "$workdir"
diff --git a/vendor/google.golang.org/grpc/credentials/credentials.go b/vendor/google.golang.org/grpc/credentials/credentials.go
index 2475fe8..a851560 100644
--- a/vendor/google.golang.org/grpc/credentials/credentials.go
+++ b/vendor/google.golang.org/grpc/credentials/credentials.go
@@ -23,6 +23,7 @@
23package credentials // import "google.golang.org/grpc/credentials" 23package credentials // import "google.golang.org/grpc/credentials"
24 24
25import ( 25import (
26 "context"
26 "crypto/tls" 27 "crypto/tls"
27 "crypto/x509" 28 "crypto/x509"
28 "errors" 29 "errors"
@@ -31,13 +32,12 @@ import (
31 "net" 32 "net"
32 "strings" 33 "strings"
33 34
34 "golang.org/x/net/context" 35 "github.com/golang/protobuf/proto"
36 "google.golang.org/grpc/credentials/internal"
35) 37)
36 38
37var ( 39// alpnProtoStr are the specified application level protocols for gRPC.
38 // alpnProtoStr are the specified application level protocols for gRPC. 40var alpnProtoStr = []string{"h2"}
39 alpnProtoStr = []string{"h2"}
40)
41 41
42// PerRPCCredentials defines the common interface for the credentials which need to 42// PerRPCCredentials defines the common interface for the credentials which need to
43// attach security information to every RPC (e.g., oauth2). 43// attach security information to every RPC (e.g., oauth2).
@@ -45,8 +45,9 @@ type PerRPCCredentials interface {
45 // GetRequestMetadata gets the current request metadata, refreshing 45 // GetRequestMetadata gets the current request metadata, refreshing
46 // tokens if required. This should be called by the transport layer on 46 // tokens if required. This should be called by the transport layer on
47 // each request, and the data should be populated in headers or other 47 // each request, and the data should be populated in headers or other
48 // context. uri is the URI of the entry point for the request. When 48 // context. If a status code is returned, it will be used as the status
49 // supported by the underlying implementation, ctx can be used for 49 // for the RPC. uri is the URI of the entry point for the request.
50 // When supported by the underlying implementation, ctx can be used for
50 // timeout and cancellation. 51 // timeout and cancellation.
51 // TODO(zhaoq): Define the set of the qualified keys instead of leaving 52 // TODO(zhaoq): Define the set of the qualified keys instead of leaving
52 // it as an arbitrary string. 53 // it as an arbitrary string.
@@ -74,11 +75,9 @@ type AuthInfo interface {
74 AuthType() string 75 AuthType() string
75} 76}
76 77
77var ( 78// ErrConnDispatched indicates that rawConn has been dispatched out of gRPC
78 // ErrConnDispatched indicates that rawConn has been dispatched out of gRPC 79// and the caller should not close rawConn.
79 // and the caller should not close rawConn. 80var ErrConnDispatched = errors.New("credentials: rawConn is dispatched out of gRPC")
80 ErrConnDispatched = errors.New("credentials: rawConn is dispatched out of gRPC")
81)
82 81
83// TransportCredentials defines the common interface for all the live gRPC wire 82// TransportCredentials defines the common interface for all the live gRPC wire
84// protocols and supported transport security protocols (e.g., TLS, SSL). 83// protocols and supported transport security protocols (e.g., TLS, SSL).
@@ -91,10 +90,14 @@ type TransportCredentials interface {
91 // (io.EOF, context.DeadlineExceeded or err.Temporary() == true). 90 // (io.EOF, context.DeadlineExceeded or err.Temporary() == true).
92 // If the returned error is a wrapper error, implementations should make sure that 91 // If the returned error is a wrapper error, implementations should make sure that
93 // the error implements Temporary() to have the correct retry behaviors. 92 // the error implements Temporary() to have the correct retry behaviors.
93 //
94 // If the returned net.Conn is closed, it MUST close the net.Conn provided.
94 ClientHandshake(context.Context, string, net.Conn) (net.Conn, AuthInfo, error) 95 ClientHandshake(context.Context, string, net.Conn) (net.Conn, AuthInfo, error)
95 // ServerHandshake does the authentication handshake for servers. It returns 96 // ServerHandshake does the authentication handshake for servers. It returns
96 // the authenticated connection and the corresponding auth information about 97 // the authenticated connection and the corresponding auth information about
97 // the connection. 98 // the connection.
99 //
100 // If the returned net.Conn is closed, it MUST close the net.Conn provided.
98 ServerHandshake(net.Conn) (net.Conn, AuthInfo, error) 101 ServerHandshake(net.Conn) (net.Conn, AuthInfo, error)
99 // Info provides the ProtocolInfo of this TransportCredentials. 102 // Info provides the ProtocolInfo of this TransportCredentials.
100 Info() ProtocolInfo 103 Info() ProtocolInfo
@@ -106,6 +109,25 @@ type TransportCredentials interface {
106 OverrideServerName(string) error 109 OverrideServerName(string) error
107} 110}
108 111
112// Bundle is a combination of TransportCredentials and PerRPCCredentials.
113//
114// It also contains a mode switching method, so it can be used as a combination
115// of different credential policies.
116//
117// Bundle cannot be used together with individual TransportCredentials.
118// PerRPCCredentials from Bundle will be appended to other PerRPCCredentials.
119//
120// This API is experimental.
121type Bundle interface {
122 TransportCredentials() TransportCredentials
123 PerRPCCredentials() PerRPCCredentials
124 // NewWithMode should make a copy of Bundle, and switch mode. Modifying the
125 // existing Bundle may cause races.
126 //
127 // NewWithMode returns nil if the requested mode is not supported.
128 NewWithMode(mode string) (Bundle, error)
129}
130
109// TLSInfo contains the auth information for a TLS authenticated connection. 131// TLSInfo contains the auth information for a TLS authenticated connection.
110// It implements the AuthInfo interface. 132// It implements the AuthInfo interface.
111type TLSInfo struct { 133type TLSInfo struct {
@@ -117,6 +139,18 @@ func (t TLSInfo) AuthType() string {
117 return "tls" 139 return "tls"
118} 140}
119 141
142// GetSecurityValue returns security info requested by channelz.
143func (t TLSInfo) GetSecurityValue() ChannelzSecurityValue {
144 v := &TLSChannelzSecurityValue{
145 StandardName: cipherSuiteLookup[t.State.CipherSuite],
146 }
147 // Currently there's no way to get LocalCertificate info from tls package.
148 if len(t.State.PeerCertificates) > 0 {
149 v.RemoteCertificate = t.State.PeerCertificates[0].Raw
150 }
151 return v
152}
153
120// tlsCreds is the credentials required for authenticating a connection using TLS. 154// tlsCreds is the credentials required for authenticating a connection using TLS.
121type tlsCreds struct { 155type tlsCreds struct {
122 // TLS configuration 156 // TLS configuration
@@ -131,15 +165,15 @@ func (c tlsCreds) Info() ProtocolInfo {
131 } 165 }
132} 166}
133 167
134func (c *tlsCreds) ClientHandshake(ctx context.Context, addr string, rawConn net.Conn) (_ net.Conn, _ AuthInfo, err error) { 168func (c *tlsCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (_ net.Conn, _ AuthInfo, err error) {
135 // use local cfg to avoid clobbering ServerName if using multiple endpoints 169 // use local cfg to avoid clobbering ServerName if using multiple endpoints
136 cfg := cloneTLSConfig(c.config) 170 cfg := cloneTLSConfig(c.config)
137 if cfg.ServerName == "" { 171 if cfg.ServerName == "" {
138 colonPos := strings.LastIndex(addr, ":") 172 colonPos := strings.LastIndex(authority, ":")
139 if colonPos == -1 { 173 if colonPos == -1 {
140 colonPos = len(addr) 174 colonPos = len(authority)
141 } 175 }
142 cfg.ServerName = addr[:colonPos] 176 cfg.ServerName = authority[:colonPos]
143 } 177 }
144 conn := tls.Client(rawConn, cfg) 178 conn := tls.Client(rawConn, cfg)
145 errChannel := make(chan error, 1) 179 errChannel := make(chan error, 1)
@@ -154,7 +188,7 @@ func (c *tlsCreds) ClientHandshake(ctx context.Context, addr string, rawConn net
154 case <-ctx.Done(): 188 case <-ctx.Done():
155 return nil, nil, ctx.Err() 189 return nil, nil, ctx.Err()
156 } 190 }
157 return conn, TLSInfo{conn.ConnectionState()}, nil 191 return internal.WrapSyscallConn(rawConn, conn), TLSInfo{conn.ConnectionState()}, nil
158} 192}
159 193
160func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) { 194func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) {
@@ -162,7 +196,7 @@ func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error)
162 if err := conn.Handshake(); err != nil { 196 if err := conn.Handshake(); err != nil {
163 return nil, nil, err 197 return nil, nil, err
164 } 198 }
165 return conn, TLSInfo{conn.ConnectionState()}, nil 199 return internal.WrapSyscallConn(rawConn, conn), TLSInfo{conn.ConnectionState()}, nil
166} 200}
167 201
168func (c *tlsCreds) Clone() TransportCredentials { 202func (c *tlsCreds) Clone() TransportCredentials {
@@ -217,3 +251,78 @@ func NewServerTLSFromFile(certFile, keyFile string) (TransportCredentials, error
217 } 251 }
218 return NewTLS(&tls.Config{Certificates: []tls.Certificate{cert}}), nil 252 return NewTLS(&tls.Config{Certificates: []tls.Certificate{cert}}), nil
219} 253}
254
255// ChannelzSecurityInfo defines the interface that security protocols should implement
256// in order to provide security info to channelz.
257type ChannelzSecurityInfo interface {
258 GetSecurityValue() ChannelzSecurityValue
259}
260
261// ChannelzSecurityValue defines the interface that GetSecurityValue() return value
262// should satisfy. This interface should only be satisfied by *TLSChannelzSecurityValue
263// and *OtherChannelzSecurityValue.
264type ChannelzSecurityValue interface {
265 isChannelzSecurityValue()
266}
267
268// TLSChannelzSecurityValue defines the struct that TLS protocol should return
269// from GetSecurityValue(), containing security info like cipher and certificate used.
270type TLSChannelzSecurityValue struct {
271 StandardName string
272 LocalCertificate []byte
273 RemoteCertificate []byte
274}
275
276func (*TLSChannelzSecurityValue) isChannelzSecurityValue() {}
277
278// OtherChannelzSecurityValue defines the struct that non-TLS protocol should return
279// from GetSecurityValue(), which contains protocol specific security info. Note
280// the Value field will be sent to users of channelz requesting channel info, and
281// thus sensitive info should better be avoided.
282type OtherChannelzSecurityValue struct {
283 Name string
284 Value proto.Message
285}
286
287func (*OtherChannelzSecurityValue) isChannelzSecurityValue() {}
288
289var cipherSuiteLookup = map[uint16]string{
290 tls.TLS_RSA_WITH_RC4_128_SHA: "TLS_RSA_WITH_RC4_128_SHA",
291 tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA: "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
292 tls.TLS_RSA_WITH_AES_128_CBC_SHA: "TLS_RSA_WITH_AES_128_CBC_SHA",
293 tls.TLS_RSA_WITH_AES_256_CBC_SHA: "TLS_RSA_WITH_AES_256_CBC_SHA",
294 tls.TLS_RSA_WITH_AES_128_GCM_SHA256: "TLS_RSA_WITH_AES_128_GCM_SHA256",
295 tls.TLS_RSA_WITH_AES_256_GCM_SHA384: "TLS_RSA_WITH_AES_256_GCM_SHA384",
296 tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
297 tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
298 tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
299 tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA: "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
300 tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
301 tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
302 tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
303 tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
304 tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
305 tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
306 tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
307 tls.TLS_FALLBACK_SCSV: "TLS_FALLBACK_SCSV",
308 tls.TLS_RSA_WITH_AES_128_CBC_SHA256: "TLS_RSA_WITH_AES_128_CBC_SHA256",
309 tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
310 tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
311 tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
312 tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
313}
314
315// cloneTLSConfig returns a shallow clone of the exported
316// fields of cfg, ignoring the unexported sync.Once, which
317// contains a mutex and must not be copied.
318//
319// If cfg is nil, a new zero tls.Config is returned.
320//
321// TODO: inline this function if possible.
322func cloneTLSConfig(cfg *tls.Config) *tls.Config {
323 if cfg == nil {
324 return &tls.Config{}
325 }
326
327 return cfg.Clone()
328}
diff --git a/vendor/google.golang.org/grpc/credentials/credentials_util_go17.go b/vendor/google.golang.org/grpc/credentials/credentials_util_go17.go
deleted file mode 100644
index 60409aa..0000000
--- a/vendor/google.golang.org/grpc/credentials/credentials_util_go17.go
+++ /dev/null
@@ -1,60 +0,0 @@
1// +build go1.7
2// +build !go1.8
3
4/*
5 *
6 * Copyright 2016 gRPC authors.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 */
21
22package credentials
23
24import (
25 "crypto/tls"
26)
27
28// cloneTLSConfig returns a shallow clone of the exported
29// fields of cfg, ignoring the unexported sync.Once, which
30// contains a mutex and must not be copied.
31//
32// If cfg is nil, a new zero tls.Config is returned.
33func cloneTLSConfig(cfg *tls.Config) *tls.Config {
34 if cfg == nil {
35 return &tls.Config{}
36 }
37 return &tls.Config{
38 Rand: cfg.Rand,
39 Time: cfg.Time,
40 Certificates: cfg.Certificates,
41 NameToCertificate: cfg.NameToCertificate,
42 GetCertificate: cfg.GetCertificate,
43 RootCAs: cfg.RootCAs,
44 NextProtos: cfg.NextProtos,
45 ServerName: cfg.ServerName,
46 ClientAuth: cfg.ClientAuth,
47 ClientCAs: cfg.ClientCAs,
48 InsecureSkipVerify: cfg.InsecureSkipVerify,
49 CipherSuites: cfg.CipherSuites,
50 PreferServerCipherSuites: cfg.PreferServerCipherSuites,
51 SessionTicketsDisabled: cfg.SessionTicketsDisabled,
52 SessionTicketKey: cfg.SessionTicketKey,
53 ClientSessionCache: cfg.ClientSessionCache,
54 MinVersion: cfg.MinVersion,
55 MaxVersion: cfg.MaxVersion,
56 CurvePreferences: cfg.CurvePreferences,
57 DynamicRecordSizingDisabled: cfg.DynamicRecordSizingDisabled,
58 Renegotiation: cfg.Renegotiation,
59 }
60}
diff --git a/vendor/google.golang.org/grpc/credentials/credentials_util_pre_go17.go b/vendor/google.golang.org/grpc/credentials/credentials_util_pre_go17.go
deleted file mode 100644
index d6bbcc9..0000000
--- a/vendor/google.golang.org/grpc/credentials/credentials_util_pre_go17.go
+++ /dev/null
@@ -1,57 +0,0 @@
1// +build !go1.7
2
3/*
4 *
5 * Copyright 2016 gRPC authors.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */
20
21package credentials
22
23import (
24 "crypto/tls"
25)
26
27// cloneTLSConfig returns a shallow clone of the exported
28// fields of cfg, ignoring the unexported sync.Once, which
29// contains a mutex and must not be copied.
30//
31// If cfg is nil, a new zero tls.Config is returned.
32func cloneTLSConfig(cfg *tls.Config) *tls.Config {
33 if cfg == nil {
34 return &tls.Config{}
35 }
36 return &tls.Config{
37 Rand: cfg.Rand,
38 Time: cfg.Time,
39 Certificates: cfg.Certificates,
40 NameToCertificate: cfg.NameToCertificate,
41 GetCertificate: cfg.GetCertificate,
42 RootCAs: cfg.RootCAs,
43 NextProtos: cfg.NextProtos,
44 ServerName: cfg.ServerName,
45 ClientAuth: cfg.ClientAuth,
46 ClientCAs: cfg.ClientCAs,
47 InsecureSkipVerify: cfg.InsecureSkipVerify,
48 CipherSuites: cfg.CipherSuites,
49 PreferServerCipherSuites: cfg.PreferServerCipherSuites,
50 SessionTicketsDisabled: cfg.SessionTicketsDisabled,
51 SessionTicketKey: cfg.SessionTicketKey,
52 ClientSessionCache: cfg.ClientSessionCache,
53 MinVersion: cfg.MinVersion,
54 MaxVersion: cfg.MaxVersion,
55 CurvePreferences: cfg.CurvePreferences,
56 }
57}
diff --git a/vendor/google.golang.org/grpc/credentials/internal/syscallconn.go b/vendor/google.golang.org/grpc/credentials/internal/syscallconn.go
new file mode 100644
index 0000000..2f4472b
--- /dev/null
+++ b/vendor/google.golang.org/grpc/credentials/internal/syscallconn.go
@@ -0,0 +1,61 @@
1// +build !appengine
2
3/*
4 *
5 * Copyright 2018 gRPC authors.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */
20
21// Package internal contains credentials-internal code.
22package internal
23
24import (
25 "net"
26 "syscall"
27)
28
29type sysConn = syscall.Conn
30
31// syscallConn keeps reference of rawConn to support syscall.Conn for channelz.
32// SyscallConn() (the method in interface syscall.Conn) is explicitly
33// implemented on this type,
34//
35// Interface syscall.Conn is implemented by most net.Conn implementations (e.g.
36// TCPConn, UnixConn), but is not part of net.Conn interface. So wrapper conns
37// that embed net.Conn don't implement syscall.Conn. (Side note: tls.Conn
38// doesn't embed net.Conn, so even if syscall.Conn is part of net.Conn, it won't
39// help here).
40type syscallConn struct {
41 net.Conn
42 // sysConn is a type alias of syscall.Conn. It's necessary because the name
43 // `Conn` collides with `net.Conn`.
44 sysConn
45}
46
47// WrapSyscallConn tries to wrap rawConn and newConn into a net.Conn that
48// implements syscall.Conn. rawConn will be used to support syscall, and newConn
49// will be used for read/write.
50//
51// This function returns newConn if rawConn doesn't implement syscall.Conn.
52func WrapSyscallConn(rawConn, newConn net.Conn) net.Conn {
53 sysConn, ok := rawConn.(syscall.Conn)
54 if !ok {
55 return newConn
56 }
57 return &syscallConn{
58 Conn: newConn,
59 sysConn: sysConn,
60 }
61}
diff --git a/vendor/google.golang.org/grpc/naming/go17.go b/vendor/google.golang.org/grpc/credentials/internal/syscallconn_appengine.go
index a537b08..d4346e9 100644
--- a/vendor/google.golang.org/grpc/naming/go17.go
+++ b/vendor/google.golang.org/grpc/credentials/internal/syscallconn_appengine.go
@@ -1,8 +1,8 @@
1// +build go1.6, !go1.8 1// +build appengine
2 2
3/* 3/*
4 * 4 *
5 * Copyright 2017 gRPC authors. 5 * Copyright 2018 gRPC authors.
6 * 6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License. 8 * you may not use this file except in compliance with the License.
@@ -18,17 +18,13 @@
18 * 18 *
19 */ 19 */
20 20
21package naming 21package internal
22 22
23import ( 23import (
24 "net" 24 "net"
25
26 "golang.org/x/net/context"
27) 25)
28 26
29var ( 27// WrapSyscallConn returns newConn on appengine.
30 lookupHost = func(ctx context.Context, host string) ([]string, error) { return net.LookupHost(host) } 28func WrapSyscallConn(rawConn, newConn net.Conn) net.Conn {
31 lookupSRV = func(ctx context.Context, service, proto, name string) (string, []*net.SRV, error) { 29 return newConn
32 return net.LookupSRV(service, proto, name) 30}
33 }
34)
diff --git a/vendor/google.golang.org/grpc/dialoptions.go b/vendor/google.golang.org/grpc/dialoptions.go
new file mode 100644
index 0000000..f286462
--- /dev/null
+++ b/vendor/google.golang.org/grpc/dialoptions.go
@@ -0,0 +1,492 @@
1/*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package grpc
20
21import (
22 "context"
23 "fmt"
24 "net"
25 "time"
26
27 "google.golang.org/grpc/balancer"
28 "google.golang.org/grpc/credentials"
29 "google.golang.org/grpc/internal"
30 "google.golang.org/grpc/internal/backoff"
31 "google.golang.org/grpc/internal/envconfig"
32 "google.golang.org/grpc/internal/transport"
33 "google.golang.org/grpc/keepalive"
34 "google.golang.org/grpc/resolver"
35 "google.golang.org/grpc/stats"
36)
37
38// dialOptions configure a Dial call. dialOptions are set by the DialOption
39// values passed to Dial.
40type dialOptions struct {
41 unaryInt UnaryClientInterceptor
42 streamInt StreamClientInterceptor
43 cp Compressor
44 dc Decompressor
45 bs backoff.Strategy
46 block bool
47 insecure bool
48 timeout time.Duration
49 scChan <-chan ServiceConfig
50 authority string
51 copts transport.ConnectOptions
52 callOptions []CallOption
53 // This is used by v1 balancer dial option WithBalancer to support v1
54 // balancer, and also by WithBalancerName dial option.
55 balancerBuilder balancer.Builder
56 // This is to support grpclb.
57 resolverBuilder resolver.Builder
58 reqHandshake envconfig.RequireHandshakeSetting
59 channelzParentID int64
60 disableServiceConfig bool
61 disableRetry bool
62 disableHealthCheck bool
63 healthCheckFunc internal.HealthChecker
64}
65
66// DialOption configures how we set up the connection.
67type DialOption interface {
68 apply(*dialOptions)
69}
70
71// EmptyDialOption does not alter the dial configuration. It can be embedded in
72// another structure to build custom dial options.
73//
74// This API is EXPERIMENTAL.
75type EmptyDialOption struct{}
76
77func (EmptyDialOption) apply(*dialOptions) {}
78
79// funcDialOption wraps a function that modifies dialOptions into an
80// implementation of the DialOption interface.
81type funcDialOption struct {
82 f func(*dialOptions)
83}
84
85func (fdo *funcDialOption) apply(do *dialOptions) {
86 fdo.f(do)
87}
88
89func newFuncDialOption(f func(*dialOptions)) *funcDialOption {
90 return &funcDialOption{
91 f: f,
92 }
93}
94
95// WithWaitForHandshake blocks until the initial settings frame is received from
96// the server before assigning RPCs to the connection.
97//
98// Deprecated: this is the default behavior, and this option will be removed
99// after the 1.18 release.
100func WithWaitForHandshake() DialOption {
101 return newFuncDialOption(func(o *dialOptions) {
102 o.reqHandshake = envconfig.RequireHandshakeOn
103 })
104}
105
106// WithWriteBufferSize determines how much data can be batched before doing a
107// write on the wire. The corresponding memory allocation for this buffer will
108// be twice the size to keep syscalls low. The default value for this buffer is
109// 32KB.
110//
111// Zero will disable the write buffer such that each write will be on underlying
112// connection. Note: A Send call may not directly translate to a write.
113func WithWriteBufferSize(s int) DialOption {
114 return newFuncDialOption(func(o *dialOptions) {
115 o.copts.WriteBufferSize = s
116 })
117}
118
119// WithReadBufferSize lets you set the size of read buffer, this determines how
120// much data can be read at most for each read syscall.
121//
122// The default value for this buffer is 32KB. Zero will disable read buffer for
123// a connection so data framer can access the underlying conn directly.
124func WithReadBufferSize(s int) DialOption {
125 return newFuncDialOption(func(o *dialOptions) {
126 o.copts.ReadBufferSize = s
127 })
128}
129
130// WithInitialWindowSize returns a DialOption which sets the value for initial
131// window size on a stream. The lower bound for window size is 64K and any value
132// smaller than that will be ignored.
133func WithInitialWindowSize(s int32) DialOption {
134 return newFuncDialOption(func(o *dialOptions) {
135 o.copts.InitialWindowSize = s
136 })
137}
138
139// WithInitialConnWindowSize returns a DialOption which sets the value for
140// initial window size on a connection. The lower bound for window size is 64K
141// and any value smaller than that will be ignored.
142func WithInitialConnWindowSize(s int32) DialOption {
143 return newFuncDialOption(func(o *dialOptions) {
144 o.copts.InitialConnWindowSize = s
145 })
146}
147
148// WithMaxMsgSize returns a DialOption which sets the maximum message size the
149// client can receive.
150//
151// Deprecated: use WithDefaultCallOptions(MaxCallRecvMsgSize(s)) instead.
152func WithMaxMsgSize(s int) DialOption {
153 return WithDefaultCallOptions(MaxCallRecvMsgSize(s))
154}
155
156// WithDefaultCallOptions returns a DialOption which sets the default
157// CallOptions for calls over the connection.
158func WithDefaultCallOptions(cos ...CallOption) DialOption {
159 return newFuncDialOption(func(o *dialOptions) {
160 o.callOptions = append(o.callOptions, cos...)
161 })
162}
163
164// WithCodec returns a DialOption which sets a codec for message marshaling and
165// unmarshaling.
166//
167// Deprecated: use WithDefaultCallOptions(CallCustomCodec(c)) instead.
168func WithCodec(c Codec) DialOption {
169 return WithDefaultCallOptions(CallCustomCodec(c))
170}
171
172// WithCompressor returns a DialOption which sets a Compressor to use for
173// message compression. It has lower priority than the compressor set by the
174// UseCompressor CallOption.
175//
176// Deprecated: use UseCompressor instead.
177func WithCompressor(cp Compressor) DialOption {
178 return newFuncDialOption(func(o *dialOptions) {
179 o.cp = cp
180 })
181}
182
183// WithDecompressor returns a DialOption which sets a Decompressor to use for
184// incoming message decompression. If incoming response messages are encoded
185// using the decompressor's Type(), it will be used. Otherwise, the message
186// encoding will be used to look up the compressor registered via
187// encoding.RegisterCompressor, which will then be used to decompress the
188// message. If no compressor is registered for the encoding, an Unimplemented
189// status error will be returned.
190//
191// Deprecated: use encoding.RegisterCompressor instead.
192func WithDecompressor(dc Decompressor) DialOption {
193 return newFuncDialOption(func(o *dialOptions) {
194 o.dc = dc
195 })
196}
197
198// WithBalancer returns a DialOption which sets a load balancer with the v1 API.
199// Name resolver will be ignored if this DialOption is specified.
200//
201// Deprecated: use the new balancer APIs in balancer package and
202// WithBalancerName.
203func WithBalancer(b Balancer) DialOption {
204 return newFuncDialOption(func(o *dialOptions) {
205 o.balancerBuilder = &balancerWrapperBuilder{
206 b: b,
207 }
208 })
209}
210
211// WithBalancerName sets the balancer that the ClientConn will be initialized
212// with. Balancer registered with balancerName will be used. This function
213// panics if no balancer was registered by balancerName.
214//
215// The balancer cannot be overridden by balancer option specified by service
216// config.
217//
218// This is an EXPERIMENTAL API.
219func WithBalancerName(balancerName string) DialOption {
220 builder := balancer.Get(balancerName)
221 if builder == nil {
222 panic(fmt.Sprintf("grpc.WithBalancerName: no balancer is registered for name %v", balancerName))
223 }
224 return newFuncDialOption(func(o *dialOptions) {
225 o.balancerBuilder = builder
226 })
227}
228
229// withResolverBuilder is only for grpclb.
230func withResolverBuilder(b resolver.Builder) DialOption {
231 return newFuncDialOption(func(o *dialOptions) {
232 o.resolverBuilder = b
233 })
234}
235
236// WithServiceConfig returns a DialOption which has a channel to read the
237// service configuration.
238//
239// Deprecated: service config should be received through name resolver, as
240// specified here.
241// https://github.com/grpc/grpc/blob/master/doc/service_config.md
242func WithServiceConfig(c <-chan ServiceConfig) DialOption {
243 return newFuncDialOption(func(o *dialOptions) {
244 o.scChan = c
245 })
246}
247
248// WithBackoffMaxDelay configures the dialer to use the provided maximum delay
249// when backing off after failed connection attempts.
250func WithBackoffMaxDelay(md time.Duration) DialOption {
251 return WithBackoffConfig(BackoffConfig{MaxDelay: md})
252}
253
254// WithBackoffConfig configures the dialer to use the provided backoff
255// parameters after connection failures.
256//
257// Use WithBackoffMaxDelay until more parameters on BackoffConfig are opened up
258// for use.
259func WithBackoffConfig(b BackoffConfig) DialOption {
260 return withBackoff(backoff.Exponential{
261 MaxDelay: b.MaxDelay,
262 })
263}
264
265// withBackoff sets the backoff strategy used for connectRetryNum after a failed
266// connection attempt.
267//
268// This can be exported if arbitrary backoff strategies are allowed by gRPC.
269func withBackoff(bs backoff.Strategy) DialOption {
270 return newFuncDialOption(func(o *dialOptions) {
271 o.bs = bs
272 })
273}
274
275// WithBlock returns a DialOption which makes caller of Dial blocks until the
276// underlying connection is up. Without this, Dial returns immediately and
277// connecting the server happens in background.
278func WithBlock() DialOption {
279 return newFuncDialOption(func(o *dialOptions) {
280 o.block = true
281 })
282}
283
284// WithInsecure returns a DialOption which disables transport security for this
285// ClientConn. Note that transport security is required unless WithInsecure is
286// set.
287func WithInsecure() DialOption {
288 return newFuncDialOption(func(o *dialOptions) {
289 o.insecure = true
290 })
291}
292
293// WithTransportCredentials returns a DialOption which configures a connection
294// level security credentials (e.g., TLS/SSL). This should not be used together
295// with WithCredentialsBundle.
296func WithTransportCredentials(creds credentials.TransportCredentials) DialOption {
297 return newFuncDialOption(func(o *dialOptions) {
298 o.copts.TransportCredentials = creds
299 })
300}
301
302// WithPerRPCCredentials returns a DialOption which sets credentials and places
303// auth state on each outbound RPC.
304func WithPerRPCCredentials(creds credentials.PerRPCCredentials) DialOption {
305 return newFuncDialOption(func(o *dialOptions) {
306 o.copts.PerRPCCredentials = append(o.copts.PerRPCCredentials, creds)
307 })
308}
309
310// WithCredentialsBundle returns a DialOption to set a credentials bundle for
311// the ClientConn.WithCreds. This should not be used together with
312// WithTransportCredentials.
313//
314// This API is experimental.
315func WithCredentialsBundle(b credentials.Bundle) DialOption {
316 return newFuncDialOption(func(o *dialOptions) {
317 o.copts.CredsBundle = b
318 })
319}
320
321// WithTimeout returns a DialOption that configures a timeout for dialing a
322// ClientConn initially. This is valid if and only if WithBlock() is present.
323//
324// Deprecated: use DialContext and context.WithTimeout instead.
325func WithTimeout(d time.Duration) DialOption {
326 return newFuncDialOption(func(o *dialOptions) {
327 o.timeout = d
328 })
329}
330
331func withContextDialer(f func(context.Context, string) (net.Conn, error)) DialOption {
332 return newFuncDialOption(func(o *dialOptions) {
333 o.copts.Dialer = f
334 })
335}
336
337func init() {
338 internal.WithContextDialer = withContextDialer
339 internal.WithResolverBuilder = withResolverBuilder
340 internal.WithHealthCheckFunc = withHealthCheckFunc
341}
342
343// WithDialer returns a DialOption that specifies a function to use for dialing
344// network addresses. If FailOnNonTempDialError() is set to true, and an error
345// is returned by f, gRPC checks the error's Temporary() method to decide if it
346// should try to reconnect to the network address.
347func WithDialer(f func(string, time.Duration) (net.Conn, error)) DialOption {
348 return withContextDialer(
349 func(ctx context.Context, addr string) (net.Conn, error) {
350 if deadline, ok := ctx.Deadline(); ok {
351 return f(addr, deadline.Sub(time.Now()))
352 }
353 return f(addr, 0)
354 })
355}
356
357// WithStatsHandler returns a DialOption that specifies the stats handler for
358// all the RPCs and underlying network connections in this ClientConn.
359func WithStatsHandler(h stats.Handler) DialOption {
360 return newFuncDialOption(func(o *dialOptions) {
361 o.copts.StatsHandler = h
362 })
363}
364
365// FailOnNonTempDialError returns a DialOption that specifies if gRPC fails on
366// non-temporary dial errors. If f is true, and dialer returns a non-temporary
367// error, gRPC will fail the connection to the network address and won't try to
368// reconnect. The default value of FailOnNonTempDialError is false.
369//
370// FailOnNonTempDialError only affects the initial dial, and does not do
371// anything useful unless you are also using WithBlock().
372//
373// This is an EXPERIMENTAL API.
374func FailOnNonTempDialError(f bool) DialOption {
375 return newFuncDialOption(func(o *dialOptions) {
376 o.copts.FailOnNonTempDialError = f
377 })
378}
379
380// WithUserAgent returns a DialOption that specifies a user agent string for all
381// the RPCs.
382func WithUserAgent(s string) DialOption {
383 return newFuncDialOption(func(o *dialOptions) {
384 o.copts.UserAgent = s
385 })
386}
387
388// WithKeepaliveParams returns a DialOption that specifies keepalive parameters
389// for the client transport.
390func WithKeepaliveParams(kp keepalive.ClientParameters) DialOption {
391 return newFuncDialOption(func(o *dialOptions) {
392 o.copts.KeepaliveParams = kp
393 })
394}
395
396// WithUnaryInterceptor returns a DialOption that specifies the interceptor for
397// unary RPCs.
398func WithUnaryInterceptor(f UnaryClientInterceptor) DialOption {
399 return newFuncDialOption(func(o *dialOptions) {
400 o.unaryInt = f
401 })
402}
403
404// WithStreamInterceptor returns a DialOption that specifies the interceptor for
405// streaming RPCs.
406func WithStreamInterceptor(f StreamClientInterceptor) DialOption {
407 return newFuncDialOption(func(o *dialOptions) {
408 o.streamInt = f
409 })
410}
411
412// WithAuthority returns a DialOption that specifies the value to be used as the
413// :authority pseudo-header. This value only works with WithInsecure and has no
414// effect if TransportCredentials are present.
415func WithAuthority(a string) DialOption {
416 return newFuncDialOption(func(o *dialOptions) {
417 o.authority = a
418 })
419}
420
421// WithChannelzParentID returns a DialOption that specifies the channelz ID of
422// current ClientConn's parent. This function is used in nested channel creation
423// (e.g. grpclb dial).
424func WithChannelzParentID(id int64) DialOption {
425 return newFuncDialOption(func(o *dialOptions) {
426 o.channelzParentID = id
427 })
428}
429
430// WithDisableServiceConfig returns a DialOption that causes grpc to ignore any
431// service config provided by the resolver and provides a hint to the resolver
432// to not fetch service configs.
433func WithDisableServiceConfig() DialOption {
434 return newFuncDialOption(func(o *dialOptions) {
435 o.disableServiceConfig = true
436 })
437}
438
439// WithDisableRetry returns a DialOption that disables retries, even if the
440// service config enables them. This does not impact transparent retries, which
441// will happen automatically if no data is written to the wire or if the RPC is
442// unprocessed by the remote server.
443//
444// Retry support is currently disabled by default, but will be enabled by
445// default in the future. Until then, it may be enabled by setting the
446// environment variable "GRPC_GO_RETRY" to "on".
447//
448// This API is EXPERIMENTAL.
449func WithDisableRetry() DialOption {
450 return newFuncDialOption(func(o *dialOptions) {
451 o.disableRetry = true
452 })
453}
454
455// WithMaxHeaderListSize returns a DialOption that specifies the maximum
456// (uncompressed) size of header list that the client is prepared to accept.
457func WithMaxHeaderListSize(s uint32) DialOption {
458 return newFuncDialOption(func(o *dialOptions) {
459 o.copts.MaxHeaderListSize = &s
460 })
461}
462
463// WithDisableHealthCheck disables the LB channel health checking for all SubConns of this ClientConn.
464//
465// This API is EXPERIMENTAL.
466func WithDisableHealthCheck() DialOption {
467 return newFuncDialOption(func(o *dialOptions) {
468 o.disableHealthCheck = true
469 })
470}
471
472// withHealthCheckFunc replaces the default health check function with the provided one. It makes
473// tests easier to change the health check function.
474//
475// For testing purpose only.
476func withHealthCheckFunc(f internal.HealthChecker) DialOption {
477 return newFuncDialOption(func(o *dialOptions) {
478 o.healthCheckFunc = f
479 })
480}
481
482func defaultDialOptions() dialOptions {
483 return dialOptions{
484 disableRetry: !envconfig.Retry,
485 reqHandshake: envconfig.RequireHandshake,
486 healthCheckFunc: internal.HealthCheckFunc,
487 copts: transport.ConnectOptions{
488 WriteBufferSize: defaultWriteBufSize,
489 ReadBufferSize: defaultReadBufSize,
490 },
491 }
492}
diff --git a/vendor/google.golang.org/grpc/encoding/encoding.go b/vendor/google.golang.org/grpc/encoding/encoding.go
new file mode 100644
index 0000000..ade8b7c
--- /dev/null
+++ b/vendor/google.golang.org/grpc/encoding/encoding.go
@@ -0,0 +1,118 @@
1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// Package encoding defines the interface for the compressor and codec, and
20// functions to register and retrieve compressors and codecs.
21//
22// This package is EXPERIMENTAL.
23package encoding
24
25import (
26 "io"
27 "strings"
28)
29
30// Identity specifies the optional encoding for uncompressed streams.
31// It is intended for grpc internal use only.
32const Identity = "identity"
33
34// Compressor is used for compressing and decompressing when sending or
35// receiving messages.
36type Compressor interface {
37 // Compress writes the data written to wc to w after compressing it. If an
38 // error occurs while initializing the compressor, that error is returned
39 // instead.
40 Compress(w io.Writer) (io.WriteCloser, error)
41 // Decompress reads data from r, decompresses it, and provides the
42 // uncompressed data via the returned io.Reader. If an error occurs while
43 // initializing the decompressor, that error is returned instead.
44 Decompress(r io.Reader) (io.Reader, error)
45 // Name is the name of the compression codec and is used to set the content
46 // coding header. The result must be static; the result cannot change
47 // between calls.
48 Name() string
49}
50
51var registeredCompressor = make(map[string]Compressor)
52
53// RegisterCompressor registers the compressor with gRPC by its name. It can
54// be activated when sending an RPC via grpc.UseCompressor(). It will be
55// automatically accessed when receiving a message based on the content coding
56// header. Servers also use it to send a response with the same encoding as
57// the request.
58//
59// NOTE: this function must only be called during initialization time (i.e. in
60// an init() function), and is not thread-safe. If multiple Compressors are
61// registered with the same name, the one registered last will take effect.
62func RegisterCompressor(c Compressor) {
63 registeredCompressor[c.Name()] = c
64}
65
66// GetCompressor returns Compressor for the given compressor name.
67func GetCompressor(name string) Compressor {
68 return registeredCompressor[name]
69}
70
71// Codec defines the interface gRPC uses to encode and decode messages. Note
72// that implementations of this interface must be thread safe; a Codec's
73// methods can be called from concurrent goroutines.
74type Codec interface {
75 // Marshal returns the wire format of v.
76 Marshal(v interface{}) ([]byte, error)
77 // Unmarshal parses the wire format into v.
78 Unmarshal(data []byte, v interface{}) error
79 // Name returns the name of the Codec implementation. The returned string
80 // will be used as part of content type in transmission. The result must be
81 // static; the result cannot change between calls.
82 Name() string
83}
84
85var registeredCodecs = make(map[string]Codec)
86
87// RegisterCodec registers the provided Codec for use with all gRPC clients and
88// servers.
89//
90// The Codec will be stored and looked up by result of its Name() method, which
91// should match the content-subtype of the encoding handled by the Codec. This
92// is case-insensitive, and is stored and looked up as lowercase. If the
93// result of calling Name() is an empty string, RegisterCodec will panic. See
94// Content-Type on
95// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
96// more details.
97//
98// NOTE: this function must only be called during initialization time (i.e. in
99// an init() function), and is not thread-safe. If multiple Compressors are
100// registered with the same name, the one registered last will take effect.
101func RegisterCodec(codec Codec) {
102 if codec == nil {
103 panic("cannot register a nil Codec")
104 }
105 contentSubtype := strings.ToLower(codec.Name())
106 if contentSubtype == "" {
107 panic("cannot register Codec with empty string result for String()")
108 }
109 registeredCodecs[contentSubtype] = codec
110}
111
112// GetCodec gets a registered Codec by content-subtype, or nil if no Codec is
113// registered for the content-subtype.
114//
115// The content-subtype is expected to be lowercase.
116func GetCodec(contentSubtype string) Codec {
117 return registeredCodecs[contentSubtype]
118}
diff --git a/vendor/google.golang.org/grpc/encoding/proto/proto.go b/vendor/google.golang.org/grpc/encoding/proto/proto.go
new file mode 100644
index 0000000..66b97a6
--- /dev/null
+++ b/vendor/google.golang.org/grpc/encoding/proto/proto.go
@@ -0,0 +1,110 @@
1/*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// Package proto defines the protobuf codec. Importing this package will
20// register the codec.
21package proto
22
23import (
24 "math"
25 "sync"
26
27 "github.com/golang/protobuf/proto"
28 "google.golang.org/grpc/encoding"
29)
30
31// Name is the name registered for the proto compressor.
32const Name = "proto"
33
34func init() {
35 encoding.RegisterCodec(codec{})
36}
37
38// codec is a Codec implementation with protobuf. It is the default codec for gRPC.
39type codec struct{}
40
41type cachedProtoBuffer struct {
42 lastMarshaledSize uint32
43 proto.Buffer
44}
45
46func capToMaxInt32(val int) uint32 {
47 if val > math.MaxInt32 {
48 return uint32(math.MaxInt32)
49 }
50 return uint32(val)
51}
52
53func marshal(v interface{}, cb *cachedProtoBuffer) ([]byte, error) {
54 protoMsg := v.(proto.Message)
55 newSlice := make([]byte, 0, cb.lastMarshaledSize)
56
57 cb.SetBuf(newSlice)
58 cb.Reset()
59 if err := cb.Marshal(protoMsg); err != nil {
60 return nil, err
61 }
62 out := cb.Bytes()
63 cb.lastMarshaledSize = capToMaxInt32(len(out))
64 return out, nil
65}
66
67func (codec) Marshal(v interface{}) ([]byte, error) {
68 if pm, ok := v.(proto.Marshaler); ok {
69 // object can marshal itself, no need for buffer
70 return pm.Marshal()
71 }
72
73 cb := protoBufferPool.Get().(*cachedProtoBuffer)
74 out, err := marshal(v, cb)
75
76 // put back buffer and lose the ref to the slice
77 cb.SetBuf(nil)
78 protoBufferPool.Put(cb)
79 return out, err
80}
81
82func (codec) Unmarshal(data []byte, v interface{}) error {
83 protoMsg := v.(proto.Message)
84 protoMsg.Reset()
85
86 if pu, ok := protoMsg.(proto.Unmarshaler); ok {
87 // object can unmarshal itself, no need for buffer
88 return pu.Unmarshal(data)
89 }
90
91 cb := protoBufferPool.Get().(*cachedProtoBuffer)
92 cb.SetBuf(data)
93 err := cb.Unmarshal(protoMsg)
94 cb.SetBuf(nil)
95 protoBufferPool.Put(cb)
96 return err
97}
98
99func (codec) Name() string {
100 return Name
101}
102
103var protoBufferPool = &sync.Pool{
104 New: func() interface{} {
105 return &cachedProtoBuffer{
106 Buffer: proto.Buffer{},
107 lastMarshaledSize: 16,
108 }
109 },
110}
diff --git a/vendor/google.golang.org/grpc/go.mod b/vendor/google.golang.org/grpc/go.mod
new file mode 100644
index 0000000..f296dcf
--- /dev/null
+++ b/vendor/google.golang.org/grpc/go.mod
@@ -0,0 +1,20 @@
1module google.golang.org/grpc
2
3require (
4 cloud.google.com/go v0.26.0 // indirect
5 github.com/client9/misspell v0.3.4
6 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
7 github.com/golang/mock v1.1.1
8 github.com/golang/protobuf v1.2.0
9 github.com/kisielk/gotool v1.0.0 // indirect
10 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3
11 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d
12 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be
13 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f // indirect
14 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522
15 golang.org/x/text v0.3.0 // indirect
16 golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52
17 google.golang.org/appengine v1.1.0 // indirect
18 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8
19 honnef.co/go/tools v0.0.0-20180728063816-88497007e858
20)
diff --git a/vendor/google.golang.org/grpc/go.sum b/vendor/google.golang.org/grpc/go.sum
new file mode 100644
index 0000000..bfb6bb7
--- /dev/null
+++ b/vendor/google.golang.org/grpc/go.sum
@@ -0,0 +1,32 @@
1cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
2cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
3github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
4github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
5github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
6github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
7github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
8github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
9github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
10github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
11github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
12github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
13golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3 h1:x/bBzNauLQAlE3fLku/xy92Y8QwKX5HZymrMz2IiKFc=
14golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
15golang.org/x/net v0.0.0-20180826012351-8a410e7b638d h1:g9qWBGx4puODJTMVyoPrpoxPFgVGd+z1DZwjfRu4d0I=
16golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
17golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
18golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
19golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
20golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
21golang.org/x/sys v0.0.0-20180830151530-49385e6e1522 h1:Ve1ORMCxvRmSXBwJK+t3Oy+V2vRW2OetUQBq4rJIkZE=
22golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
23golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
24golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
25golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52 h1:JG/0uqcGdTNgq7FdU+61l5Pdmb8putNZlXb65bJBROs=
26golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
27google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=
28google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
29google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
30google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
31honnef.co/go/tools v0.0.0-20180728063816-88497007e858 h1:wN+eVZ7U+gqdqkec6C6VXR1OFf9a5Ul9ETzeYsYv20g=
32honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/vendor/google.golang.org/grpc/go16.go b/vendor/google.golang.org/grpc/go16.go
deleted file mode 100644
index f3dbf21..0000000
--- a/vendor/google.golang.org/grpc/go16.go
+++ /dev/null
@@ -1,98 +0,0 @@
1// +build go1.6,!go1.7
2
3/*
4 *
5 * Copyright 2016 gRPC authors.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */
20
21package grpc
22
23import (
24 "fmt"
25 "io"
26 "net"
27 "net/http"
28 "os"
29
30 "golang.org/x/net/context"
31 "google.golang.org/grpc/codes"
32 "google.golang.org/grpc/status"
33 "google.golang.org/grpc/transport"
34)
35
36// dialContext connects to the address on the named network.
37func dialContext(ctx context.Context, network, address string) (net.Conn, error) {
38 return (&net.Dialer{Cancel: ctx.Done()}).Dial(network, address)
39}
40
41func sendHTTPRequest(ctx context.Context, req *http.Request, conn net.Conn) error {
42 req.Cancel = ctx.Done()
43 if err := req.Write(conn); err != nil {
44 return fmt.Errorf("failed to write the HTTP request: %v", err)
45 }
46 return nil
47}
48
49// toRPCErr converts an error into an error from the status package.
50func toRPCErr(err error) error {
51 if _, ok := status.FromError(err); ok {
52 return err
53 }
54 switch e := err.(type) {
55 case transport.StreamError:
56 return status.Error(e.Code, e.Desc)
57 case transport.ConnectionError:
58 return status.Error(codes.Unavailable, e.Desc)
59 default:
60 switch err {
61 case context.DeadlineExceeded:
62 return status.Error(codes.DeadlineExceeded, err.Error())
63 case context.Canceled:
64 return status.Error(codes.Canceled, err.Error())
65 case ErrClientConnClosing:
66 return status.Error(codes.FailedPrecondition, err.Error())
67 }
68 }
69 return status.Error(codes.Unknown, err.Error())
70}
71
72// convertCode converts a standard Go error into its canonical code. Note that
73// this is only used to translate the error returned by the server applications.
74func convertCode(err error) codes.Code {
75 switch err {
76 case nil:
77 return codes.OK
78 case io.EOF:
79 return codes.OutOfRange
80 case io.ErrClosedPipe, io.ErrNoProgress, io.ErrShortBuffer, io.ErrShortWrite, io.ErrUnexpectedEOF:
81 return codes.FailedPrecondition
82 case os.ErrInvalid:
83 return codes.InvalidArgument
84 case context.Canceled:
85 return codes.Canceled
86 case context.DeadlineExceeded:
87 return codes.DeadlineExceeded
88 }
89 switch {
90 case os.IsExist(err):
91 return codes.AlreadyExists
92 case os.IsNotExist(err):
93 return codes.NotFound
94 case os.IsPermission(err):
95 return codes.PermissionDenied
96 }
97 return codes.Unknown
98}
diff --git a/vendor/google.golang.org/grpc/go17.go b/vendor/google.golang.org/grpc/go17.go
deleted file mode 100644
index a3421d9..0000000
--- a/vendor/google.golang.org/grpc/go17.go
+++ /dev/null
@@ -1,98 +0,0 @@
1// +build go1.7
2
3/*
4 *
5 * Copyright 2016 gRPC authors.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */
20
21package grpc
22
23import (
24 "context"
25 "io"
26 "net"
27 "net/http"
28 "os"
29
30 netctx "golang.org/x/net/context"
31 "google.golang.org/grpc/codes"
32 "google.golang.org/grpc/status"
33 "google.golang.org/grpc/transport"
34)
35
36// dialContext connects to the address on the named network.
37func dialContext(ctx context.Context, network, address string) (net.Conn, error) {
38 return (&net.Dialer{}).DialContext(ctx, network, address)
39}
40
41func sendHTTPRequest(ctx context.Context, req *http.Request, conn net.Conn) error {
42 req = req.WithContext(ctx)
43 if err := req.Write(conn); err != nil {
44 return err
45 }
46 return nil
47}
48
49// toRPCErr converts an error into an error from the status package.
50func toRPCErr(err error) error {
51 if _, ok := status.FromError(err); ok {
52 return err
53 }
54 switch e := err.(type) {
55 case transport.StreamError:
56 return status.Error(e.Code, e.Desc)
57 case transport.ConnectionError:
58 return status.Error(codes.Unavailable, e.Desc)
59 default:
60 switch err {
61 case context.DeadlineExceeded, netctx.DeadlineExceeded:
62 return status.Error(codes.DeadlineExceeded, err.Error())
63 case context.Canceled, netctx.Canceled:
64 return status.Error(codes.Canceled, err.Error())
65 case ErrClientConnClosing:
66 return status.Error(codes.FailedPrecondition, err.Error())
67 }
68 }
69 return status.Error(codes.Unknown, err.Error())
70}
71
72// convertCode converts a standard Go error into its canonical code. Note that
73// this is only used to translate the error returned by the server applications.
74func convertCode(err error) codes.Code {
75 switch err {
76 case nil:
77 return codes.OK
78 case io.EOF:
79 return codes.OutOfRange
80 case io.ErrClosedPipe, io.ErrNoProgress, io.ErrShortBuffer, io.ErrShortWrite, io.ErrUnexpectedEOF:
81 return codes.FailedPrecondition
82 case os.ErrInvalid:
83 return codes.InvalidArgument
84 case context.Canceled, netctx.Canceled:
85 return codes.Canceled
86 case context.DeadlineExceeded, netctx.DeadlineExceeded:
87 return codes.DeadlineExceeded
88 }
89 switch {
90 case os.IsExist(err):
91 return codes.AlreadyExists
92 case os.IsNotExist(err):
93 return codes.NotFound
94 case os.IsPermission(err):
95 return codes.PermissionDenied
96 }
97 return codes.Unknown
98}
diff --git a/vendor/google.golang.org/grpc/grpclb.go b/vendor/google.golang.org/grpc/grpclb.go
deleted file mode 100644
index f7b6b7d..0000000
--- a/vendor/google.golang.org/grpc/grpclb.go
+++ /dev/null
@@ -1,737 +0,0 @@
1/*
2 *
3 * Copyright 2016 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package grpc
20
21import (
22 "errors"
23 "fmt"
24 "math/rand"
25 "net"
26 "sync"
27 "time"
28
29 "golang.org/x/net/context"
30 "google.golang.org/grpc/codes"
31 lbpb "google.golang.org/grpc/grpclb/grpc_lb_v1"
32 "google.golang.org/grpc/grpclog"
33 "google.golang.org/grpc/metadata"
34 "google.golang.org/grpc/naming"
35)
36
37// Client API for LoadBalancer service.
38// Mostly copied from generated pb.go file.
39// To avoid circular dependency.
40type loadBalancerClient struct {
41 cc *ClientConn
42}
43
44func (c *loadBalancerClient) BalanceLoad(ctx context.Context, opts ...CallOption) (*balanceLoadClientStream, error) {
45 desc := &StreamDesc{
46 StreamName: "BalanceLoad",
47 ServerStreams: true,
48 ClientStreams: true,
49 }
50 stream, err := NewClientStream(ctx, desc, c.cc, "/grpc.lb.v1.LoadBalancer/BalanceLoad", opts...)
51 if err != nil {
52 return nil, err
53 }
54 x := &balanceLoadClientStream{stream}
55 return x, nil
56}
57
58type balanceLoadClientStream struct {
59 ClientStream
60}
61
62func (x *balanceLoadClientStream) Send(m *lbpb.LoadBalanceRequest) error {
63 return x.ClientStream.SendMsg(m)
64}
65
66func (x *balanceLoadClientStream) Recv() (*lbpb.LoadBalanceResponse, error) {
67 m := new(lbpb.LoadBalanceResponse)
68 if err := x.ClientStream.RecvMsg(m); err != nil {
69 return nil, err
70 }
71 return m, nil
72}
73
74// NewGRPCLBBalancer creates a grpclb load balancer.
75func NewGRPCLBBalancer(r naming.Resolver) Balancer {
76 return &balancer{
77 r: r,
78 }
79}
80
81type remoteBalancerInfo struct {
82 addr string
83 // the server name used for authentication with the remote LB server.
84 name string
85}
86
87// grpclbAddrInfo consists of the information of a backend server.
88type grpclbAddrInfo struct {
89 addr Address
90 connected bool
91 // dropForRateLimiting indicates whether this particular request should be
92 // dropped by the client for rate limiting.
93 dropForRateLimiting bool
94 // dropForLoadBalancing indicates whether this particular request should be
95 // dropped by the client for load balancing.
96 dropForLoadBalancing bool
97}
98
99type balancer struct {
100 r naming.Resolver
101 target string
102 mu sync.Mutex
103 seq int // a sequence number to make sure addrCh does not get stale addresses.
104 w naming.Watcher
105 addrCh chan []Address
106 rbs []remoteBalancerInfo
107 addrs []*grpclbAddrInfo
108 next int
109 waitCh chan struct{}
110 done bool
111 expTimer *time.Timer
112 rand *rand.Rand
113
114 clientStats lbpb.ClientStats
115}
116
117func (b *balancer) watchAddrUpdates(w naming.Watcher, ch chan []remoteBalancerInfo) error {
118 updates, err := w.Next()
119 if err != nil {
120 grpclog.Warningf("grpclb: failed to get next addr update from watcher: %v", err)
121 return err
122 }
123 b.mu.Lock()
124 defer b.mu.Unlock()
125 if b.done {
126 return ErrClientConnClosing
127 }
128 for _, update := range updates {
129 switch update.Op {
130 case naming.Add:
131 var exist bool
132 for _, v := range b.rbs {
133 // TODO: Is the same addr with different server name a different balancer?
134 if update.Addr == v.addr {
135 exist = true
136 break
137 }
138 }
139 if exist {
140 continue
141 }
142 md, ok := update.Metadata.(*naming.AddrMetadataGRPCLB)
143 if !ok {
144 // TODO: Revisit the handling here and may introduce some fallback mechanism.
145 grpclog.Errorf("The name resolution contains unexpected metadata %v", update.Metadata)
146 continue
147 }
148 switch md.AddrType {
149 case naming.Backend:
150 // TODO: Revisit the handling here and may introduce some fallback mechanism.
151 grpclog.Errorf("The name resolution does not give grpclb addresses")
152 continue
153 case naming.GRPCLB:
154 b.rbs = append(b.rbs, remoteBalancerInfo{
155 addr: update.Addr,
156 name: md.ServerName,
157 })
158 default:
159 grpclog.Errorf("Received unknow address type %d", md.AddrType)
160 continue
161 }
162 case naming.Delete:
163 for i, v := range b.rbs {
164 if update.Addr == v.addr {
165 copy(b.rbs[i:], b.rbs[i+1:])
166 b.rbs = b.rbs[:len(b.rbs)-1]
167 break
168 }
169 }
170 default:
171 grpclog.Errorf("Unknown update.Op %v", update.Op)
172 }
173 }
174 // TODO: Fall back to the basic round-robin load balancing if the resulting address is
175 // not a load balancer.
176 select {
177 case <-ch:
178 default:
179 }
180 ch <- b.rbs
181 return nil
182}
183
184func (b *balancer) serverListExpire(seq int) {
185 b.mu.Lock()
186 defer b.mu.Unlock()
187 // TODO: gRPC interanls do not clear the connections when the server list is stale.
188 // This means RPCs will keep using the existing server list until b receives new
189 // server list even though the list is expired. Revisit this behavior later.
190 if b.done || seq < b.seq {
191 return
192 }
193 b.next = 0
194 b.addrs = nil
195 // Ask grpc internals to close all the corresponding connections.
196 b.addrCh <- nil
197}
198
199func convertDuration(d *lbpb.Duration) time.Duration {
200 if d == nil {
201 return 0
202 }
203 return time.Duration(d.Seconds)*time.Second + time.Duration(d.Nanos)*time.Nanosecond
204}
205
206func (b *balancer) processServerList(l *lbpb.ServerList, seq int) {
207 if l == nil {
208 return
209 }
210 servers := l.GetServers()
211 expiration := convertDuration(l.GetExpirationInterval())
212 var (
213 sl []*grpclbAddrInfo
214 addrs []Address
215 )
216 for _, s := range servers {
217 md := metadata.Pairs("lb-token", s.LoadBalanceToken)
218 ip := net.IP(s.IpAddress)
219 ipStr := ip.String()
220 if ip.To4() == nil {
221 // Add square brackets to ipv6 addresses, otherwise net.Dial() and
222 // net.SplitHostPort() will return too many colons error.
223 ipStr = fmt.Sprintf("[%s]", ipStr)
224 }
225 addr := Address{
226 Addr: fmt.Sprintf("%s:%d", ipStr, s.Port),
227 Metadata: &md,
228 }
229 sl = append(sl, &grpclbAddrInfo{
230 addr: addr,
231 dropForRateLimiting: s.DropForRateLimiting,
232 dropForLoadBalancing: s.DropForLoadBalancing,
233 })
234 addrs = append(addrs, addr)
235 }
236 b.mu.Lock()
237 defer b.mu.Unlock()
238 if b.done || seq < b.seq {
239 return
240 }
241 if len(sl) > 0 {
242 // reset b.next to 0 when replacing the server list.
243 b.next = 0
244 b.addrs = sl
245 b.addrCh <- addrs
246 if b.expTimer != nil {
247 b.expTimer.Stop()
248 b.expTimer = nil
249 }
250 if expiration > 0 {
251 b.expTimer = time.AfterFunc(expiration, func() {
252 b.serverListExpire(seq)
253 })
254 }
255 }
256 return
257}
258
259func (b *balancer) sendLoadReport(s *balanceLoadClientStream, interval time.Duration, done <-chan struct{}) {
260 ticker := time.NewTicker(interval)
261 defer ticker.Stop()
262 for {
263 select {
264 case <-ticker.C:
265 case <-done:
266 return
267 }
268 b.mu.Lock()
269 stats := b.clientStats
270 b.clientStats = lbpb.ClientStats{} // Clear the stats.
271 b.mu.Unlock()
272 t := time.Now()
273 stats.Timestamp = &lbpb.Timestamp{
274 Seconds: t.Unix(),
275 Nanos: int32(t.Nanosecond()),
276 }
277 if err := s.Send(&lbpb.LoadBalanceRequest{
278 LoadBalanceRequestType: &lbpb.LoadBalanceRequest_ClientStats{
279 ClientStats: &stats,
280 },
281 }); err != nil {
282 grpclog.Errorf("grpclb: failed to send load report: %v", err)
283 return
284 }
285 }
286}
287
288func (b *balancer) callRemoteBalancer(lbc *loadBalancerClient, seq int) (retry bool) {
289 ctx, cancel := context.WithCancel(context.Background())
290 defer cancel()
291 stream, err := lbc.BalanceLoad(ctx)
292 if err != nil {
293 grpclog.Errorf("grpclb: failed to perform RPC to the remote balancer %v", err)
294 return
295 }
296 b.mu.Lock()
297 if b.done {
298 b.mu.Unlock()
299 return
300 }
301 b.mu.Unlock()
302 initReq := &lbpb.LoadBalanceRequest{
303 LoadBalanceRequestType: &lbpb.LoadBalanceRequest_InitialRequest{
304 InitialRequest: &lbpb.InitialLoadBalanceRequest{
305 Name: b.target,
306 },
307 },
308 }
309 if err := stream.Send(initReq); err != nil {
310 grpclog.Errorf("grpclb: failed to send init request: %v", err)
311 // TODO: backoff on retry?
312 return true
313 }
314 reply, err := stream.Recv()
315 if err != nil {
316 grpclog.Errorf("grpclb: failed to recv init response: %v", err)
317 // TODO: backoff on retry?
318 return true
319 }
320 initResp := reply.GetInitialResponse()
321 if initResp == nil {
322 grpclog.Errorf("grpclb: reply from remote balancer did not include initial response.")
323 return
324 }
325 // TODO: Support delegation.
326 if initResp.LoadBalancerDelegate != "" {
327 // delegation
328 grpclog.Errorf("TODO: Delegation is not supported yet.")
329 return
330 }
331 streamDone := make(chan struct{})
332 defer close(streamDone)
333 b.mu.Lock()
334 b.clientStats = lbpb.ClientStats{} // Clear client stats.
335 b.mu.Unlock()
336 if d := convertDuration(initResp.ClientStatsReportInterval); d > 0 {
337 go b.sendLoadReport(stream, d, streamDone)
338 }
339 // Retrieve the server list.
340 for {
341 reply, err := stream.Recv()
342 if err != nil {
343 grpclog.Errorf("grpclb: failed to recv server list: %v", err)
344 break
345 }
346 b.mu.Lock()
347 if b.done || seq < b.seq {
348 b.mu.Unlock()
349 return
350 }
351 b.seq++ // tick when receiving a new list of servers.
352 seq = b.seq
353 b.mu.Unlock()
354 if serverList := reply.GetServerList(); serverList != nil {
355 b.processServerList(serverList, seq)
356 }
357 }
358 return true
359}
360
361func (b *balancer) Start(target string, config BalancerConfig) error {
362 b.rand = rand.New(rand.NewSource(time.Now().Unix()))
363 // TODO: Fall back to the basic direct connection if there is no name resolver.
364 if b.r == nil {
365 return errors.New("there is no name resolver installed")
366 }
367 b.target = target
368 b.mu.Lock()
369 if b.done {
370 b.mu.Unlock()
371 return ErrClientConnClosing
372 }
373 b.addrCh = make(chan []Address)
374 w, err := b.r.Resolve(target)
375 if err != nil {
376 b.mu.Unlock()
377 grpclog.Errorf("grpclb: failed to resolve address: %v, err: %v", target, err)
378 return err
379 }
380 b.w = w
381 b.mu.Unlock()
382 balancerAddrsCh := make(chan []remoteBalancerInfo, 1)
383 // Spawn a goroutine to monitor the name resolution of remote load balancer.
384 go func() {
385 for {
386 if err := b.watchAddrUpdates(w, balancerAddrsCh); err != nil {
387 grpclog.Warningf("grpclb: the naming watcher stops working due to %v.\n", err)
388 close(balancerAddrsCh)
389 return
390 }
391 }
392 }()
393 // Spawn a goroutine to talk to the remote load balancer.
394 go func() {
395 var (
396 cc *ClientConn
397 // ccError is closed when there is an error in the current cc.
398 // A new rb should be picked from rbs and connected.
399 ccError chan struct{}
400 rb *remoteBalancerInfo
401 rbs []remoteBalancerInfo
402 rbIdx int
403 )
404
405 defer func() {
406 if ccError != nil {
407 select {
408 case <-ccError:
409 default:
410 close(ccError)
411 }
412 }
413 if cc != nil {
414 cc.Close()
415 }
416 }()
417
418 for {
419 var ok bool
420 select {
421 case rbs, ok = <-balancerAddrsCh:
422 if !ok {
423 return
424 }
425 foundIdx := -1
426 if rb != nil {
427 for i, trb := range rbs {
428 if trb == *rb {
429 foundIdx = i
430 break
431 }
432 }
433 }
434 if foundIdx >= 0 {
435 if foundIdx >= 1 {
436 // Move the address in use to the beginning of the list.
437 b.rbs[0], b.rbs[foundIdx] = b.rbs[foundIdx], b.rbs[0]
438 rbIdx = 0
439 }
440 continue // If found, don't dial new cc.
441 } else if len(rbs) > 0 {
442 // Pick a random one from the list, instead of always using the first one.
443 if l := len(rbs); l > 1 && rb != nil {
444 tmpIdx := b.rand.Intn(l - 1)
445 b.rbs[0], b.rbs[tmpIdx] = b.rbs[tmpIdx], b.rbs[0]
446 }
447 rbIdx = 0
448 rb = &rbs[0]
449 } else {
450 // foundIdx < 0 && len(rbs) <= 0.
451 rb = nil
452 }
453 case <-ccError:
454 ccError = nil
455 if rbIdx < len(rbs)-1 {
456 rbIdx++
457 rb = &rbs[rbIdx]
458 } else {
459 rb = nil
460 }
461 }
462
463 if rb == nil {
464 continue
465 }
466
467 if cc != nil {
468 cc.Close()
469 }
470 // Talk to the remote load balancer to get the server list.
471 var (
472 err error
473 dopts []DialOption
474 )
475 if creds := config.DialCreds; creds != nil {
476 if rb.name != "" {
477 if err := creds.OverrideServerName(rb.name); err != nil {
478 grpclog.Warningf("grpclb: failed to override the server name in the credentials: %v", err)
479 continue
480 }
481 }
482 dopts = append(dopts, WithTransportCredentials(creds))
483 } else {
484 dopts = append(dopts, WithInsecure())
485 }
486 if dialer := config.Dialer; dialer != nil {
487 // WithDialer takes a different type of function, so we instead use a special DialOption here.
488 dopts = append(dopts, func(o *dialOptions) { o.copts.Dialer = dialer })
489 }
490 ccError = make(chan struct{})
491 cc, err = Dial(rb.addr, dopts...)
492 if err != nil {
493 grpclog.Warningf("grpclb: failed to setup a connection to the remote balancer %v: %v", rb.addr, err)
494 close(ccError)
495 continue
496 }
497 b.mu.Lock()
498 b.seq++ // tick when getting a new balancer address
499 seq := b.seq
500 b.next = 0
501 b.mu.Unlock()
502 go func(cc *ClientConn, ccError chan struct{}) {
503 lbc := &loadBalancerClient{cc}
504 b.callRemoteBalancer(lbc, seq)
505 cc.Close()
506 select {
507 case <-ccError:
508 default:
509 close(ccError)
510 }
511 }(cc, ccError)
512 }
513 }()
514 return nil
515}
516
517func (b *balancer) down(addr Address, err error) {
518 b.mu.Lock()
519 defer b.mu.Unlock()
520 for _, a := range b.addrs {
521 if addr == a.addr {
522 a.connected = false
523 break
524 }
525 }
526}
527
528func (b *balancer) Up(addr Address) func(error) {
529 b.mu.Lock()
530 defer b.mu.Unlock()
531 if b.done {
532 return nil
533 }
534 var cnt int
535 for _, a := range b.addrs {
536 if a.addr == addr {
537 if a.connected {
538 return nil
539 }
540 a.connected = true
541 }
542 if a.connected && !a.dropForRateLimiting && !a.dropForLoadBalancing {
543 cnt++
544 }
545 }
546 // addr is the only one which is connected. Notify the Get() callers who are blocking.
547 if cnt == 1 && b.waitCh != nil {
548 close(b.waitCh)
549 b.waitCh = nil
550 }
551 return func(err error) {
552 b.down(addr, err)
553 }
554}
555
556func (b *balancer) Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error) {
557 var ch chan struct{}
558 b.mu.Lock()
559 if b.done {
560 b.mu.Unlock()
561 err = ErrClientConnClosing
562 return
563 }
564 seq := b.seq
565
566 defer func() {
567 if err != nil {
568 return
569 }
570 put = func() {
571 s, ok := rpcInfoFromContext(ctx)
572 if !ok {
573 return
574 }
575 b.mu.Lock()
576 defer b.mu.Unlock()
577 if b.done || seq < b.seq {
578 return
579 }
580 b.clientStats.NumCallsFinished++
581 if !s.bytesSent {
582 b.clientStats.NumCallsFinishedWithClientFailedToSend++
583 } else if s.bytesReceived {
584 b.clientStats.NumCallsFinishedKnownReceived++
585 }
586 }
587 }()
588
589 b.clientStats.NumCallsStarted++
590 if len(b.addrs) > 0 {
591 if b.next >= len(b.addrs) {
592 b.next = 0
593 }
594 next := b.next
595 for {
596 a := b.addrs[next]
597 next = (next + 1) % len(b.addrs)
598 if a.connected {
599 if !a.dropForRateLimiting && !a.dropForLoadBalancing {
600 addr = a.addr
601 b.next = next
602 b.mu.Unlock()
603 return
604 }
605 if !opts.BlockingWait {
606 b.next = next
607 if a.dropForLoadBalancing {
608 b.clientStats.NumCallsFinished++
609 b.clientStats.NumCallsFinishedWithDropForLoadBalancing++
610 } else if a.dropForRateLimiting {
611 b.clientStats.NumCallsFinished++
612 b.clientStats.NumCallsFinishedWithDropForRateLimiting++
613 }
614 b.mu.Unlock()
615 err = Errorf(codes.Unavailable, "%s drops requests", a.addr.Addr)
616 return
617 }
618 }
619 if next == b.next {
620 // Has iterated all the possible address but none is connected.
621 break
622 }
623 }
624 }
625 if !opts.BlockingWait {
626 if len(b.addrs) == 0 {
627 b.clientStats.NumCallsFinished++
628 b.clientStats.NumCallsFinishedWithClientFailedToSend++
629 b.mu.Unlock()
630 err = Errorf(codes.Unavailable, "there is no address available")
631 return
632 }
633 // Returns the next addr on b.addrs for a failfast RPC.
634 addr = b.addrs[b.next].addr
635 b.next++
636 b.mu.Unlock()
637 return
638 }
639 // Wait on b.waitCh for non-failfast RPCs.
640 if b.waitCh == nil {
641 ch = make(chan struct{})
642 b.waitCh = ch
643 } else {
644 ch = b.waitCh
645 }
646 b.mu.Unlock()
647 for {
648 select {
649 case <-ctx.Done():
650 b.mu.Lock()
651 b.clientStats.NumCallsFinished++
652 b.clientStats.NumCallsFinishedWithClientFailedToSend++
653 b.mu.Unlock()
654 err = ctx.Err()
655 return
656 case <-ch:
657 b.mu.Lock()
658 if b.done {
659 b.clientStats.NumCallsFinished++
660 b.clientStats.NumCallsFinishedWithClientFailedToSend++
661 b.mu.Unlock()
662 err = ErrClientConnClosing
663 return
664 }
665
666 if len(b.addrs) > 0 {
667 if b.next >= len(b.addrs) {
668 b.next = 0
669 }
670 next := b.next
671 for {
672 a := b.addrs[next]
673 next = (next + 1) % len(b.addrs)
674 if a.connected {
675 if !a.dropForRateLimiting && !a.dropForLoadBalancing {
676 addr = a.addr
677 b.next = next
678 b.mu.Unlock()
679 return
680 }
681 if !opts.BlockingWait {
682 b.next = next
683 if a.dropForLoadBalancing {
684 b.clientStats.NumCallsFinished++
685 b.clientStats.NumCallsFinishedWithDropForLoadBalancing++
686 } else if a.dropForRateLimiting {
687 b.clientStats.NumCallsFinished++
688 b.clientStats.NumCallsFinishedWithDropForRateLimiting++
689 }
690 b.mu.Unlock()
691 err = Errorf(codes.Unavailable, "drop requests for the addreess %s", a.addr.Addr)
692 return
693 }
694 }
695 if next == b.next {
696 // Has iterated all the possible address but none is connected.
697 break
698 }
699 }
700 }
701 // The newly added addr got removed by Down() again.
702 if b.waitCh == nil {
703 ch = make(chan struct{})
704 b.waitCh = ch
705 } else {
706 ch = b.waitCh
707 }
708 b.mu.Unlock()
709 }
710 }
711}
712
713func (b *balancer) Notify() <-chan []Address {
714 return b.addrCh
715}
716
717func (b *balancer) Close() error {
718 b.mu.Lock()
719 defer b.mu.Unlock()
720 if b.done {
721 return errBalancerClosed
722 }
723 b.done = true
724 if b.expTimer != nil {
725 b.expTimer.Stop()
726 }
727 if b.waitCh != nil {
728 close(b.waitCh)
729 }
730 if b.addrCh != nil {
731 close(b.addrCh)
732 }
733 if b.w != nil {
734 b.w.Close()
735 }
736 return nil
737}
diff --git a/vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/grpclb.pb.go b/vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/grpclb.pb.go
deleted file mode 100644
index f63941b..0000000
--- a/vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/grpclb.pb.go
+++ /dev/null
@@ -1,629 +0,0 @@
1// Code generated by protoc-gen-go.
2// source: grpclb.proto
3// DO NOT EDIT!
4
5/*
6Package grpc_lb_v1 is a generated protocol buffer package.
7
8It is generated from these files:
9 grpclb.proto
10
11It has these top-level messages:
12 Duration
13 Timestamp
14 LoadBalanceRequest
15 InitialLoadBalanceRequest
16 ClientStats
17 LoadBalanceResponse
18 InitialLoadBalanceResponse
19 ServerList
20 Server
21*/
22package grpc_lb_v1
23
24import proto "github.com/golang/protobuf/proto"
25import fmt "fmt"
26import math "math"
27
28// Reference imports to suppress errors if they are not otherwise used.
29var _ = proto.Marshal
30var _ = fmt.Errorf
31var _ = math.Inf
32
33// This is a compile-time assertion to ensure that this generated file
34// is compatible with the proto package it is being compiled against.
35// A compilation error at this line likely means your copy of the
36// proto package needs to be updated.
37const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
38
39type Duration struct {
40 // Signed seconds of the span of time. Must be from -315,576,000,000
41 // to +315,576,000,000 inclusive.
42 Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"`
43 // Signed fractions of a second at nanosecond resolution of the span
44 // of time. Durations less than one second are represented with a 0
45 // `seconds` field and a positive or negative `nanos` field. For durations
46 // of one second or more, a non-zero value for the `nanos` field must be
47 // of the same sign as the `seconds` field. Must be from -999,999,999
48 // to +999,999,999 inclusive.
49 Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"`
50}
51
52func (m *Duration) Reset() { *m = Duration{} }
53func (m *Duration) String() string { return proto.CompactTextString(m) }
54func (*Duration) ProtoMessage() {}
55func (*Duration) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
56
57func (m *Duration) GetSeconds() int64 {
58 if m != nil {
59 return m.Seconds
60 }
61 return 0
62}
63
64func (m *Duration) GetNanos() int32 {
65 if m != nil {
66 return m.Nanos
67 }
68 return 0
69}
70
71type Timestamp struct {
72 // Represents seconds of UTC time since Unix epoch
73 // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
74 // 9999-12-31T23:59:59Z inclusive.
75 Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"`
76 // Non-negative fractions of a second at nanosecond resolution. Negative
77 // second values with fractions must still have non-negative nanos values
78 // that count forward in time. Must be from 0 to 999,999,999
79 // inclusive.
80 Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"`
81}
82
83func (m *Timestamp) Reset() { *m = Timestamp{} }
84func (m *Timestamp) String() string { return proto.CompactTextString(m) }
85func (*Timestamp) ProtoMessage() {}
86func (*Timestamp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
87
88func (m *Timestamp) GetSeconds() int64 {
89 if m != nil {
90 return m.Seconds
91 }
92 return 0
93}
94
95func (m *Timestamp) GetNanos() int32 {
96 if m != nil {
97 return m.Nanos
98 }
99 return 0
100}
101
102type LoadBalanceRequest struct {
103 // Types that are valid to be assigned to LoadBalanceRequestType:
104 // *LoadBalanceRequest_InitialRequest
105 // *LoadBalanceRequest_ClientStats
106 LoadBalanceRequestType isLoadBalanceRequest_LoadBalanceRequestType `protobuf_oneof:"load_balance_request_type"`
107}
108
109func (m *LoadBalanceRequest) Reset() { *m = LoadBalanceRequest{} }
110func (m *LoadBalanceRequest) String() string { return proto.CompactTextString(m) }
111func (*LoadBalanceRequest) ProtoMessage() {}
112func (*LoadBalanceRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
113
114type isLoadBalanceRequest_LoadBalanceRequestType interface {
115 isLoadBalanceRequest_LoadBalanceRequestType()
116}
117
118type LoadBalanceRequest_InitialRequest struct {
119 InitialRequest *InitialLoadBalanceRequest `protobuf:"bytes,1,opt,name=initial_request,json=initialRequest,oneof"`
120}
121type LoadBalanceRequest_ClientStats struct {
122 ClientStats *ClientStats `protobuf:"bytes,2,opt,name=client_stats,json=clientStats,oneof"`
123}
124
125func (*LoadBalanceRequest_InitialRequest) isLoadBalanceRequest_LoadBalanceRequestType() {}
126func (*LoadBalanceRequest_ClientStats) isLoadBalanceRequest_LoadBalanceRequestType() {}
127
128func (m *LoadBalanceRequest) GetLoadBalanceRequestType() isLoadBalanceRequest_LoadBalanceRequestType {
129 if m != nil {
130 return m.LoadBalanceRequestType
131 }
132 return nil
133}
134
135func (m *LoadBalanceRequest) GetInitialRequest() *InitialLoadBalanceRequest {
136 if x, ok := m.GetLoadBalanceRequestType().(*LoadBalanceRequest_InitialRequest); ok {
137 return x.InitialRequest
138 }
139 return nil
140}
141
142func (m *LoadBalanceRequest) GetClientStats() *ClientStats {
143 if x, ok := m.GetLoadBalanceRequestType().(*LoadBalanceRequest_ClientStats); ok {
144 return x.ClientStats
145 }
146 return nil
147}
148
149// XXX_OneofFuncs is for the internal use of the proto package.
150func (*LoadBalanceRequest) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
151 return _LoadBalanceRequest_OneofMarshaler, _LoadBalanceRequest_OneofUnmarshaler, _LoadBalanceRequest_OneofSizer, []interface{}{
152 (*LoadBalanceRequest_InitialRequest)(nil),
153 (*LoadBalanceRequest_ClientStats)(nil),
154 }
155}
156
157func _LoadBalanceRequest_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
158 m := msg.(*LoadBalanceRequest)
159 // load_balance_request_type
160 switch x := m.LoadBalanceRequestType.(type) {
161 case *LoadBalanceRequest_InitialRequest:
162 b.EncodeVarint(1<<3 | proto.WireBytes)
163 if err := b.EncodeMessage(x.InitialRequest); err != nil {
164 return err
165 }
166 case *LoadBalanceRequest_ClientStats:
167 b.EncodeVarint(2<<3 | proto.WireBytes)
168 if err := b.EncodeMessage(x.ClientStats); err != nil {
169 return err
170 }
171 case nil:
172 default:
173 return fmt.Errorf("LoadBalanceRequest.LoadBalanceRequestType has unexpected type %T", x)
174 }
175 return nil
176}
177
178func _LoadBalanceRequest_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
179 m := msg.(*LoadBalanceRequest)
180 switch tag {
181 case 1: // load_balance_request_type.initial_request
182 if wire != proto.WireBytes {
183 return true, proto.ErrInternalBadWireType
184 }
185 msg := new(InitialLoadBalanceRequest)
186 err := b.DecodeMessage(msg)
187 m.LoadBalanceRequestType = &LoadBalanceRequest_InitialRequest{msg}
188 return true, err
189 case 2: // load_balance_request_type.client_stats
190 if wire != proto.WireBytes {
191 return true, proto.ErrInternalBadWireType
192 }
193 msg := new(ClientStats)
194 err := b.DecodeMessage(msg)
195 m.LoadBalanceRequestType = &LoadBalanceRequest_ClientStats{msg}
196 return true, err
197 default:
198 return false, nil
199 }
200}
201
202func _LoadBalanceRequest_OneofSizer(msg proto.Message) (n int) {
203 m := msg.(*LoadBalanceRequest)
204 // load_balance_request_type
205 switch x := m.LoadBalanceRequestType.(type) {
206 case *LoadBalanceRequest_InitialRequest:
207 s := proto.Size(x.InitialRequest)
208 n += proto.SizeVarint(1<<3 | proto.WireBytes)
209 n += proto.SizeVarint(uint64(s))
210 n += s
211 case *LoadBalanceRequest_ClientStats:
212 s := proto.Size(x.ClientStats)
213 n += proto.SizeVarint(2<<3 | proto.WireBytes)
214 n += proto.SizeVarint(uint64(s))
215 n += s
216 case nil:
217 default:
218 panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
219 }
220 return n
221}
222
223type InitialLoadBalanceRequest struct {
224 // Name of load balanced service (IE, balancer.service.com)
225 // length should be less than 256 bytes.
226 Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
227}
228
229func (m *InitialLoadBalanceRequest) Reset() { *m = InitialLoadBalanceRequest{} }
230func (m *InitialLoadBalanceRequest) String() string { return proto.CompactTextString(m) }
231func (*InitialLoadBalanceRequest) ProtoMessage() {}
232func (*InitialLoadBalanceRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
233
234func (m *InitialLoadBalanceRequest) GetName() string {
235 if m != nil {
236 return m.Name
237 }
238 return ""
239}
240
241// Contains client level statistics that are useful to load balancing. Each
242// count except the timestamp should be reset to zero after reporting the stats.
243type ClientStats struct {
244 // The timestamp of generating the report.
245 Timestamp *Timestamp `protobuf:"bytes,1,opt,name=timestamp" json:"timestamp,omitempty"`
246 // The total number of RPCs that started.
247 NumCallsStarted int64 `protobuf:"varint,2,opt,name=num_calls_started,json=numCallsStarted" json:"num_calls_started,omitempty"`
248 // The total number of RPCs that finished.
249 NumCallsFinished int64 `protobuf:"varint,3,opt,name=num_calls_finished,json=numCallsFinished" json:"num_calls_finished,omitempty"`
250 // The total number of RPCs that were dropped by the client because of rate
251 // limiting.
252 NumCallsFinishedWithDropForRateLimiting int64 `protobuf:"varint,4,opt,name=num_calls_finished_with_drop_for_rate_limiting,json=numCallsFinishedWithDropForRateLimiting" json:"num_calls_finished_with_drop_for_rate_limiting,omitempty"`
253 // The total number of RPCs that were dropped by the client because of load
254 // balancing.
255 NumCallsFinishedWithDropForLoadBalancing int64 `protobuf:"varint,5,opt,name=num_calls_finished_with_drop_for_load_balancing,json=numCallsFinishedWithDropForLoadBalancing" json:"num_calls_finished_with_drop_for_load_balancing,omitempty"`
256 // The total number of RPCs that failed to reach a server except dropped RPCs.
257 NumCallsFinishedWithClientFailedToSend int64 `protobuf:"varint,6,opt,name=num_calls_finished_with_client_failed_to_send,json=numCallsFinishedWithClientFailedToSend" json:"num_calls_finished_with_client_failed_to_send,omitempty"`
258 // The total number of RPCs that finished and are known to have been received
259 // by a server.
260 NumCallsFinishedKnownReceived int64 `protobuf:"varint,7,opt,name=num_calls_finished_known_received,json=numCallsFinishedKnownReceived" json:"num_calls_finished_known_received,omitempty"`
261}
262
263func (m *ClientStats) Reset() { *m = ClientStats{} }
264func (m *ClientStats) String() string { return proto.CompactTextString(m) }
265func (*ClientStats) ProtoMessage() {}
266func (*ClientStats) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
267
268func (m *ClientStats) GetTimestamp() *Timestamp {
269 if m != nil {
270 return m.Timestamp
271 }
272 return nil
273}
274
275func (m *ClientStats) GetNumCallsStarted() int64 {
276 if m != nil {
277 return m.NumCallsStarted
278 }
279 return 0
280}
281
282func (m *ClientStats) GetNumCallsFinished() int64 {
283 if m != nil {
284 return m.NumCallsFinished
285 }
286 return 0
287}
288
289func (m *ClientStats) GetNumCallsFinishedWithDropForRateLimiting() int64 {
290 if m != nil {
291 return m.NumCallsFinishedWithDropForRateLimiting
292 }
293 return 0
294}
295
296func (m *ClientStats) GetNumCallsFinishedWithDropForLoadBalancing() int64 {
297 if m != nil {
298 return m.NumCallsFinishedWithDropForLoadBalancing
299 }
300 return 0
301}
302
303func (m *ClientStats) GetNumCallsFinishedWithClientFailedToSend() int64 {
304 if m != nil {
305 return m.NumCallsFinishedWithClientFailedToSend
306 }
307 return 0
308}
309
310func (m *ClientStats) GetNumCallsFinishedKnownReceived() int64 {
311 if m != nil {
312 return m.NumCallsFinishedKnownReceived
313 }
314 return 0
315}
316
317type LoadBalanceResponse struct {
318 // Types that are valid to be assigned to LoadBalanceResponseType:
319 // *LoadBalanceResponse_InitialResponse
320 // *LoadBalanceResponse_ServerList
321 LoadBalanceResponseType isLoadBalanceResponse_LoadBalanceResponseType `protobuf_oneof:"load_balance_response_type"`
322}
323
324func (m *LoadBalanceResponse) Reset() { *m = LoadBalanceResponse{} }
325func (m *LoadBalanceResponse) String() string { return proto.CompactTextString(m) }
326func (*LoadBalanceResponse) ProtoMessage() {}
327func (*LoadBalanceResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
328
329type isLoadBalanceResponse_LoadBalanceResponseType interface {
330 isLoadBalanceResponse_LoadBalanceResponseType()
331}
332
333type LoadBalanceResponse_InitialResponse struct {
334 InitialResponse *InitialLoadBalanceResponse `protobuf:"bytes,1,opt,name=initial_response,json=initialResponse,oneof"`
335}
336type LoadBalanceResponse_ServerList struct {
337 ServerList *ServerList `protobuf:"bytes,2,opt,name=server_list,json=serverList,oneof"`
338}
339
340func (*LoadBalanceResponse_InitialResponse) isLoadBalanceResponse_LoadBalanceResponseType() {}
341func (*LoadBalanceResponse_ServerList) isLoadBalanceResponse_LoadBalanceResponseType() {}
342
343func (m *LoadBalanceResponse) GetLoadBalanceResponseType() isLoadBalanceResponse_LoadBalanceResponseType {
344 if m != nil {
345 return m.LoadBalanceResponseType
346 }
347 return nil
348}
349
350func (m *LoadBalanceResponse) GetInitialResponse() *InitialLoadBalanceResponse {
351 if x, ok := m.GetLoadBalanceResponseType().(*LoadBalanceResponse_InitialResponse); ok {
352 return x.InitialResponse
353 }
354 return nil
355}
356
357func (m *LoadBalanceResponse) GetServerList() *ServerList {
358 if x, ok := m.GetLoadBalanceResponseType().(*LoadBalanceResponse_ServerList); ok {
359 return x.ServerList
360 }
361 return nil
362}
363
364// XXX_OneofFuncs is for the internal use of the proto package.
365func (*LoadBalanceResponse) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
366 return _LoadBalanceResponse_OneofMarshaler, _LoadBalanceResponse_OneofUnmarshaler, _LoadBalanceResponse_OneofSizer, []interface{}{
367 (*LoadBalanceResponse_InitialResponse)(nil),
368 (*LoadBalanceResponse_ServerList)(nil),
369 }
370}
371
372func _LoadBalanceResponse_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
373 m := msg.(*LoadBalanceResponse)
374 // load_balance_response_type
375 switch x := m.LoadBalanceResponseType.(type) {
376 case *LoadBalanceResponse_InitialResponse:
377 b.EncodeVarint(1<<3 | proto.WireBytes)
378 if err := b.EncodeMessage(x.InitialResponse); err != nil {
379 return err
380 }
381 case *LoadBalanceResponse_ServerList:
382 b.EncodeVarint(2<<3 | proto.WireBytes)
383 if err := b.EncodeMessage(x.ServerList); err != nil {
384 return err
385 }
386 case nil:
387 default:
388 return fmt.Errorf("LoadBalanceResponse.LoadBalanceResponseType has unexpected type %T", x)
389 }
390 return nil
391}
392
393func _LoadBalanceResponse_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
394 m := msg.(*LoadBalanceResponse)
395 switch tag {
396 case 1: // load_balance_response_type.initial_response
397 if wire != proto.WireBytes {
398 return true, proto.ErrInternalBadWireType
399 }
400 msg := new(InitialLoadBalanceResponse)
401 err := b.DecodeMessage(msg)
402 m.LoadBalanceResponseType = &LoadBalanceResponse_InitialResponse{msg}
403 return true, err
404 case 2: // load_balance_response_type.server_list
405 if wire != proto.WireBytes {
406 return true, proto.ErrInternalBadWireType
407 }
408 msg := new(ServerList)
409 err := b.DecodeMessage(msg)
410 m.LoadBalanceResponseType = &LoadBalanceResponse_ServerList{msg}
411 return true, err
412 default:
413 return false, nil
414 }
415}
416
417func _LoadBalanceResponse_OneofSizer(msg proto.Message) (n int) {
418 m := msg.(*LoadBalanceResponse)
419 // load_balance_response_type
420 switch x := m.LoadBalanceResponseType.(type) {
421 case *LoadBalanceResponse_InitialResponse:
422 s := proto.Size(x.InitialResponse)
423 n += proto.SizeVarint(1<<3 | proto.WireBytes)
424 n += proto.SizeVarint(uint64(s))
425 n += s
426 case *LoadBalanceResponse_ServerList:
427 s := proto.Size(x.ServerList)
428 n += proto.SizeVarint(2<<3 | proto.WireBytes)
429 n += proto.SizeVarint(uint64(s))
430 n += s
431 case nil:
432 default:
433 panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
434 }
435 return n
436}
437
438type InitialLoadBalanceResponse struct {
439 // This is an application layer redirect that indicates the client should use
440 // the specified server for load balancing. When this field is non-empty in
441 // the response, the client should open a separate connection to the
442 // load_balancer_delegate and call the BalanceLoad method. Its length should
443 // be less than 64 bytes.
444 LoadBalancerDelegate string `protobuf:"bytes,1,opt,name=load_balancer_delegate,json=loadBalancerDelegate" json:"load_balancer_delegate,omitempty"`
445 // This interval defines how often the client should send the client stats
446 // to the load balancer. Stats should only be reported when the duration is
447 // positive.
448 ClientStatsReportInterval *Duration `protobuf:"bytes,2,opt,name=client_stats_report_interval,json=clientStatsReportInterval" json:"client_stats_report_interval,omitempty"`
449}
450
451func (m *InitialLoadBalanceResponse) Reset() { *m = InitialLoadBalanceResponse{} }
452func (m *InitialLoadBalanceResponse) String() string { return proto.CompactTextString(m) }
453func (*InitialLoadBalanceResponse) ProtoMessage() {}
454func (*InitialLoadBalanceResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
455
456func (m *InitialLoadBalanceResponse) GetLoadBalancerDelegate() string {
457 if m != nil {
458 return m.LoadBalancerDelegate
459 }
460 return ""
461}
462
463func (m *InitialLoadBalanceResponse) GetClientStatsReportInterval() *Duration {
464 if m != nil {
465 return m.ClientStatsReportInterval
466 }
467 return nil
468}
469
470type ServerList struct {
471 // Contains a list of servers selected by the load balancer. The list will
472 // be updated when server resolutions change or as needed to balance load
473 // across more servers. The client should consume the server list in order
474 // unless instructed otherwise via the client_config.
475 Servers []*Server `protobuf:"bytes,1,rep,name=servers" json:"servers,omitempty"`
476 // Indicates the amount of time that the client should consider this server
477 // list as valid. It may be considered stale after waiting this interval of
478 // time after receiving the list. If the interval is not positive, the
479 // client can assume the list is valid until the next list is received.
480 ExpirationInterval *Duration `protobuf:"bytes,3,opt,name=expiration_interval,json=expirationInterval" json:"expiration_interval,omitempty"`
481}
482
483func (m *ServerList) Reset() { *m = ServerList{} }
484func (m *ServerList) String() string { return proto.CompactTextString(m) }
485func (*ServerList) ProtoMessage() {}
486func (*ServerList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
487
488func (m *ServerList) GetServers() []*Server {
489 if m != nil {
490 return m.Servers
491 }
492 return nil
493}
494
495func (m *ServerList) GetExpirationInterval() *Duration {
496 if m != nil {
497 return m.ExpirationInterval
498 }
499 return nil
500}
501
502// Contains server information. When none of the [drop_for_*] fields are true,
503// use the other fields. When drop_for_rate_limiting is true, ignore all other
504// fields. Use drop_for_load_balancing only when it is true and
505// drop_for_rate_limiting is false.
506type Server struct {
507 // A resolved address for the server, serialized in network-byte-order. It may
508 // either be an IPv4 or IPv6 address.
509 IpAddress []byte `protobuf:"bytes,1,opt,name=ip_address,json=ipAddress,proto3" json:"ip_address,omitempty"`
510 // A resolved port number for the server.
511 Port int32 `protobuf:"varint,2,opt,name=port" json:"port,omitempty"`
512 // An opaque but printable token given to the frontend for each pick. All
513 // frontend requests for that pick must include the token in its initial
514 // metadata. The token is used by the backend to verify the request and to
515 // allow the backend to report load to the gRPC LB system.
516 //
517 // Its length is variable but less than 50 bytes.
518 LoadBalanceToken string `protobuf:"bytes,3,opt,name=load_balance_token,json=loadBalanceToken" json:"load_balance_token,omitempty"`
519 // Indicates whether this particular request should be dropped by the client
520 // for rate limiting.
521 DropForRateLimiting bool `protobuf:"varint,4,opt,name=drop_for_rate_limiting,json=dropForRateLimiting" json:"drop_for_rate_limiting,omitempty"`
522 // Indicates whether this particular request should be dropped by the client
523 // for load balancing.
524 DropForLoadBalancing bool `protobuf:"varint,5,opt,name=drop_for_load_balancing,json=dropForLoadBalancing" json:"drop_for_load_balancing,omitempty"`
525}
526
527func (m *Server) Reset() { *m = Server{} }
528func (m *Server) String() string { return proto.CompactTextString(m) }
529func (*Server) ProtoMessage() {}
530func (*Server) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
531
532func (m *Server) GetIpAddress() []byte {
533 if m != nil {
534 return m.IpAddress
535 }
536 return nil
537}
538
539func (m *Server) GetPort() int32 {
540 if m != nil {
541 return m.Port
542 }
543 return 0
544}
545
546func (m *Server) GetLoadBalanceToken() string {
547 if m != nil {
548 return m.LoadBalanceToken
549 }
550 return ""
551}
552
553func (m *Server) GetDropForRateLimiting() bool {
554 if m != nil {
555 return m.DropForRateLimiting
556 }
557 return false
558}
559
560func (m *Server) GetDropForLoadBalancing() bool {
561 if m != nil {
562 return m.DropForLoadBalancing
563 }
564 return false
565}
566
567func init() {
568 proto.RegisterType((*Duration)(nil), "grpc.lb.v1.Duration")
569 proto.RegisterType((*Timestamp)(nil), "grpc.lb.v1.Timestamp")
570 proto.RegisterType((*LoadBalanceRequest)(nil), "grpc.lb.v1.LoadBalanceRequest")
571 proto.RegisterType((*InitialLoadBalanceRequest)(nil), "grpc.lb.v1.InitialLoadBalanceRequest")
572 proto.RegisterType((*ClientStats)(nil), "grpc.lb.v1.ClientStats")
573 proto.RegisterType((*LoadBalanceResponse)(nil), "grpc.lb.v1.LoadBalanceResponse")
574 proto.RegisterType((*InitialLoadBalanceResponse)(nil), "grpc.lb.v1.InitialLoadBalanceResponse")
575 proto.RegisterType((*ServerList)(nil), "grpc.lb.v1.ServerList")
576 proto.RegisterType((*Server)(nil), "grpc.lb.v1.Server")
577}
578
579func init() { proto.RegisterFile("grpclb.proto", fileDescriptor0) }
580
581var fileDescriptor0 = []byte{
582 // 733 bytes of a gzipped FileDescriptorProto
583 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x55, 0xdd, 0x4e, 0x1b, 0x39,
584 0x14, 0x66, 0x36, 0xfc, 0xe5, 0x24, 0x5a, 0x58, 0x93, 0x85, 0xc0, 0xc2, 0x2e, 0x1b, 0xa9, 0x34,
585 0xaa, 0x68, 0x68, 0x43, 0x7b, 0xd1, 0x9f, 0x9b, 0x02, 0x45, 0x41, 0xe5, 0xa2, 0x72, 0xa8, 0x7a,
586 0x55, 0x59, 0x4e, 0xc6, 0x80, 0xc5, 0xc4, 0x9e, 0xda, 0x4e, 0x68, 0x2f, 0x7b, 0xd9, 0x47, 0xe9,
587 0x63, 0x54, 0x7d, 0x86, 0xbe, 0x4f, 0x65, 0x7b, 0x26, 0x33, 0x90, 0x1f, 0xd4, 0xbb, 0xf1, 0xf1,
588 0x77, 0xbe, 0xf3, 0xf9, 0xd8, 0xdf, 0x19, 0x28, 0x5f, 0xa8, 0xb8, 0x1b, 0x75, 0x1a, 0xb1, 0x92,
589 0x46, 0x22, 0xb0, 0xab, 0x46, 0xd4, 0x69, 0x0c, 0x1e, 0xd7, 0x9e, 0xc3, 0xe2, 0x51, 0x5f, 0x51,
590 0xc3, 0xa5, 0x40, 0x55, 0x58, 0xd0, 0xac, 0x2b, 0x45, 0xa8, 0xab, 0xc1, 0x76, 0x50, 0x2f, 0xe0,
591 0x74, 0x89, 0x2a, 0x30, 0x27, 0xa8, 0x90, 0xba, 0xfa, 0xc7, 0x76, 0x50, 0x9f, 0xc3, 0x7e, 0x51,
592 0x7b, 0x01, 0xc5, 0x33, 0xde, 0x63, 0xda, 0xd0, 0x5e, 0xfc, 0xdb, 0xc9, 0xdf, 0x03, 0x40, 0xa7,
593 0x92, 0x86, 0x07, 0x34, 0xa2, 0xa2, 0xcb, 0x30, 0xfb, 0xd8, 0x67, 0xda, 0xa0, 0xb7, 0xb0, 0xc4,
594 0x05, 0x37, 0x9c, 0x46, 0x44, 0xf9, 0x90, 0xa3, 0x2b, 0x35, 0xef, 0x35, 0x32, 0xd5, 0x8d, 0x13,
595 0x0f, 0x19, 0xcd, 0x6f, 0xcd, 0xe0, 0x3f, 0x93, 0xfc, 0x94, 0xf1, 0x25, 0x94, 0xbb, 0x11, 0x67,
596 0xc2, 0x10, 0x6d, 0xa8, 0xf1, 0x2a, 0x4a, 0xcd, 0xb5, 0x3c, 0xdd, 0xa1, 0xdb, 0x6f, 0xdb, 0xed,
597 0xd6, 0x0c, 0x2e, 0x75, 0xb3, 0xe5, 0xc1, 0x3f, 0xb0, 0x1e, 0x49, 0x1a, 0x92, 0x8e, 0x2f, 0x93,
598 0x8a, 0x22, 0xe6, 0x73, 0xcc, 0x6a, 0x7b, 0xb0, 0x3e, 0x51, 0x09, 0x42, 0x30, 0x2b, 0x68, 0x8f,
599 0x39, 0xf9, 0x45, 0xec, 0xbe, 0x6b, 0x5f, 0x67, 0xa1, 0x94, 0x2b, 0x86, 0xf6, 0xa1, 0x68, 0xd2,
600 0x0e, 0x26, 0xe7, 0xfc, 0x3b, 0x2f, 0x6c, 0xd8, 0x5e, 0x9c, 0xe1, 0xd0, 0x03, 0xf8, 0x4b, 0xf4,
601 0x7b, 0xa4, 0x4b, 0xa3, 0x48, 0xdb, 0x33, 0x29, 0xc3, 0x42, 0x77, 0xaa, 0x02, 0x5e, 0x12, 0xfd,
602 0xde, 0xa1, 0x8d, 0xb7, 0x7d, 0x18, 0xed, 0x02, 0xca, 0xb0, 0xe7, 0x5c, 0x70, 0x7d, 0xc9, 0xc2,
603 0x6a, 0xc1, 0x81, 0x97, 0x53, 0xf0, 0x71, 0x12, 0x47, 0x04, 0x1a, 0xa3, 0x68, 0x72, 0xcd, 0xcd,
604 0x25, 0x09, 0x95, 0x8c, 0xc9, 0xb9, 0x54, 0x44, 0x51, 0xc3, 0x48, 0xc4, 0x7b, 0xdc, 0x70, 0x71,
605 0x51, 0x9d, 0x75, 0x4c, 0xf7, 0x6f, 0x33, 0xbd, 0xe7, 0xe6, 0xf2, 0x48, 0xc9, 0xf8, 0x58, 0x2a,
606 0x4c, 0x0d, 0x3b, 0x4d, 0xe0, 0x88, 0xc2, 0xde, 0x9d, 0x05, 0x72, 0xed, 0xb6, 0x15, 0xe6, 0x5c,
607 0x85, 0xfa, 0x94, 0x0a, 0x59, 0xef, 0x6d, 0x89, 0x0f, 0xf0, 0x70, 0x52, 0x89, 0xe4, 0x19, 0x9c,
608 0x53, 0x1e, 0xb1, 0x90, 0x18, 0x49, 0x34, 0x13, 0x61, 0x75, 0xde, 0x15, 0xd8, 0x19, 0x57, 0xc0,
609 0x5f, 0xd5, 0xb1, 0xc3, 0x9f, 0xc9, 0x36, 0x13, 0x21, 0x6a, 0xc1, 0xff, 0x63, 0xe8, 0xaf, 0x84,
610 0xbc, 0x16, 0x44, 0xb1, 0x2e, 0xe3, 0x03, 0x16, 0x56, 0x17, 0x1c, 0xe5, 0xd6, 0x6d, 0xca, 0x37,
611 0x16, 0x85, 0x13, 0x50, 0xed, 0x47, 0x00, 0x2b, 0x37, 0x9e, 0x8d, 0x8e, 0xa5, 0xd0, 0x0c, 0xb5,
612 0x61, 0x39, 0x73, 0x80, 0x8f, 0x25, 0x4f, 0x63, 0xe7, 0x2e, 0x0b, 0x78, 0x74, 0x6b, 0x06, 0x2f,
613 0x0d, 0x3d, 0x90, 0x90, 0x3e, 0x83, 0x92, 0x66, 0x6a, 0xc0, 0x14, 0x89, 0xb8, 0x36, 0x89, 0x07,
614 0x56, 0xf3, 0x7c, 0x6d, 0xb7, 0x7d, 0xca, 0x9d, 0x87, 0x40, 0x0f, 0x57, 0x07, 0x9b, 0xb0, 0x71,
615 0xcb, 0x01, 0x9e, 0xd3, 0x5b, 0xe0, 0x5b, 0x00, 0x1b, 0x93, 0xa5, 0xa0, 0x27, 0xb0, 0x9a, 0x4f,
616 0x56, 0x24, 0x64, 0x11, 0xbb, 0xa0, 0x26, 0xb5, 0x45, 0x25, 0xca, 0x92, 0xd4, 0x51, 0xb2, 0x87,
617 0xde, 0xc1, 0x66, 0xde, 0xb2, 0x44, 0xb1, 0x58, 0x2a, 0x43, 0xb8, 0x30, 0x4c, 0x0d, 0x68, 0x94,
618 0xc8, 0xaf, 0xe4, 0xe5, 0xa7, 0x43, 0x0c, 0xaf, 0xe7, 0xdc, 0x8b, 0x5d, 0xde, 0x49, 0x92, 0x56,
619 0xfb, 0x12, 0x00, 0x64, 0xc7, 0x44, 0xbb, 0x76, 0x62, 0xd9, 0x95, 0x9d, 0x58, 0x85, 0x7a, 0xa9,
620 0x89, 0x46, 0xfb, 0x81, 0x53, 0x08, 0x7a, 0x0d, 0x2b, 0xec, 0x53, 0xcc, 0x7d, 0x95, 0x4c, 0x4a,
621 0x61, 0x8a, 0x14, 0x94, 0x25, 0x0c, 0x35, 0xfc, 0x0c, 0x60, 0xde, 0x53, 0xa3, 0x2d, 0x00, 0x1e,
622 0x13, 0x1a, 0x86, 0x8a, 0x69, 0x3f, 0x34, 0xcb, 0xb8, 0xc8, 0xe3, 0x57, 0x3e, 0x60, 0xe7, 0x87,
623 0x55, 0x9f, 0x4c, 0x4d, 0xf7, 0x6d, 0xed, 0x7c, 0xe3, 0x2e, 0x8c, 0xbc, 0x62, 0xc2, 0x69, 0x28,
624 0xe2, 0xe5, 0x5c, 0x2b, 0xcf, 0x6c, 0x1c, 0xed, 0xc3, 0xea, 0x14, 0xdb, 0x2e, 0xe2, 0x95, 0x70,
625 0x8c, 0x45, 0x9f, 0xc2, 0xda, 0x34, 0x2b, 0x2e, 0xe2, 0x4a, 0x38, 0xc6, 0x76, 0xcd, 0x0e, 0x94,
626 0x73, 0xf7, 0xaf, 0x10, 0x86, 0x52, 0xf2, 0x6d, 0xc3, 0xe8, 0xdf, 0x7c, 0x83, 0x46, 0x87, 0xe5,
627 0xc6, 0x7f, 0x13, 0xf7, 0xfd, 0x43, 0xaa, 0x07, 0x8f, 0x82, 0xce, 0xbc, 0xfb, 0x7d, 0xed, 0xff,
628 0x0a, 0x00, 0x00, 0xff, 0xff, 0x64, 0xbf, 0xda, 0x5e, 0xce, 0x06, 0x00, 0x00,
629}
diff --git a/vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/grpclb.proto b/vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/grpclb.proto
deleted file mode 100644
index b13b343..0000000
--- a/vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/grpclb.proto
+++ /dev/null
@@ -1,164 +0,0 @@
1// Copyright 2016 gRPC authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15syntax = "proto3";
16
17package grpc.lb.v1;
18
19message Duration {
20 // Signed seconds of the span of time. Must be from -315,576,000,000
21 // to +315,576,000,000 inclusive.
22 int64 seconds = 1;
23
24 // Signed fractions of a second at nanosecond resolution of the span
25 // of time. Durations less than one second are represented with a 0
26 // `seconds` field and a positive or negative `nanos` field. For durations
27 // of one second or more, a non-zero value for the `nanos` field must be
28 // of the same sign as the `seconds` field. Must be from -999,999,999
29 // to +999,999,999 inclusive.
30 int32 nanos = 2;
31}
32
33message Timestamp {
34
35 // Represents seconds of UTC time since Unix epoch
36 // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
37 // 9999-12-31T23:59:59Z inclusive.
38 int64 seconds = 1;
39
40 // Non-negative fractions of a second at nanosecond resolution. Negative
41 // second values with fractions must still have non-negative nanos values
42 // that count forward in time. Must be from 0 to 999,999,999
43 // inclusive.
44 int32 nanos = 2;
45}
46
47service LoadBalancer {
48 // Bidirectional rpc to get a list of servers.
49 rpc BalanceLoad(stream LoadBalanceRequest)
50 returns (stream LoadBalanceResponse);
51}
52
53message LoadBalanceRequest {
54 oneof load_balance_request_type {
55 // This message should be sent on the first request to the load balancer.
56 InitialLoadBalanceRequest initial_request = 1;
57
58 // The client stats should be periodically reported to the load balancer
59 // based on the duration defined in the InitialLoadBalanceResponse.
60 ClientStats client_stats = 2;
61 }
62}
63
64message InitialLoadBalanceRequest {
65 // Name of load balanced service (IE, balancer.service.com)
66 // length should be less than 256 bytes.
67 string name = 1;
68}
69
70// Contains client level statistics that are useful to load balancing. Each
71// count except the timestamp should be reset to zero after reporting the stats.
72message ClientStats {
73 // The timestamp of generating the report.
74 Timestamp timestamp = 1;
75
76 // The total number of RPCs that started.
77 int64 num_calls_started = 2;
78
79 // The total number of RPCs that finished.
80 int64 num_calls_finished = 3;
81
82 // The total number of RPCs that were dropped by the client because of rate
83 // limiting.
84 int64 num_calls_finished_with_drop_for_rate_limiting = 4;
85
86 // The total number of RPCs that were dropped by the client because of load
87 // balancing.
88 int64 num_calls_finished_with_drop_for_load_balancing = 5;
89
90 // The total number of RPCs that failed to reach a server except dropped RPCs.
91 int64 num_calls_finished_with_client_failed_to_send = 6;
92
93 // The total number of RPCs that finished and are known to have been received
94 // by a server.
95 int64 num_calls_finished_known_received = 7;
96}
97
98message LoadBalanceResponse {
99 oneof load_balance_response_type {
100 // This message should be sent on the first response to the client.
101 InitialLoadBalanceResponse initial_response = 1;
102
103 // Contains the list of servers selected by the load balancer. The client
104 // should send requests to these servers in the specified order.
105 ServerList server_list = 2;
106 }
107}
108
109message InitialLoadBalanceResponse {
110 // This is an application layer redirect that indicates the client should use
111 // the specified server for load balancing. When this field is non-empty in
112 // the response, the client should open a separate connection to the
113 // load_balancer_delegate and call the BalanceLoad method. Its length should
114 // be less than 64 bytes.
115 string load_balancer_delegate = 1;
116
117 // This interval defines how often the client should send the client stats
118 // to the load balancer. Stats should only be reported when the duration is
119 // positive.
120 Duration client_stats_report_interval = 2;
121}
122
123message ServerList {
124 // Contains a list of servers selected by the load balancer. The list will
125 // be updated when server resolutions change or as needed to balance load
126 // across more servers. The client should consume the server list in order
127 // unless instructed otherwise via the client_config.
128 repeated Server servers = 1;
129
130 // Indicates the amount of time that the client should consider this server
131 // list as valid. It may be considered stale after waiting this interval of
132 // time after receiving the list. If the interval is not positive, the
133 // client can assume the list is valid until the next list is received.
134 Duration expiration_interval = 3;
135}
136
137// Contains server information. When none of the [drop_for_*] fields are true,
138// use the other fields. When drop_for_rate_limiting is true, ignore all other
139// fields. Use drop_for_load_balancing only when it is true and
140// drop_for_rate_limiting is false.
141message Server {
142 // A resolved address for the server, serialized in network-byte-order. It may
143 // either be an IPv4 or IPv6 address.
144 bytes ip_address = 1;
145
146 // A resolved port number for the server.
147 int32 port = 2;
148
149 // An opaque but printable token given to the frontend for each pick. All
150 // frontend requests for that pick must include the token in its initial
151 // metadata. The token is used by the backend to verify the request and to
152 // allow the backend to report load to the gRPC LB system.
153 //
154 // Its length is variable but less than 50 bytes.
155 string load_balance_token = 3;
156
157 // Indicates whether this particular request should be dropped by the client
158 // for rate limiting.
159 bool drop_for_rate_limiting = 4;
160
161 // Indicates whether this particular request should be dropped by the client
162 // for load balancing.
163 bool drop_for_load_balancing = 5;
164}
diff --git a/vendor/google.golang.org/grpc/grpclog/grpclog.go b/vendor/google.golang.org/grpc/grpclog/grpclog.go
index 16a7d88..1fabb11 100644
--- a/vendor/google.golang.org/grpc/grpclog/grpclog.go
+++ b/vendor/google.golang.org/grpc/grpclog/grpclog.go
@@ -105,18 +105,21 @@ func Fatalln(args ...interface{}) {
105} 105}
106 106
107// Print prints to the logger. Arguments are handled in the manner of fmt.Print. 107// Print prints to the logger. Arguments are handled in the manner of fmt.Print.
108//
108// Deprecated: use Info. 109// Deprecated: use Info.
109func Print(args ...interface{}) { 110func Print(args ...interface{}) {
110 logger.Info(args...) 111 logger.Info(args...)
111} 112}
112 113
113// Printf prints to the logger. Arguments are handled in the manner of fmt.Printf. 114// Printf prints to the logger. Arguments are handled in the manner of fmt.Printf.
115//
114// Deprecated: use Infof. 116// Deprecated: use Infof.
115func Printf(format string, args ...interface{}) { 117func Printf(format string, args ...interface{}) {
116 logger.Infof(format, args...) 118 logger.Infof(format, args...)
117} 119}
118 120
119// Println prints to the logger. Arguments are handled in the manner of fmt.Println. 121// Println prints to the logger. Arguments are handled in the manner of fmt.Println.
122//
120// Deprecated: use Infoln. 123// Deprecated: use Infoln.
121func Println(args ...interface{}) { 124func Println(args ...interface{}) {
122 logger.Infoln(args...) 125 logger.Infoln(args...)
diff --git a/vendor/google.golang.org/grpc/grpclog/logger.go b/vendor/google.golang.org/grpc/grpclog/logger.go
index d03b239..097494f 100644
--- a/vendor/google.golang.org/grpc/grpclog/logger.go
+++ b/vendor/google.golang.org/grpc/grpclog/logger.go
@@ -19,6 +19,7 @@
19package grpclog 19package grpclog
20 20
21// Logger mimics golang's standard Logger as an interface. 21// Logger mimics golang's standard Logger as an interface.
22//
22// Deprecated: use LoggerV2. 23// Deprecated: use LoggerV2.
23type Logger interface { 24type Logger interface {
24 Fatal(args ...interface{}) 25 Fatal(args ...interface{})
@@ -31,6 +32,7 @@ type Logger interface {
31 32
32// SetLogger sets the logger that is used in grpc. Call only from 33// SetLogger sets the logger that is used in grpc. Call only from
33// init() functions. 34// init() functions.
35//
34// Deprecated: use SetLoggerV2. 36// Deprecated: use SetLoggerV2.
35func SetLogger(l Logger) { 37func SetLogger(l Logger) {
36 logger = &loggerWrapper{Logger: l} 38 logger = &loggerWrapper{Logger: l}
diff --git a/vendor/google.golang.org/grpc/health/client.go b/vendor/google.golang.org/grpc/health/client.go
new file mode 100644
index 0000000..e15f04c
--- /dev/null
+++ b/vendor/google.golang.org/grpc/health/client.go
@@ -0,0 +1,107 @@
1/*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package health
20
21import (
22 "context"
23 "fmt"
24 "io"
25 "time"
26
27 "google.golang.org/grpc"
28 "google.golang.org/grpc/codes"
29 healthpb "google.golang.org/grpc/health/grpc_health_v1"
30 "google.golang.org/grpc/internal"
31 "google.golang.org/grpc/internal/backoff"
32 "google.golang.org/grpc/status"
33)
34
35const maxDelay = 120 * time.Second
36
37var backoffStrategy = backoff.Exponential{MaxDelay: maxDelay}
38var backoffFunc = func(ctx context.Context, retries int) bool {
39 d := backoffStrategy.Backoff(retries)
40 timer := time.NewTimer(d)
41 select {
42 case <-timer.C:
43 return true
44 case <-ctx.Done():
45 timer.Stop()
46 return false
47 }
48}
49
50func init() {
51 internal.HealthCheckFunc = clientHealthCheck
52}
53
54func clientHealthCheck(ctx context.Context, newStream func() (interface{}, error), reportHealth func(bool), service string) error {
55 tryCnt := 0
56
57retryConnection:
58 for {
59 // Backs off if the connection has failed in some way without receiving a message in the previous retry.
60 if tryCnt > 0 && !backoffFunc(ctx, tryCnt-1) {
61 return nil
62 }
63 tryCnt++
64
65 if ctx.Err() != nil {
66 return nil
67 }
68 rawS, err := newStream()
69 if err != nil {
70 continue retryConnection
71 }
72
73 s, ok := rawS.(grpc.ClientStream)
74 // Ideally, this should never happen. But if it happens, the server is marked as healthy for LBing purposes.
75 if !ok {
76 reportHealth(true)
77 return fmt.Errorf("newStream returned %v (type %T); want grpc.ClientStream", rawS, rawS)
78 }
79
80 if err = s.SendMsg(&healthpb.HealthCheckRequest{Service: service}); err != nil && err != io.EOF {
81 // Stream should have been closed, so we can safely continue to create a new stream.
82 continue retryConnection
83 }
84 s.CloseSend()
85
86 resp := new(healthpb.HealthCheckResponse)
87 for {
88 err = s.RecvMsg(resp)
89
90 // Reports healthy for the LBing purposes if health check is not implemented in the server.
91 if status.Code(err) == codes.Unimplemented {
92 reportHealth(true)
93 return err
94 }
95
96 // Reports unhealthy if server's Watch method gives an error other than UNIMPLEMENTED.
97 if err != nil {
98 reportHealth(false)
99 continue retryConnection
100 }
101
102 // As a message has been received, removes the need for backoff for the next retry by reseting the try count.
103 tryCnt = 0
104 reportHealth(resp.Status == healthpb.HealthCheckResponse_SERVING)
105 }
106 }
107}
diff --git a/vendor/google.golang.org/grpc/health/grpc_health_v1/health.pb.go b/vendor/google.golang.org/grpc/health/grpc_health_v1/health.pb.go
index 89c4d45..c2f2c77 100644
--- a/vendor/google.golang.org/grpc/health/grpc_health_v1/health.pb.go
+++ b/vendor/google.golang.org/grpc/health/grpc_health_v1/health.pb.go
@@ -1,18 +1,7 @@
1// Code generated by protoc-gen-go. 1// Code generated by protoc-gen-go. DO NOT EDIT.
2// source: health.proto 2// source: grpc/health/v1/health.proto
3// DO NOT EDIT!
4 3
5/* 4package grpc_health_v1 // import "google.golang.org/grpc/health/grpc_health_v1"
6Package grpc_health_v1 is a generated protocol buffer package.
7
8It is generated from these files:
9 health.proto
10
11It has these top-level messages:
12 HealthCheckRequest
13 HealthCheckResponse
14*/
15package grpc_health_v1
16 5
17import proto "github.com/golang/protobuf/proto" 6import proto "github.com/golang/protobuf/proto"
18import fmt "fmt" 7import fmt "fmt"
@@ -37,46 +26,107 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
37type HealthCheckResponse_ServingStatus int32 26type HealthCheckResponse_ServingStatus int32
38 27
39const ( 28const (
40 HealthCheckResponse_UNKNOWN HealthCheckResponse_ServingStatus = 0 29 HealthCheckResponse_UNKNOWN HealthCheckResponse_ServingStatus = 0
41 HealthCheckResponse_SERVING HealthCheckResponse_ServingStatus = 1 30 HealthCheckResponse_SERVING HealthCheckResponse_ServingStatus = 1
42 HealthCheckResponse_NOT_SERVING HealthCheckResponse_ServingStatus = 2 31 HealthCheckResponse_NOT_SERVING HealthCheckResponse_ServingStatus = 2
32 HealthCheckResponse_SERVICE_UNKNOWN HealthCheckResponse_ServingStatus = 3
43) 33)
44 34
45var HealthCheckResponse_ServingStatus_name = map[int32]string{ 35var HealthCheckResponse_ServingStatus_name = map[int32]string{
46 0: "UNKNOWN", 36 0: "UNKNOWN",
47 1: "SERVING", 37 1: "SERVING",
48 2: "NOT_SERVING", 38 2: "NOT_SERVING",
39 3: "SERVICE_UNKNOWN",
49} 40}
50var HealthCheckResponse_ServingStatus_value = map[string]int32{ 41var HealthCheckResponse_ServingStatus_value = map[string]int32{
51 "UNKNOWN": 0, 42 "UNKNOWN": 0,
52 "SERVING": 1, 43 "SERVING": 1,
53 "NOT_SERVING": 2, 44 "NOT_SERVING": 2,
45 "SERVICE_UNKNOWN": 3,
54} 46}
55 47
56func (x HealthCheckResponse_ServingStatus) String() string { 48func (x HealthCheckResponse_ServingStatus) String() string {
57 return proto.EnumName(HealthCheckResponse_ServingStatus_name, int32(x)) 49 return proto.EnumName(HealthCheckResponse_ServingStatus_name, int32(x))
58} 50}
59func (HealthCheckResponse_ServingStatus) EnumDescriptor() ([]byte, []int) { 51func (HealthCheckResponse_ServingStatus) EnumDescriptor() ([]byte, []int) {
60 return fileDescriptor0, []int{1, 0} 52 return fileDescriptor_health_6b1a06aa67f91efd, []int{1, 0}
61} 53}
62 54
63type HealthCheckRequest struct { 55type HealthCheckRequest struct {
64 Service string `protobuf:"bytes,1,opt,name=service" json:"service,omitempty"` 56 Service string `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"`
57 XXX_NoUnkeyedLiteral struct{} `json:"-"`
58 XXX_unrecognized []byte `json:"-"`
59 XXX_sizecache int32 `json:"-"`
60}
61
62func (m *HealthCheckRequest) Reset() { *m = HealthCheckRequest{} }
63func (m *HealthCheckRequest) String() string { return proto.CompactTextString(m) }
64func (*HealthCheckRequest) ProtoMessage() {}
65func (*HealthCheckRequest) Descriptor() ([]byte, []int) {
66 return fileDescriptor_health_6b1a06aa67f91efd, []int{0}
67}
68func (m *HealthCheckRequest) XXX_Unmarshal(b []byte) error {
69 return xxx_messageInfo_HealthCheckRequest.Unmarshal(m, b)
70}
71func (m *HealthCheckRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
72 return xxx_messageInfo_HealthCheckRequest.Marshal(b, m, deterministic)
73}
74func (dst *HealthCheckRequest) XXX_Merge(src proto.Message) {
75 xxx_messageInfo_HealthCheckRequest.Merge(dst, src)
76}
77func (m *HealthCheckRequest) XXX_Size() int {
78 return xxx_messageInfo_HealthCheckRequest.Size(m)
79}
80func (m *HealthCheckRequest) XXX_DiscardUnknown() {
81 xxx_messageInfo_HealthCheckRequest.DiscardUnknown(m)
65} 82}
66 83
67func (m *HealthCheckRequest) Reset() { *m = HealthCheckRequest{} } 84var xxx_messageInfo_HealthCheckRequest proto.InternalMessageInfo
68func (m *HealthCheckRequest) String() string { return proto.CompactTextString(m) } 85
69func (*HealthCheckRequest) ProtoMessage() {} 86func (m *HealthCheckRequest) GetService() string {
70func (*HealthCheckRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } 87 if m != nil {
88 return m.Service
89 }
90 return ""
91}
71 92
72type HealthCheckResponse struct { 93type HealthCheckResponse struct {
73 Status HealthCheckResponse_ServingStatus `protobuf:"varint,1,opt,name=status,enum=grpc.health.v1.HealthCheckResponse_ServingStatus" json:"status,omitempty"` 94 Status HealthCheckResponse_ServingStatus `protobuf:"varint,1,opt,name=status,proto3,enum=grpc.health.v1.HealthCheckResponse_ServingStatus" json:"status,omitempty"`
95 XXX_NoUnkeyedLiteral struct{} `json:"-"`
96 XXX_unrecognized []byte `json:"-"`
97 XXX_sizecache int32 `json:"-"`
74} 98}
75 99
76func (m *HealthCheckResponse) Reset() { *m = HealthCheckResponse{} } 100func (m *HealthCheckResponse) Reset() { *m = HealthCheckResponse{} }
77func (m *HealthCheckResponse) String() string { return proto.CompactTextString(m) } 101func (m *HealthCheckResponse) String() string { return proto.CompactTextString(m) }
78func (*HealthCheckResponse) ProtoMessage() {} 102func (*HealthCheckResponse) ProtoMessage() {}
79func (*HealthCheckResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } 103func (*HealthCheckResponse) Descriptor() ([]byte, []int) {
104 return fileDescriptor_health_6b1a06aa67f91efd, []int{1}
105}
106func (m *HealthCheckResponse) XXX_Unmarshal(b []byte) error {
107 return xxx_messageInfo_HealthCheckResponse.Unmarshal(m, b)
108}
109func (m *HealthCheckResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
110 return xxx_messageInfo_HealthCheckResponse.Marshal(b, m, deterministic)
111}
112func (dst *HealthCheckResponse) XXX_Merge(src proto.Message) {
113 xxx_messageInfo_HealthCheckResponse.Merge(dst, src)
114}
115func (m *HealthCheckResponse) XXX_Size() int {
116 return xxx_messageInfo_HealthCheckResponse.Size(m)
117}
118func (m *HealthCheckResponse) XXX_DiscardUnknown() {
119 xxx_messageInfo_HealthCheckResponse.DiscardUnknown(m)
120}
121
122var xxx_messageInfo_HealthCheckResponse proto.InternalMessageInfo
123
124func (m *HealthCheckResponse) GetStatus() HealthCheckResponse_ServingStatus {
125 if m != nil {
126 return m.Status
127 }
128 return HealthCheckResponse_UNKNOWN
129}
80 130
81func init() { 131func init() {
82 proto.RegisterType((*HealthCheckRequest)(nil), "grpc.health.v1.HealthCheckRequest") 132 proto.RegisterType((*HealthCheckRequest)(nil), "grpc.health.v1.HealthCheckRequest")
@@ -92,10 +142,29 @@ var _ grpc.ClientConn
92// is compatible with the grpc package it is being compiled against. 142// is compatible with the grpc package it is being compiled against.
93const _ = grpc.SupportPackageIsVersion4 143const _ = grpc.SupportPackageIsVersion4
94 144
95// Client API for Health service 145// HealthClient is the client API for Health service.
96 146//
147// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
97type HealthClient interface { 148type HealthClient interface {
149 // If the requested service is unknown, the call will fail with status
150 // NOT_FOUND.
98 Check(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) 151 Check(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error)
152 // Performs a watch for the serving status of the requested service.
153 // The server will immediately send back a message indicating the current
154 // serving status. It will then subsequently send a new message whenever
155 // the service's serving status changes.
156 //
157 // If the requested service is unknown when the call is received, the
158 // server will send a message setting the serving status to
159 // SERVICE_UNKNOWN but will *not* terminate the call. If at some
160 // future point, the serving status of the service becomes known, the
161 // server will send a new message with the service's serving status.
162 //
163 // If the call terminates with status UNIMPLEMENTED, then clients
164 // should assume this method is not supported and should not retry the
165 // call. If the call terminates with any other status (including OK),
166 // clients should retry the call with appropriate exponential backoff.
167 Watch(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (Health_WatchClient, error)
99} 168}
100 169
101type healthClient struct { 170type healthClient struct {
@@ -108,17 +177,66 @@ func NewHealthClient(cc *grpc.ClientConn) HealthClient {
108 177
109func (c *healthClient) Check(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) { 178func (c *healthClient) Check(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) {
110 out := new(HealthCheckResponse) 179 out := new(HealthCheckResponse)
111 err := grpc.Invoke(ctx, "/grpc.health.v1.Health/Check", in, out, c.cc, opts...) 180 err := c.cc.Invoke(ctx, "/grpc.health.v1.Health/Check", in, out, opts...)
112 if err != nil { 181 if err != nil {
113 return nil, err 182 return nil, err
114 } 183 }
115 return out, nil 184 return out, nil
116} 185}
117 186
118// Server API for Health service 187func (c *healthClient) Watch(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (Health_WatchClient, error) {
188 stream, err := c.cc.NewStream(ctx, &_Health_serviceDesc.Streams[0], "/grpc.health.v1.Health/Watch", opts...)
189 if err != nil {
190 return nil, err
191 }
192 x := &healthWatchClient{stream}
193 if err := x.ClientStream.SendMsg(in); err != nil {
194 return nil, err
195 }
196 if err := x.ClientStream.CloseSend(); err != nil {
197 return nil, err
198 }
199 return x, nil
200}
201
202type Health_WatchClient interface {
203 Recv() (*HealthCheckResponse, error)
204 grpc.ClientStream
205}
206
207type healthWatchClient struct {
208 grpc.ClientStream
209}
119 210
211func (x *healthWatchClient) Recv() (*HealthCheckResponse, error) {
212 m := new(HealthCheckResponse)
213 if err := x.ClientStream.RecvMsg(m); err != nil {
214 return nil, err
215 }
216 return m, nil
217}
218
219// HealthServer is the server API for Health service.
120type HealthServer interface { 220type HealthServer interface {
221 // If the requested service is unknown, the call will fail with status
222 // NOT_FOUND.
121 Check(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error) 223 Check(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error)
224 // Performs a watch for the serving status of the requested service.
225 // The server will immediately send back a message indicating the current
226 // serving status. It will then subsequently send a new message whenever
227 // the service's serving status changes.
228 //
229 // If the requested service is unknown when the call is received, the
230 // server will send a message setting the serving status to
231 // SERVICE_UNKNOWN but will *not* terminate the call. If at some
232 // future point, the serving status of the service becomes known, the
233 // server will send a new message with the service's serving status.
234 //
235 // If the call terminates with status UNIMPLEMENTED, then clients
236 // should assume this method is not supported and should not retry the
237 // call. If the call terminates with any other status (including OK),
238 // clients should retry the call with appropriate exponential backoff.
239 Watch(*HealthCheckRequest, Health_WatchServer) error
122} 240}
123 241
124func RegisterHealthServer(s *grpc.Server, srv HealthServer) { 242func RegisterHealthServer(s *grpc.Server, srv HealthServer) {
@@ -143,6 +261,27 @@ func _Health_Check_Handler(srv interface{}, ctx context.Context, dec func(interf
143 return interceptor(ctx, in, info, handler) 261 return interceptor(ctx, in, info, handler)
144} 262}
145 263
264func _Health_Watch_Handler(srv interface{}, stream grpc.ServerStream) error {
265 m := new(HealthCheckRequest)
266 if err := stream.RecvMsg(m); err != nil {
267 return err
268 }
269 return srv.(HealthServer).Watch(m, &healthWatchServer{stream})
270}
271
272type Health_WatchServer interface {
273 Send(*HealthCheckResponse) error
274 grpc.ServerStream
275}
276
277type healthWatchServer struct {
278 grpc.ServerStream
279}
280
281func (x *healthWatchServer) Send(m *HealthCheckResponse) error {
282 return x.ServerStream.SendMsg(m)
283}
284
146var _Health_serviceDesc = grpc.ServiceDesc{ 285var _Health_serviceDesc = grpc.ServiceDesc{
147 ServiceName: "grpc.health.v1.Health", 286 ServiceName: "grpc.health.v1.Health",
148 HandlerType: (*HealthServer)(nil), 287 HandlerType: (*HealthServer)(nil),
@@ -152,25 +291,37 @@ var _Health_serviceDesc = grpc.ServiceDesc{
152 Handler: _Health_Check_Handler, 291 Handler: _Health_Check_Handler,
153 }, 292 },
154 }, 293 },
155 Streams: []grpc.StreamDesc{}, 294 Streams: []grpc.StreamDesc{
156 Metadata: "health.proto", 295 {
157} 296 StreamName: "Watch",
158 297 Handler: _Health_Watch_Handler,
159func init() { proto.RegisterFile("health.proto", fileDescriptor0) } 298 ServerStreams: true,
160 299 },
161var fileDescriptor0 = []byte{ 300 },
162 // 204 bytes of a gzipped FileDescriptorProto 301 Metadata: "grpc/health/v1/health.proto",
163 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xc9, 0x48, 0x4d, 0xcc, 302}
164 0x29, 0xc9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x4b, 0x2f, 0x2a, 0x48, 0xd6, 0x83, 303
165 0x0a, 0x95, 0x19, 0x2a, 0xe9, 0x71, 0x09, 0x79, 0x80, 0x39, 0xce, 0x19, 0xa9, 0xc9, 0xd9, 0x41, 304func init() { proto.RegisterFile("grpc/health/v1/health.proto", fileDescriptor_health_6b1a06aa67f91efd) }
166 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x42, 0x12, 0x5c, 0xec, 0xc5, 0xa9, 0x45, 0x65, 0x99, 0xc9, 305
167 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x30, 0xae, 0xd2, 0x1c, 0x46, 0x2e, 0x61, 0x14, 306var fileDescriptor_health_6b1a06aa67f91efd = []byte{
168 0x0d, 0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x42, 0x9e, 0x5c, 0x6c, 0xc5, 0x25, 0x89, 0x25, 0xa5, 307 // 297 bytes of a gzipped FileDescriptorProto
169 0xc5, 0x60, 0x0d, 0x7c, 0x46, 0x86, 0x7a, 0xa8, 0x16, 0xe9, 0x61, 0xd1, 0xa4, 0x17, 0x0c, 0x32, 308 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4e, 0x2f, 0x2a, 0x48,
170 0x34, 0x2f, 0x3d, 0x18, 0xac, 0x31, 0x08, 0x6a, 0x80, 0x92, 0x15, 0x17, 0x2f, 0x8a, 0x84, 0x10, 309 0xd6, 0xcf, 0x48, 0x4d, 0xcc, 0x29, 0xc9, 0xd0, 0x2f, 0x33, 0x84, 0xb2, 0xf4, 0x0a, 0x8a, 0xf2,
171 0x37, 0x17, 0x7b, 0xa8, 0x9f, 0xb7, 0x9f, 0x7f, 0xb8, 0x9f, 0x00, 0x03, 0x88, 0x13, 0xec, 0x1a, 310 0x4b, 0xf2, 0x85, 0xf8, 0x40, 0x92, 0x7a, 0x50, 0xa1, 0x32, 0x43, 0x25, 0x3d, 0x2e, 0x21, 0x0f,
172 0x14, 0xe6, 0xe9, 0xe7, 0x2e, 0xc0, 0x28, 0xc4, 0xcf, 0xc5, 0xed, 0xe7, 0x1f, 0x12, 0x0f, 0x13, 311 0x30, 0xc7, 0x39, 0x23, 0x35, 0x39, 0x3b, 0x28, 0xb5, 0xb0, 0x34, 0xb5, 0xb8, 0x44, 0x48, 0x82,
173 0x60, 0x32, 0x8a, 0xe2, 0x62, 0x83, 0x58, 0x24, 0x14, 0xc0, 0xc5, 0x0a, 0xb6, 0x4c, 0x48, 0x09, 312 0x8b, 0xbd, 0x38, 0xb5, 0xa8, 0x2c, 0x33, 0x39, 0x55, 0x82, 0x51, 0x81, 0x51, 0x83, 0x33, 0x08,
174 0xaf, 0x4b, 0xc0, 0xfe, 0x95, 0x52, 0x26, 0xc2, 0xb5, 0x49, 0x6c, 0xe0, 0x10, 0x34, 0x06, 0x04, 313 0xc6, 0x55, 0xda, 0xc8, 0xc8, 0x25, 0x8c, 0xa2, 0xa1, 0xb8, 0x20, 0x3f, 0xaf, 0x38, 0x55, 0xc8,
175 0x00, 0x00, 0xff, 0xff, 0xac, 0x56, 0x2a, 0xcb, 0x51, 0x01, 0x00, 0x00, 314 0x93, 0x8b, 0xad, 0xb8, 0x24, 0xb1, 0xa4, 0xb4, 0x18, 0xac, 0x81, 0xcf, 0xc8, 0x50, 0x0f, 0xd5,
315 0x22, 0x3d, 0x2c, 0x9a, 0xf4, 0x82, 0x41, 0x86, 0xe6, 0xa5, 0x07, 0x83, 0x35, 0x06, 0x41, 0x0d,
316 0x50, 0xf2, 0xe7, 0xe2, 0x45, 0x91, 0x10, 0xe2, 0xe6, 0x62, 0x0f, 0xf5, 0xf3, 0xf6, 0xf3, 0x0f,
317 0xf7, 0x13, 0x60, 0x00, 0x71, 0x82, 0x5d, 0x83, 0xc2, 0x3c, 0xfd, 0xdc, 0x05, 0x18, 0x85, 0xf8,
318 0xb9, 0xb8, 0xfd, 0xfc, 0x43, 0xe2, 0x61, 0x02, 0x4c, 0x42, 0xc2, 0x5c, 0xfc, 0x60, 0x8e, 0xb3,
319 0x6b, 0x3c, 0x4c, 0x0b, 0xb3, 0xd1, 0x3a, 0x46, 0x2e, 0x36, 0x88, 0xf5, 0x42, 0x01, 0x5c, 0xac,
320 0x60, 0x27, 0x08, 0x29, 0xe1, 0x75, 0x1f, 0x38, 0x14, 0xa4, 0x94, 0x89, 0xf0, 0x83, 0x50, 0x10,
321 0x17, 0x6b, 0x78, 0x62, 0x49, 0x72, 0x06, 0xd5, 0x4c, 0x34, 0x60, 0x74, 0x4a, 0xe4, 0x12, 0xcc,
322 0xcc, 0x47, 0x53, 0xea, 0xc4, 0x0d, 0x51, 0x1b, 0x00, 0x8a, 0xc6, 0x00, 0xc6, 0x28, 0x9d, 0xf4,
323 0xfc, 0xfc, 0xf4, 0x9c, 0x54, 0xbd, 0xf4, 0xfc, 0x9c, 0xc4, 0xbc, 0x74, 0xbd, 0xfc, 0xa2, 0x74,
324 0x7d, 0xe4, 0x78, 0x07, 0xb1, 0xe3, 0x21, 0xec, 0xf8, 0x32, 0xc3, 0x55, 0x4c, 0x7c, 0xee, 0x20,
325 0xd3, 0x20, 0x46, 0xe8, 0x85, 0x19, 0x26, 0xb1, 0x81, 0x93, 0x83, 0x31, 0x20, 0x00, 0x00, 0xff,
326 0xff, 0x12, 0x7d, 0x96, 0xcb, 0x2d, 0x02, 0x00, 0x00,
176} 327}
diff --git a/vendor/google.golang.org/grpc/health/grpc_health_v1/health.proto b/vendor/google.golang.org/grpc/health/grpc_health_v1/health.proto
deleted file mode 100644
index 6072fdc..0000000
--- a/vendor/google.golang.org/grpc/health/grpc_health_v1/health.proto
+++ /dev/null
@@ -1,34 +0,0 @@
1// Copyright 2017 gRPC authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15syntax = "proto3";
16
17package grpc.health.v1;
18
19message HealthCheckRequest {
20 string service = 1;
21}
22
23message HealthCheckResponse {
24 enum ServingStatus {
25 UNKNOWN = 0;
26 SERVING = 1;
27 NOT_SERVING = 2;
28 }
29 ServingStatus status = 1;
30}
31
32service Health{
33 rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
34}
diff --git a/vendor/google.golang.org/grpc/health/health.go b/vendor/google.golang.org/grpc/health/health.go
deleted file mode 100644
index 4dccbc7..0000000
--- a/vendor/google.golang.org/grpc/health/health.go
+++ /dev/null
@@ -1,70 +0,0 @@
1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// Package health provides some utility functions to health-check a server. The implementation
20// is based on protobuf. Users need to write their own implementations if other IDLs are used.
21package health
22
23import (
24 "sync"
25
26 "golang.org/x/net/context"
27 "google.golang.org/grpc"
28 "google.golang.org/grpc/codes"
29 healthpb "google.golang.org/grpc/health/grpc_health_v1"
30)
31
32// Server implements `service Health`.
33type Server struct {
34 mu sync.Mutex
35 // statusMap stores the serving status of the services this Server monitors.
36 statusMap map[string]healthpb.HealthCheckResponse_ServingStatus
37}
38
39// NewServer returns a new Server.
40func NewServer() *Server {
41 return &Server{
42 statusMap: make(map[string]healthpb.HealthCheckResponse_ServingStatus),
43 }
44}
45
46// Check implements `service Health`.
47func (s *Server) Check(ctx context.Context, in *healthpb.HealthCheckRequest) (*healthpb.HealthCheckResponse, error) {
48 s.mu.Lock()
49 defer s.mu.Unlock()
50 if in.Service == "" {
51 // check the server overall health status.
52 return &healthpb.HealthCheckResponse{
53 Status: healthpb.HealthCheckResponse_SERVING,
54 }, nil
55 }
56 if status, ok := s.statusMap[in.Service]; ok {
57 return &healthpb.HealthCheckResponse{
58 Status: status,
59 }, nil
60 }
61 return nil, grpc.Errorf(codes.NotFound, "unknown service")
62}
63
64// SetServingStatus is called when need to reset the serving status of a service
65// or insert a new service entry into the statusMap.
66func (s *Server) SetServingStatus(service string, status healthpb.HealthCheckResponse_ServingStatus) {
67 s.mu.Lock()
68 s.statusMap[service] = status
69 s.mu.Unlock()
70}
diff --git a/vendor/google.golang.org/grpc/health/regenerate.sh b/vendor/google.golang.org/grpc/health/regenerate.sh
new file mode 100644
index 0000000..b11eccb
--- /dev/null
+++ b/vendor/google.golang.org/grpc/health/regenerate.sh
@@ -0,0 +1,33 @@
1#!/bin/bash
2# Copyright 2018 gRPC authors.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16set -eux -o pipefail
17
18TMP=$(mktemp -d)
19
20function finish {
21 rm -rf "$TMP"
22}
23trap finish EXIT
24
25pushd "$TMP"
26mkdir -p grpc/health/v1
27curl https://raw.githubusercontent.com/grpc/grpc-proto/master/grpc/health/v1/health.proto > grpc/health/v1/health.proto
28
29protoc --go_out=plugins=grpc,paths=source_relative:. -I. grpc/health/v1/*.proto
30popd
31rm -f grpc_health_v1/*.pb.go
32cp "$TMP"/grpc/health/v1/*.pb.go grpc_health_v1/
33
diff --git a/vendor/google.golang.org/grpc/health/server.go b/vendor/google.golang.org/grpc/health/server.go
new file mode 100644
index 0000000..c79f9d2
--- /dev/null
+++ b/vendor/google.golang.org/grpc/health/server.go
@@ -0,0 +1,165 @@
1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19//go:generate ./regenerate.sh
20
21// Package health provides a service that exposes server's health and it must be
22// imported to enable support for client-side health checks.
23package health
24
25import (
26 "context"
27 "sync"
28
29 "google.golang.org/grpc/codes"
30 "google.golang.org/grpc/grpclog"
31 healthgrpc "google.golang.org/grpc/health/grpc_health_v1"
32 healthpb "google.golang.org/grpc/health/grpc_health_v1"
33 "google.golang.org/grpc/status"
34)
35
36// Server implements `service Health`.
37type Server struct {
38 mu sync.Mutex
39 // If shutdown is true, it's expected all serving status is NOT_SERVING, and
40 // will stay in NOT_SERVING.
41 shutdown bool
42 // statusMap stores the serving status of the services this Server monitors.
43 statusMap map[string]healthpb.HealthCheckResponse_ServingStatus
44 updates map[string]map[healthgrpc.Health_WatchServer]chan healthpb.HealthCheckResponse_ServingStatus
45}
46
47// NewServer returns a new Server.
48func NewServer() *Server {
49 return &Server{
50 statusMap: map[string]healthpb.HealthCheckResponse_ServingStatus{"": healthpb.HealthCheckResponse_SERVING},
51 updates: make(map[string]map[healthgrpc.Health_WatchServer]chan healthpb.HealthCheckResponse_ServingStatus),
52 }
53}
54
55// Check implements `service Health`.
56func (s *Server) Check(ctx context.Context, in *healthpb.HealthCheckRequest) (*healthpb.HealthCheckResponse, error) {
57 s.mu.Lock()
58 defer s.mu.Unlock()
59 if servingStatus, ok := s.statusMap[in.Service]; ok {
60 return &healthpb.HealthCheckResponse{
61 Status: servingStatus,
62 }, nil
63 }
64 return nil, status.Error(codes.NotFound, "unknown service")
65}
66
67// Watch implements `service Health`.
68func (s *Server) Watch(in *healthpb.HealthCheckRequest, stream healthgrpc.Health_WatchServer) error {
69 service := in.Service
70 // update channel is used for getting service status updates.
71 update := make(chan healthpb.HealthCheckResponse_ServingStatus, 1)
72 s.mu.Lock()
73 // Puts the initial status to the channel.
74 if servingStatus, ok := s.statusMap[service]; ok {
75 update <- servingStatus
76 } else {
77 update <- healthpb.HealthCheckResponse_SERVICE_UNKNOWN
78 }
79
80 // Registers the update channel to the correct place in the updates map.
81 if _, ok := s.updates[service]; !ok {
82 s.updates[service] = make(map[healthgrpc.Health_WatchServer]chan healthpb.HealthCheckResponse_ServingStatus)
83 }
84 s.updates[service][stream] = update
85 defer func() {
86 s.mu.Lock()
87 delete(s.updates[service], stream)
88 s.mu.Unlock()
89 }()
90 s.mu.Unlock()
91
92 var lastSentStatus healthpb.HealthCheckResponse_ServingStatus = -1
93 for {
94 select {
95 // Status updated. Sends the up-to-date status to the client.
96 case servingStatus := <-update:
97 if lastSentStatus == servingStatus {
98 continue
99 }
100 lastSentStatus = servingStatus
101 err := stream.Send(&healthpb.HealthCheckResponse{Status: servingStatus})
102 if err != nil {
103 return status.Error(codes.Canceled, "Stream has ended.")
104 }
105 // Context done. Removes the update channel from the updates map.
106 case <-stream.Context().Done():
107 return status.Error(codes.Canceled, "Stream has ended.")
108 }
109 }
110}
111
112// SetServingStatus is called when need to reset the serving status of a service
113// or insert a new service entry into the statusMap.
114func (s *Server) SetServingStatus(service string, servingStatus healthpb.HealthCheckResponse_ServingStatus) {
115 s.mu.Lock()
116 defer s.mu.Unlock()
117 if s.shutdown {
118 grpclog.Infof("health: status changing for %s to %v is ignored because health service is shutdown", service, servingStatus)
119 return
120 }
121
122 s.setServingStatusLocked(service, servingStatus)
123}
124
125func (s *Server) setServingStatusLocked(service string, servingStatus healthpb.HealthCheckResponse_ServingStatus) {
126 s.statusMap[service] = servingStatus
127 for _, update := range s.updates[service] {
128 // Clears previous updates, that are not sent to the client, from the channel.
129 // This can happen if the client is not reading and the server gets flow control limited.
130 select {
131 case <-update:
132 default:
133 }
134 // Puts the most recent update to the channel.
135 update <- servingStatus
136 }
137}
138
139// Shutdown sets all serving status to NOT_SERVING, and configures the server to
140// ignore all future status changes.
141//
142// This changes serving status for all services. To set status for a perticular
143// services, call SetServingStatus().
144func (s *Server) Shutdown() {
145 s.mu.Lock()
146 defer s.mu.Unlock()
147 s.shutdown = true
148 for service := range s.statusMap {
149 s.setServingStatusLocked(service, healthpb.HealthCheckResponse_NOT_SERVING)
150 }
151}
152
153// Resume sets all serving status to SERVING, and configures the server to
154// accept all future status changes.
155//
156// This changes serving status for all services. To set status for a perticular
157// services, call SetServingStatus().
158func (s *Server) Resume() {
159 s.mu.Lock()
160 defer s.mu.Unlock()
161 s.shutdown = false
162 for service := range s.statusMap {
163 s.setServingStatusLocked(service, healthpb.HealthCheckResponse_SERVING)
164 }
165}
diff --git a/vendor/google.golang.org/grpc/install_gae.sh b/vendor/google.golang.org/grpc/install_gae.sh
new file mode 100644
index 0000000..7c7bcad
--- /dev/null
+++ b/vendor/google.golang.org/grpc/install_gae.sh
@@ -0,0 +1,6 @@
1#!/bin/bash
2
3TMP=$(mktemp -d /tmp/sdk.XXX) \
4&& curl -o $TMP.zip "https://storage.googleapis.com/appengine-sdks/featured/go_appengine_sdk_linux_amd64-1.9.68.zip" \
5&& unzip -q $TMP.zip -d $TMP \
6&& export PATH="$PATH:$TMP/go_appengine"
diff --git a/vendor/google.golang.org/grpc/interceptor.go b/vendor/google.golang.org/grpc/interceptor.go
index 06dc825..8b73500 100644
--- a/vendor/google.golang.org/grpc/interceptor.go
+++ b/vendor/google.golang.org/grpc/interceptor.go
@@ -19,7 +19,7 @@
19package grpc 19package grpc
20 20
21import ( 21import (
22 "golang.org/x/net/context" 22 "context"
23) 23)
24 24
25// UnaryInvoker is called by UnaryClientInterceptor to complete RPCs. 25// UnaryInvoker is called by UnaryClientInterceptor to complete RPCs.
@@ -48,7 +48,9 @@ type UnaryServerInfo struct {
48} 48}
49 49
50// UnaryHandler defines the handler invoked by UnaryServerInterceptor to complete the normal 50// UnaryHandler defines the handler invoked by UnaryServerInterceptor to complete the normal
51// execution of a unary RPC. 51// execution of a unary RPC. If a UnaryHandler returns an error, it should be produced by the
52// status package, or else gRPC will use codes.Unknown as the status code and err.Error() as
53// the status message of the RPC.
52type UnaryHandler func(ctx context.Context, req interface{}) (interface{}, error) 54type UnaryHandler func(ctx context.Context, req interface{}) (interface{}, error)
53 55
54// UnaryServerInterceptor provides a hook to intercept the execution of a unary RPC on the server. info 56// UnaryServerInterceptor provides a hook to intercept the execution of a unary RPC on the server. info
diff --git a/vendor/google.golang.org/grpc/internal/backoff/backoff.go b/vendor/google.golang.org/grpc/internal/backoff/backoff.go
new file mode 100644
index 0000000..1bd0cce
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/backoff/backoff.go
@@ -0,0 +1,78 @@
1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// Package backoff implement the backoff strategy for gRPC.
20//
21// This is kept in internal until the gRPC project decides whether or not to
22// allow alternative backoff strategies.
23package backoff
24
25import (
26 "time"
27
28 "google.golang.org/grpc/internal/grpcrand"
29)
30
31// Strategy defines the methodology for backing off after a grpc connection
32// failure.
33//
34type Strategy interface {
35 // Backoff returns the amount of time to wait before the next retry given
36 // the number of consecutive failures.
37 Backoff(retries int) time.Duration
38}
39
40const (
41 // baseDelay is the amount of time to wait before retrying after the first
42 // failure.
43 baseDelay = 1.0 * time.Second
44 // factor is applied to the backoff after each retry.
45 factor = 1.6
46 // jitter provides a range to randomize backoff delays.
47 jitter = 0.2
48)
49
50// Exponential implements exponential backoff algorithm as defined in
51// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md.
52type Exponential struct {
53 // MaxDelay is the upper bound of backoff delay.
54 MaxDelay time.Duration
55}
56
57// Backoff returns the amount of time to wait before the next retry given the
58// number of retries.
59func (bc Exponential) Backoff(retries int) time.Duration {
60 if retries == 0 {
61 return baseDelay
62 }
63 backoff, max := float64(baseDelay), float64(bc.MaxDelay)
64 for backoff < max && retries > 0 {
65 backoff *= factor
66 retries--
67 }
68 if backoff > max {
69 backoff = max
70 }
71 // Randomize backoff delays so that if a cluster of requests start at
72 // the same time, they won't operate in lockstep.
73 backoff *= 1 + jitter*(grpcrand.Float64()*2-1)
74 if backoff < 0 {
75 return 0
76 }
77 return time.Duration(backoff)
78}
diff --git a/vendor/google.golang.org/grpc/internal/binarylog/binarylog.go b/vendor/google.golang.org/grpc/internal/binarylog/binarylog.go
new file mode 100644
index 0000000..fee6aec
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/binarylog/binarylog.go
@@ -0,0 +1,167 @@
1/*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// Package binarylog implementation binary logging as defined in
20// https://github.com/grpc/proposal/blob/master/A16-binary-logging.md.
21package binarylog
22
23import (
24 "fmt"
25 "os"
26
27 "google.golang.org/grpc/grpclog"
28)
29
30// Logger is the global binary logger. It can be used to get binary logger for
31// each method.
32type Logger interface {
33 getMethodLogger(methodName string) *MethodLogger
34}
35
36// binLogger is the global binary logger for the binary. One of this should be
37// built at init time from the configuration (environment varialbe or flags).
38//
39// It is used to get a methodLogger for each individual method.
40var binLogger Logger
41
42// SetLogger sets the binarg logger.
43//
44// Only call this at init time.
45func SetLogger(l Logger) {
46 binLogger = l
47}
48
49// GetMethodLogger returns the methodLogger for the given methodName.
50//
51// methodName should be in the format of "/service/method".
52//
53// Each methodLogger returned by this method is a new instance. This is to
54// generate sequence id within the call.
55func GetMethodLogger(methodName string) *MethodLogger {
56 if binLogger == nil {
57 return nil
58 }
59 return binLogger.getMethodLogger(methodName)
60}
61
62func init() {
63 const envStr = "GRPC_BINARY_LOG_FILTER"
64 configStr := os.Getenv(envStr)
65 binLogger = NewLoggerFromConfigString(configStr)
66}
67
68type methodLoggerConfig struct {
69 // Max length of header and message.
70 hdr, msg uint64
71}
72
73type logger struct {
74 all *methodLoggerConfig
75 services map[string]*methodLoggerConfig
76 methods map[string]*methodLoggerConfig
77
78 blacklist map[string]struct{}
79}
80
81// newEmptyLogger creates an empty logger. The map fields need to be filled in
82// using the set* functions.
83func newEmptyLogger() *logger {
84 return &logger{}
85}
86
87// Set method logger for "*".
88func (l *logger) setDefaultMethodLogger(ml *methodLoggerConfig) error {
89 if l.all != nil {
90 return fmt.Errorf("conflicting global rules found")
91 }
92 l.all = ml
93 return nil
94}
95
96// Set method logger for "service/*".
97//
98// New methodLogger with same service overrides the old one.
99func (l *logger) setServiceMethodLogger(service string, ml *methodLoggerConfig) error {
100 if _, ok := l.services[service]; ok {
101 return fmt.Errorf("conflicting rules for service %v found", service)
102 }
103 if l.services == nil {
104 l.services = make(map[string]*methodLoggerConfig)
105 }
106 l.services[service] = ml
107 return nil
108}
109
110// Set method logger for "service/method".
111//
112// New methodLogger with same method overrides the old one.
113func (l *logger) setMethodMethodLogger(method string, ml *methodLoggerConfig) error {
114 if _, ok := l.blacklist[method]; ok {
115 return fmt.Errorf("conflicting rules for method %v found", method)
116 }
117 if _, ok := l.methods[method]; ok {
118 return fmt.Errorf("conflicting rules for method %v found", method)
119 }
120 if l.methods == nil {
121 l.methods = make(map[string]*methodLoggerConfig)
122 }
123 l.methods[method] = ml
124 return nil
125}
126
127// Set blacklist method for "-service/method".
128func (l *logger) setBlacklist(method string) error {
129 if _, ok := l.blacklist[method]; ok {
130 return fmt.Errorf("conflicting rules for method %v found", method)
131 }
132 if _, ok := l.methods[method]; ok {
133 return fmt.Errorf("conflicting rules for method %v found", method)
134 }
135 if l.blacklist == nil {
136 l.blacklist = make(map[string]struct{})
137 }
138 l.blacklist[method] = struct{}{}
139 return nil
140}
141
142// getMethodLogger returns the methodLogger for the given methodName.
143//
144// methodName should be in the format of "/service/method".
145//
146// Each methodLogger returned by this method is a new instance. This is to
147// generate sequence id within the call.
148func (l *logger) getMethodLogger(methodName string) *MethodLogger {
149 s, m, err := parseMethodName(methodName)
150 if err != nil {
151 grpclog.Infof("binarylogging: failed to parse %q: %v", methodName, err)
152 return nil
153 }
154 if ml, ok := l.methods[s+"/"+m]; ok {
155 return newMethodLogger(ml.hdr, ml.msg)
156 }
157 if _, ok := l.blacklist[s+"/"+m]; ok {
158 return nil
159 }
160 if ml, ok := l.services[s]; ok {
161 return newMethodLogger(ml.hdr, ml.msg)
162 }
163 if l.all == nil {
164 return nil
165 }
166 return newMethodLogger(l.all.hdr, l.all.msg)
167}
diff --git a/vendor/google.golang.org/grpc/internal/binarylog/binarylog_testutil.go b/vendor/google.golang.org/grpc/internal/binarylog/binarylog_testutil.go
new file mode 100644
index 0000000..1ee00a3
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/binarylog/binarylog_testutil.go
@@ -0,0 +1,42 @@
1/*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// This file contains exported variables/functions that are exported for testing
20// only.
21//
22// An ideal way for this would be to put those in a *_test.go but in binarylog
23// package. But this doesn't work with staticcheck with go module. Error was:
24// "MdToMetadataProto not declared by package binarylog". This could be caused
25// by the way staticcheck looks for files for a certain package, which doesn't
26// support *_test.go files.
27//
28// Move those to binary_test.go when staticcheck is fixed.
29
30package binarylog
31
32var (
33 // AllLogger is a logger that logs all headers/messages for all RPCs. It's
34 // for testing only.
35 AllLogger = NewLoggerFromConfigString("*")
36 // MdToMetadataProto converts metadata to a binary logging proto message.
37 // It's for testing only.
38 MdToMetadataProto = mdToMetadataProto
39 // AddrToProto converts an address to a binary logging proto message. It's
40 // for testing only.
41 AddrToProto = addrToProto
42)
diff --git a/vendor/google.golang.org/grpc/internal/binarylog/env_config.go b/vendor/google.golang.org/grpc/internal/binarylog/env_config.go
new file mode 100644
index 0000000..eb188ea
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/binarylog/env_config.go
@@ -0,0 +1,210 @@
1/*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package binarylog
20
21import (
22 "errors"
23 "fmt"
24 "regexp"
25 "strconv"
26 "strings"
27
28 "google.golang.org/grpc/grpclog"
29)
30
31// NewLoggerFromConfigString reads the string and build a logger. It can be used
32// to build a new logger and assign it to binarylog.Logger.
33//
34// Example filter config strings:
35// - "" Nothing will be logged
36// - "*" All headers and messages will be fully logged.
37// - "*{h}" Only headers will be logged.
38// - "*{m:256}" Only the first 256 bytes of each message will be logged.
39// - "Foo/*" Logs every method in service Foo
40// - "Foo/*,-Foo/Bar" Logs every method in service Foo except method /Foo/Bar
41// - "Foo/*,Foo/Bar{m:256}" Logs the first 256 bytes of each message in method
42// /Foo/Bar, logs all headers and messages in every other method in service
43// Foo.
44//
45// If two configs exist for one certain method or service, the one specified
46// later overrides the privous config.
47func NewLoggerFromConfigString(s string) Logger {
48 if s == "" {
49 return nil
50 }
51 l := newEmptyLogger()
52 methods := strings.Split(s, ",")
53 for _, method := range methods {
54 if err := l.fillMethodLoggerWithConfigString(method); err != nil {
55 grpclog.Warningf("failed to parse binary log config: %v", err)
56 return nil
57 }
58 }
59 return l
60}
61
62// fillMethodLoggerWithConfigString parses config, creates methodLogger and adds
63// it to the right map in the logger.
64func (l *logger) fillMethodLoggerWithConfigString(config string) error {
65 // "" is invalid.
66 if config == "" {
67 return errors.New("empty string is not a valid method binary logging config")
68 }
69
70 // "-service/method", blacklist, no * or {} allowed.
71 if config[0] == '-' {
72 s, m, suffix, err := parseMethodConfigAndSuffix(config[1:])
73 if err != nil {
74 return fmt.Errorf("invalid config: %q, %v", config, err)
75 }
76 if m == "*" {
77 return fmt.Errorf("invalid config: %q, %v", config, "* not allowd in blacklist config")
78 }
79 if suffix != "" {
80 return fmt.Errorf("invalid config: %q, %v", config, "header/message limit not allowed in blacklist config")
81 }
82 if err := l.setBlacklist(s + "/" + m); err != nil {
83 return fmt.Errorf("invalid config: %v", err)
84 }
85 return nil
86 }
87
88 // "*{h:256;m:256}"
89 if config[0] == '*' {
90 hdr, msg, err := parseHeaderMessageLengthConfig(config[1:])
91 if err != nil {
92 return fmt.Errorf("invalid config: %q, %v", config, err)
93 }
94 if err := l.setDefaultMethodLogger(&methodLoggerConfig{hdr: hdr, msg: msg}); err != nil {
95 return fmt.Errorf("invalid config: %v", err)
96 }
97 return nil
98 }
99
100 s, m, suffix, err := parseMethodConfigAndSuffix(config)
101 if err != nil {
102 return fmt.Errorf("invalid config: %q, %v", config, err)
103 }
104 hdr, msg, err := parseHeaderMessageLengthConfig(suffix)
105 if err != nil {
106 return fmt.Errorf("invalid header/message length config: %q, %v", suffix, err)
107 }
108 if m == "*" {
109 if err := l.setServiceMethodLogger(s, &methodLoggerConfig{hdr: hdr, msg: msg}); err != nil {
110 return fmt.Errorf("invalid config: %v", err)
111 }
112 } else {
113 if err := l.setMethodMethodLogger(s+"/"+m, &methodLoggerConfig{hdr: hdr, msg: msg}); err != nil {
114 return fmt.Errorf("invalid config: %v", err)
115 }
116 }
117 return nil
118}
119
120const (
121 // TODO: this const is only used by env_config now. But could be useful for
122 // other config. Move to binarylog.go if necessary.
123 maxUInt = ^uint64(0)
124
125 // For "p.s/m" plus any suffix. Suffix will be parsed again. See test for
126 // expected output.
127 longMethodConfigRegexpStr = `^([\w./]+)/((?:\w+)|[*])(.+)?$`
128
129 // For suffix from above, "{h:123,m:123}". See test for expected output.
130 optionalLengthRegexpStr = `(?::(\d+))?` // Optional ":123".
131 headerConfigRegexpStr = `^{h` + optionalLengthRegexpStr + `}$`
132 messageConfigRegexpStr = `^{m` + optionalLengthRegexpStr + `}$`
133 headerMessageConfigRegexpStr = `^{h` + optionalLengthRegexpStr + `;m` + optionalLengthRegexpStr + `}$`
134)
135
136var (
137 longMethodConfigRegexp = regexp.MustCompile(longMethodConfigRegexpStr)
138 headerConfigRegexp = regexp.MustCompile(headerConfigRegexpStr)
139 messageConfigRegexp = regexp.MustCompile(messageConfigRegexpStr)
140 headerMessageConfigRegexp = regexp.MustCompile(headerMessageConfigRegexpStr)
141)
142
143// Turn "service/method{h;m}" into "service", "method", "{h;m}".
144func parseMethodConfigAndSuffix(c string) (service, method, suffix string, _ error) {
145 // Regexp result:
146 //
147 // in: "p.s/m{h:123,m:123}",
148 // out: []string{"p.s/m{h:123,m:123}", "p.s", "m", "{h:123,m:123}"},
149 match := longMethodConfigRegexp.FindStringSubmatch(c)
150 if match == nil {
151 return "", "", "", fmt.Errorf("%q contains invalid substring", c)
152 }
153 service = match[1]
154 method = match[2]
155 suffix = match[3]
156 return
157}
158
159// Turn "{h:123;m:345}" into 123, 345.
160//
161// Return maxUInt if length is unspecified.
162func parseHeaderMessageLengthConfig(c string) (hdrLenStr, msgLenStr uint64, err error) {
163 if c == "" {
164 return maxUInt, maxUInt, nil
165 }
166 // Header config only.
167 if match := headerConfigRegexp.FindStringSubmatch(c); match != nil {
168 if s := match[1]; s != "" {
169 hdrLenStr, err = strconv.ParseUint(s, 10, 64)
170 if err != nil {
171 return 0, 0, fmt.Errorf("failed to convert %q to uint", s)
172 }
173 return hdrLenStr, 0, nil
174 }
175 return maxUInt, 0, nil
176 }
177
178 // Message config only.
179 if match := messageConfigRegexp.FindStringSubmatch(c); match != nil {
180 if s := match[1]; s != "" {
181 msgLenStr, err = strconv.ParseUint(s, 10, 64)
182 if err != nil {
183 return 0, 0, fmt.Errorf("Failed to convert %q to uint", s)
184 }
185 return 0, msgLenStr, nil
186 }
187 return 0, maxUInt, nil
188 }
189
190 // Header and message config both.
191 if match := headerMessageConfigRegexp.FindStringSubmatch(c); match != nil {
192 // Both hdr and msg are specified, but one or two of them might be empty.
193 hdrLenStr = maxUInt
194 msgLenStr = maxUInt
195 if s := match[1]; s != "" {
196 hdrLenStr, err = strconv.ParseUint(s, 10, 64)
197 if err != nil {
198 return 0, 0, fmt.Errorf("Failed to convert %q to uint", s)
199 }
200 }
201 if s := match[2]; s != "" {
202 msgLenStr, err = strconv.ParseUint(s, 10, 64)
203 if err != nil {
204 return 0, 0, fmt.Errorf("Failed to convert %q to uint", s)
205 }
206 }
207 return hdrLenStr, msgLenStr, nil
208 }
209 return 0, 0, fmt.Errorf("%q contains invalid substring", c)
210}
diff --git a/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go b/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go
new file mode 100644
index 0000000..b06cdd4
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go
@@ -0,0 +1,426 @@
1/*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package binarylog
20
21import (
22 "net"
23 "strings"
24 "sync/atomic"
25 "time"
26
27 "github.com/golang/protobuf/proto"
28 "github.com/golang/protobuf/ptypes"
29 pb "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
30 "google.golang.org/grpc/grpclog"
31 "google.golang.org/grpc/metadata"
32 "google.golang.org/grpc/status"
33)
34
35type callIDGenerator struct {
36 id uint64
37}
38
39func (g *callIDGenerator) next() uint64 {
40 id := atomic.AddUint64(&g.id, 1)
41 return id
42}
43
44// reset is for testing only, and doesn't need to be thread safe.
45func (g *callIDGenerator) reset() {
46 g.id = 0
47}
48
49var idGen callIDGenerator
50
51// MethodLogger is the sub-logger for each method.
52type MethodLogger struct {
53 headerMaxLen, messageMaxLen uint64
54
55 callID uint64
56 idWithinCallGen *callIDGenerator
57
58 sink Sink // TODO(blog): make this plugable.
59}
60
61func newMethodLogger(h, m uint64) *MethodLogger {
62 return &MethodLogger{
63 headerMaxLen: h,
64 messageMaxLen: m,
65
66 callID: idGen.next(),
67 idWithinCallGen: &callIDGenerator{},
68
69 sink: defaultSink, // TODO(blog): make it plugable.
70 }
71}
72
73// Log creates a proto binary log entry, and logs it to the sink.
74func (ml *MethodLogger) Log(c LogEntryConfig) {
75 m := c.toProto()
76 timestamp, _ := ptypes.TimestampProto(time.Now())
77 m.Timestamp = timestamp
78 m.CallId = ml.callID
79 m.SequenceIdWithinCall = ml.idWithinCallGen.next()
80
81 switch pay := m.Payload.(type) {
82 case *pb.GrpcLogEntry_ClientHeader:
83 m.PayloadTruncated = ml.truncateMetadata(pay.ClientHeader.GetMetadata())
84 case *pb.GrpcLogEntry_ServerHeader:
85 m.PayloadTruncated = ml.truncateMetadata(pay.ServerHeader.GetMetadata())
86 case *pb.GrpcLogEntry_Message:
87 m.PayloadTruncated = ml.truncateMessage(pay.Message)
88 }
89
90 ml.sink.Write(m)
91}
92
93func (ml *MethodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated bool) {
94 if ml.headerMaxLen == maxUInt {
95 return false
96 }
97 var (
98 bytesLimit = ml.headerMaxLen
99 index int
100 )
101 // At the end of the loop, index will be the first entry where the total
102 // size is greater than the limit:
103 //
104 // len(entry[:index]) <= ml.hdr && len(entry[:index+1]) > ml.hdr.
105 for ; index < len(mdPb.Entry); index++ {
106 entry := mdPb.Entry[index]
107 if entry.Key == "grpc-trace-bin" {
108 // "grpc-trace-bin" is a special key. It's kept in the log entry,
109 // but not counted towards the size limit.
110 continue
111 }
112 currentEntryLen := uint64(len(entry.Value))
113 if currentEntryLen > bytesLimit {
114 break
115 }
116 bytesLimit -= currentEntryLen
117 }
118 truncated = index < len(mdPb.Entry)
119 mdPb.Entry = mdPb.Entry[:index]
120 return truncated
121}
122
123func (ml *MethodLogger) truncateMessage(msgPb *pb.Message) (truncated bool) {
124 if ml.messageMaxLen == maxUInt {
125 return false
126 }
127 if ml.messageMaxLen >= uint64(len(msgPb.Data)) {
128 return false
129 }
130 msgPb.Data = msgPb.Data[:ml.messageMaxLen]
131 return true
132}
133
134// LogEntryConfig represents the configuration for binary log entry.
135type LogEntryConfig interface {
136 toProto() *pb.GrpcLogEntry
137}
138
139// ClientHeader configs the binary log entry to be a ClientHeader entry.
140type ClientHeader struct {
141 OnClientSide bool
142 Header metadata.MD
143 MethodName string
144 Authority string
145 Timeout time.Duration
146 // PeerAddr is required only when it's on server side.
147 PeerAddr net.Addr
148}
149
150func (c *ClientHeader) toProto() *pb.GrpcLogEntry {
151 // This function doesn't need to set all the fields (e.g. seq ID). The Log
152 // function will set the fields when necessary.
153 clientHeader := &pb.ClientHeader{
154 Metadata: mdToMetadataProto(c.Header),
155 MethodName: c.MethodName,
156 Authority: c.Authority,
157 }
158 if c.Timeout > 0 {
159 clientHeader.Timeout = ptypes.DurationProto(c.Timeout)
160 }
161 ret := &pb.GrpcLogEntry{
162 Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER,
163 Payload: &pb.GrpcLogEntry_ClientHeader{
164 ClientHeader: clientHeader,
165 },
166 }
167 if c.OnClientSide {
168 ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
169 } else {
170 ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
171 }
172 if c.PeerAddr != nil {
173 ret.Peer = addrToProto(c.PeerAddr)
174 }
175 return ret
176}
177
178// ServerHeader configs the binary log entry to be a ServerHeader entry.
179type ServerHeader struct {
180 OnClientSide bool
181 Header metadata.MD
182 // PeerAddr is required only when it's on client side.
183 PeerAddr net.Addr
184}
185
186func (c *ServerHeader) toProto() *pb.GrpcLogEntry {
187 ret := &pb.GrpcLogEntry{
188 Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_HEADER,
189 Payload: &pb.GrpcLogEntry_ServerHeader{
190 ServerHeader: &pb.ServerHeader{
191 Metadata: mdToMetadataProto(c.Header),
192 },
193 },
194 }
195 if c.OnClientSide {
196 ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
197 } else {
198 ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
199 }
200 if c.PeerAddr != nil {
201 ret.Peer = addrToProto(c.PeerAddr)
202 }
203 return ret
204}
205
206// ClientMessage configs the binary log entry to be a ClientMessage entry.
207type ClientMessage struct {
208 OnClientSide bool
209 // Message can be a proto.Message or []byte. Other messages formats are not
210 // supported.
211 Message interface{}
212}
213
214func (c *ClientMessage) toProto() *pb.GrpcLogEntry {
215 var (
216 data []byte
217 err error
218 )
219 if m, ok := c.Message.(proto.Message); ok {
220 data, err = proto.Marshal(m)
221 if err != nil {
222 grpclog.Infof("binarylogging: failed to marshal proto message: %v", err)
223 }
224 } else if b, ok := c.Message.([]byte); ok {
225 data = b
226 } else {
227 grpclog.Infof("binarylogging: message to log is neither proto.message nor []byte")
228 }
229 ret := &pb.GrpcLogEntry{
230 Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_MESSAGE,
231 Payload: &pb.GrpcLogEntry_Message{
232 Message: &pb.Message{
233 Length: uint32(len(data)),
234 Data: data,
235 },
236 },
237 }
238 if c.OnClientSide {
239 ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
240 } else {
241 ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
242 }
243 return ret
244}
245
246// ServerMessage configs the binary log entry to be a ServerMessage entry.
247type ServerMessage struct {
248 OnClientSide bool
249 // Message can be a proto.Message or []byte. Other messages formats are not
250 // supported.
251 Message interface{}
252}
253
254func (c *ServerMessage) toProto() *pb.GrpcLogEntry {
255 var (
256 data []byte
257 err error
258 )
259 if m, ok := c.Message.(proto.Message); ok {
260 data, err = proto.Marshal(m)
261 if err != nil {
262 grpclog.Infof("binarylogging: failed to marshal proto message: %v", err)
263 }
264 } else if b, ok := c.Message.([]byte); ok {
265 data = b
266 } else {
267 grpclog.Infof("binarylogging: message to log is neither proto.message nor []byte")
268 }
269 ret := &pb.GrpcLogEntry{
270 Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_MESSAGE,
271 Payload: &pb.GrpcLogEntry_Message{
272 Message: &pb.Message{
273 Length: uint32(len(data)),
274 Data: data,
275 },
276 },
277 }
278 if c.OnClientSide {
279 ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
280 } else {
281 ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
282 }
283 return ret
284}
285
286// ClientHalfClose configs the binary log entry to be a ClientHalfClose entry.
287type ClientHalfClose struct {
288 OnClientSide bool
289}
290
291func (c *ClientHalfClose) toProto() *pb.GrpcLogEntry {
292 ret := &pb.GrpcLogEntry{
293 Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HALF_CLOSE,
294 Payload: nil, // No payload here.
295 }
296 if c.OnClientSide {
297 ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
298 } else {
299 ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
300 }
301 return ret
302}
303
304// ServerTrailer configs the binary log entry to be a ServerTrailer entry.
305type ServerTrailer struct {
306 OnClientSide bool
307 Trailer metadata.MD
308 // Err is the status error.
309 Err error
310 // PeerAddr is required only when it's on client side and the RPC is trailer
311 // only.
312 PeerAddr net.Addr
313}
314
315func (c *ServerTrailer) toProto() *pb.GrpcLogEntry {
316 st, ok := status.FromError(c.Err)
317 if !ok {
318 grpclog.Info("binarylogging: error in trailer is not a status error")
319 }
320 var (
321 detailsBytes []byte
322 err error
323 )
324 stProto := st.Proto()
325 if stProto != nil && len(stProto.Details) != 0 {
326 detailsBytes, err = proto.Marshal(stProto)
327 if err != nil {
328 grpclog.Infof("binarylogging: failed to marshal status proto: %v", err)
329 }
330 }
331 ret := &pb.GrpcLogEntry{
332 Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER,
333 Payload: &pb.GrpcLogEntry_Trailer{
334 Trailer: &pb.Trailer{
335 Metadata: mdToMetadataProto(c.Trailer),
336 StatusCode: uint32(st.Code()),
337 StatusMessage: st.Message(),
338 StatusDetails: detailsBytes,
339 },
340 },
341 }
342 if c.OnClientSide {
343 ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
344 } else {
345 ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
346 }
347 if c.PeerAddr != nil {
348 ret.Peer = addrToProto(c.PeerAddr)
349 }
350 return ret
351}
352
353// Cancel configs the binary log entry to be a Cancel entry.
354type Cancel struct {
355 OnClientSide bool
356}
357
358func (c *Cancel) toProto() *pb.GrpcLogEntry {
359 ret := &pb.GrpcLogEntry{
360 Type: pb.GrpcLogEntry_EVENT_TYPE_CANCEL,
361 Payload: nil,
362 }
363 if c.OnClientSide {
364 ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
365 } else {
366 ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
367 }
368 return ret
369}
370
371// metadataKeyOmit returns whether the metadata entry with this key should be
372// omitted.
373func metadataKeyOmit(key string) bool {
374 switch key {
375 case "lb-token", ":path", ":authority", "content-encoding", "content-type", "user-agent", "te":
376 return true
377 case "grpc-trace-bin": // grpc-trace-bin is special because it's visiable to users.
378 return false
379 }
380 if strings.HasPrefix(key, "grpc-") {
381 return true
382 }
383 return false
384}
385
386func mdToMetadataProto(md metadata.MD) *pb.Metadata {
387 ret := &pb.Metadata{}
388 for k, vv := range md {
389 if metadataKeyOmit(k) {
390 continue
391 }
392 for _, v := range vv {
393 ret.Entry = append(ret.Entry,
394 &pb.MetadataEntry{
395 Key: k,
396 Value: []byte(v),
397 },
398 )
399 }
400 }
401 return ret
402}
403
404func addrToProto(addr net.Addr) *pb.Address {
405 ret := &pb.Address{}
406 switch a := addr.(type) {
407 case *net.TCPAddr:
408 if a.IP.To4() != nil {
409 ret.Type = pb.Address_TYPE_IPV4
410 } else if a.IP.To16() != nil {
411 ret.Type = pb.Address_TYPE_IPV6
412 } else {
413 ret.Type = pb.Address_TYPE_UNKNOWN
414 // Do not set address and port fields.
415 break
416 }
417 ret.Address = a.IP.String()
418 ret.IpPort = uint32(a.Port)
419 case *net.UnixAddr:
420 ret.Type = pb.Address_TYPE_UNIX
421 ret.Address = a.String()
422 default:
423 ret.Type = pb.Address_TYPE_UNKNOWN
424 }
425 return ret
426}
diff --git a/vendor/google.golang.org/grpc/internal/binarylog/regenerate.sh b/vendor/google.golang.org/grpc/internal/binarylog/regenerate.sh
new file mode 100644
index 0000000..113d40c
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/binarylog/regenerate.sh
@@ -0,0 +1,33 @@
1#!/bin/bash
2# Copyright 2018 gRPC authors.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16set -eux -o pipefail
17
18TMP=$(mktemp -d)
19
20function finish {
21 rm -rf "$TMP"
22}
23trap finish EXIT
24
25pushd "$TMP"
26mkdir -p grpc/binarylog/grpc_binarylog_v1
27curl https://raw.githubusercontent.com/grpc/grpc-proto/master/grpc/binlog/v1/binarylog.proto > grpc/binarylog/grpc_binarylog_v1/binarylog.proto
28
29protoc --go_out=plugins=grpc,paths=source_relative:. -I. grpc/binarylog/grpc_binarylog_v1/*.proto
30popd
31rm -f ./grpc_binarylog_v1/*.pb.go
32cp "$TMP"/grpc/binarylog/grpc_binarylog_v1/*.pb.go ../../binarylog/grpc_binarylog_v1/
33
diff --git a/vendor/google.golang.org/grpc/internal/binarylog/sink.go b/vendor/google.golang.org/grpc/internal/binarylog/sink.go
new file mode 100644
index 0000000..20d044f
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/binarylog/sink.go
@@ -0,0 +1,162 @@
1/*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package binarylog
20
21import (
22 "bufio"
23 "encoding/binary"
24 "fmt"
25 "io"
26 "io/ioutil"
27 "sync"
28 "time"
29
30 "github.com/golang/protobuf/proto"
31 pb "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
32 "google.golang.org/grpc/grpclog"
33)
34
35var (
36 defaultSink Sink = &noopSink{} // TODO(blog): change this default (file in /tmp).
37)
38
39// SetDefaultSink sets the sink where binary logs will be written to.
40//
41// Not thread safe. Only set during initialization.
42func SetDefaultSink(s Sink) {
43 if defaultSink != nil {
44 defaultSink.Close()
45 }
46 defaultSink = s
47}
48
49// Sink writes log entry into the binary log sink.
50type Sink interface {
51 // Write will be called to write the log entry into the sink.
52 //
53 // It should be thread-safe so it can be called in parallel.
54 Write(*pb.GrpcLogEntry) error
55 // Close will be called when the Sink is replaced by a new Sink.
56 Close() error
57}
58
59type noopSink struct{}
60
61func (ns *noopSink) Write(*pb.GrpcLogEntry) error { return nil }
62func (ns *noopSink) Close() error { return nil }
63
64// newWriterSink creates a binary log sink with the given writer.
65//
66// Write() marshalls the proto message and writes it to the given writer. Each
67// message is prefixed with a 4 byte big endian unsigned integer as the length.
68//
69// No buffer is done, Close() doesn't try to close the writer.
70func newWriterSink(w io.Writer) *writerSink {
71 return &writerSink{out: w}
72}
73
74type writerSink struct {
75 out io.Writer
76}
77
78func (ws *writerSink) Write(e *pb.GrpcLogEntry) error {
79 b, err := proto.Marshal(e)
80 if err != nil {
81 grpclog.Infof("binary logging: failed to marshal proto message: %v", err)
82 }
83 hdr := make([]byte, 4)
84 binary.BigEndian.PutUint32(hdr, uint32(len(b)))
85 if _, err := ws.out.Write(hdr); err != nil {
86 return err
87 }
88 if _, err := ws.out.Write(b); err != nil {
89 return err
90 }
91 return nil
92}
93
94func (ws *writerSink) Close() error { return nil }
95
96type bufWriteCloserSink struct {
97 mu sync.Mutex
98 closer io.Closer
99 out *writerSink // out is built on buf.
100 buf *bufio.Writer // buf is kept for flush.
101
102 writeStartOnce sync.Once
103 writeTicker *time.Ticker
104}
105
106func (fs *bufWriteCloserSink) Write(e *pb.GrpcLogEntry) error {
107 // Start the write loop when Write is called.
108 fs.writeStartOnce.Do(fs.startFlushGoroutine)
109 fs.mu.Lock()
110 if err := fs.out.Write(e); err != nil {
111 fs.mu.Unlock()
112 return err
113 }
114 fs.mu.Unlock()
115 return nil
116}
117
118const (
119 bufFlushDuration = 60 * time.Second
120)
121
122func (fs *bufWriteCloserSink) startFlushGoroutine() {
123 fs.writeTicker = time.NewTicker(bufFlushDuration)
124 go func() {
125 for range fs.writeTicker.C {
126 fs.mu.Lock()
127 fs.buf.Flush()
128 fs.mu.Unlock()
129 }
130 }()
131}
132
133func (fs *bufWriteCloserSink) Close() error {
134 if fs.writeTicker != nil {
135 fs.writeTicker.Stop()
136 }
137 fs.mu.Lock()
138 fs.buf.Flush()
139 fs.closer.Close()
140 fs.out.Close()
141 fs.mu.Unlock()
142 return nil
143}
144
145func newBufWriteCloserSink(o io.WriteCloser) Sink {
146 bufW := bufio.NewWriter(o)
147 return &bufWriteCloserSink{
148 closer: o,
149 out: newWriterSink(bufW),
150 buf: bufW,
151 }
152}
153
154// NewTempFileSink creates a temp file and returns a Sink that writes to this
155// file.
156func NewTempFileSink() (Sink, error) {
157 tempFile, err := ioutil.TempFile("/tmp", "grpcgo_binarylog_*.txt")
158 if err != nil {
159 return nil, fmt.Errorf("failed to create temp file: %v", err)
160 }
161 return newBufWriteCloserSink(tempFile), nil
162}
diff --git a/vendor/google.golang.org/grpc/internal/binarylog/util.go b/vendor/google.golang.org/grpc/internal/binarylog/util.go
new file mode 100644
index 0000000..15dc780
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/binarylog/util.go
@@ -0,0 +1,41 @@
1/*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package binarylog
20
21import (
22 "errors"
23 "strings"
24)
25
26// parseMethodName splits service and method from the input. It expects format
27// "/service/method".
28//
29// TODO: move to internal/grpcutil.
30func parseMethodName(methodName string) (service, method string, _ error) {
31 if !strings.HasPrefix(methodName, "/") {
32 return "", "", errors.New("invalid method name: should start with /")
33 }
34 methodName = methodName[1:]
35
36 pos := strings.LastIndex(methodName, "/")
37 if pos < 0 {
38 return "", "", errors.New("invalid method name: suffix /method is missing")
39 }
40 return methodName[:pos], methodName[pos+1:], nil
41}
diff --git a/vendor/google.golang.org/grpc/internal/channelz/funcs.go b/vendor/google.golang.org/grpc/internal/channelz/funcs.go
new file mode 100644
index 0000000..041520d
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/channelz/funcs.go
@@ -0,0 +1,699 @@
1/*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// Package channelz defines APIs for enabling channelz service, entry
20// registration/deletion, and accessing channelz data. It also defines channelz
21// metric struct formats.
22//
23// All APIs in this package are experimental.
24package channelz
25
26import (
27 "sort"
28 "sync"
29 "sync/atomic"
30 "time"
31
32 "google.golang.org/grpc/grpclog"
33)
34
35const (
36 defaultMaxTraceEntry int32 = 30
37)
38
39var (
40 db dbWrapper
41 idGen idGenerator
42 // EntryPerPage defines the number of channelz entries to be shown on a web page.
43 EntryPerPage = int64(50)
44 curState int32
45 maxTraceEntry = defaultMaxTraceEntry
46)
47
48// TurnOn turns on channelz data collection.
49func TurnOn() {
50 if !IsOn() {
51 NewChannelzStorage()
52 atomic.StoreInt32(&curState, 1)
53 }
54}
55
56// IsOn returns whether channelz data collection is on.
57func IsOn() bool {
58 return atomic.CompareAndSwapInt32(&curState, 1, 1)
59}
60
61// SetMaxTraceEntry sets maximum number of trace entry per entity (i.e. channel/subchannel).
62// Setting it to 0 will disable channel tracing.
63func SetMaxTraceEntry(i int32) {
64 atomic.StoreInt32(&maxTraceEntry, i)
65}
66
67// ResetMaxTraceEntryToDefault resets the maximum number of trace entry per entity to default.
68func ResetMaxTraceEntryToDefault() {
69 atomic.StoreInt32(&maxTraceEntry, defaultMaxTraceEntry)
70}
71
72func getMaxTraceEntry() int {
73 i := atomic.LoadInt32(&maxTraceEntry)
74 return int(i)
75}
76
77// dbWarpper wraps around a reference to internal channelz data storage, and
78// provide synchronized functionality to set and get the reference.
79type dbWrapper struct {
80 mu sync.RWMutex
81 DB *channelMap
82}
83
84func (d *dbWrapper) set(db *channelMap) {
85 d.mu.Lock()
86 d.DB = db
87 d.mu.Unlock()
88}
89
90func (d *dbWrapper) get() *channelMap {
91 d.mu.RLock()
92 defer d.mu.RUnlock()
93 return d.DB
94}
95
96// NewChannelzStorage initializes channelz data storage and id generator.
97//
98// Note: This function is exported for testing purpose only. User should not call
99// it in most cases.
100func NewChannelzStorage() {
101 db.set(&channelMap{
102 topLevelChannels: make(map[int64]struct{}),
103 channels: make(map[int64]*channel),
104 listenSockets: make(map[int64]*listenSocket),
105 normalSockets: make(map[int64]*normalSocket),
106 servers: make(map[int64]*server),
107 subChannels: make(map[int64]*subChannel),
108 })
109 idGen.reset()
110}
111
112// GetTopChannels returns a slice of top channel's ChannelMetric, along with a
113// boolean indicating whether there's more top channels to be queried for.
114//
115// The arg id specifies that only top channel with id at or above it will be included
116// in the result. The returned slice is up to a length of the arg maxResults or
117// EntryPerPage if maxResults is zero, and is sorted in ascending id order.
118func GetTopChannels(id int64, maxResults int64) ([]*ChannelMetric, bool) {
119 return db.get().GetTopChannels(id, maxResults)
120}
121
122// GetServers returns a slice of server's ServerMetric, along with a
123// boolean indicating whether there's more servers to be queried for.
124//
125// The arg id specifies that only server with id at or above it will be included
126// in the result. The returned slice is up to a length of the arg maxResults or
127// EntryPerPage if maxResults is zero, and is sorted in ascending id order.
128func GetServers(id int64, maxResults int64) ([]*ServerMetric, bool) {
129 return db.get().GetServers(id, maxResults)
130}
131
132// GetServerSockets returns a slice of server's (identified by id) normal socket's
133// SocketMetric, along with a boolean indicating whether there's more sockets to
134// be queried for.
135//
136// The arg startID specifies that only sockets with id at or above it will be
137// included in the result. The returned slice is up to a length of the arg maxResults
138// or EntryPerPage if maxResults is zero, and is sorted in ascending id order.
139func GetServerSockets(id int64, startID int64, maxResults int64) ([]*SocketMetric, bool) {
140 return db.get().GetServerSockets(id, startID, maxResults)
141}
142
143// GetChannel returns the ChannelMetric for the channel (identified by id).
144func GetChannel(id int64) *ChannelMetric {
145 return db.get().GetChannel(id)
146}
147
148// GetSubChannel returns the SubChannelMetric for the subchannel (identified by id).
149func GetSubChannel(id int64) *SubChannelMetric {
150 return db.get().GetSubChannel(id)
151}
152
153// GetSocket returns the SocketInternalMetric for the socket (identified by id).
154func GetSocket(id int64) *SocketMetric {
155 return db.get().GetSocket(id)
156}
157
158// GetServer returns the ServerMetric for the server (identified by id).
159func GetServer(id int64) *ServerMetric {
160 return db.get().GetServer(id)
161}
162
163// RegisterChannel registers the given channel c in channelz database with ref
164// as its reference name, and add it to the child list of its parent (identified
165// by pid). pid = 0 means no parent. It returns the unique channelz tracking id
166// assigned to this channel.
167func RegisterChannel(c Channel, pid int64, ref string) int64 {
168 id := idGen.genID()
169 cn := &channel{
170 refName: ref,
171 c: c,
172 subChans: make(map[int64]string),
173 nestedChans: make(map[int64]string),
174 id: id,
175 pid: pid,
176 trace: &channelTrace{createdTime: time.Now(), events: make([]*TraceEvent, 0, getMaxTraceEntry())},
177 }
178 if pid == 0 {
179 db.get().addChannel(id, cn, true, pid, ref)
180 } else {
181 db.get().addChannel(id, cn, false, pid, ref)
182 }
183 return id
184}
185
186// RegisterSubChannel registers the given channel c in channelz database with ref
187// as its reference name, and add it to the child list of its parent (identified
188// by pid). It returns the unique channelz tracking id assigned to this subchannel.
189func RegisterSubChannel(c Channel, pid int64, ref string) int64 {
190 if pid == 0 {
191 grpclog.Error("a SubChannel's parent id cannot be 0")
192 return 0
193 }
194 id := idGen.genID()
195 sc := &subChannel{
196 refName: ref,
197 c: c,
198 sockets: make(map[int64]string),
199 id: id,
200 pid: pid,
201 trace: &channelTrace{createdTime: time.Now(), events: make([]*TraceEvent, 0, getMaxTraceEntry())},
202 }
203 db.get().addSubChannel(id, sc, pid, ref)
204 return id
205}
206
207// RegisterServer registers the given server s in channelz database. It returns
208// the unique channelz tracking id assigned to this server.
209func RegisterServer(s Server, ref string) int64 {
210 id := idGen.genID()
211 svr := &server{
212 refName: ref,
213 s: s,
214 sockets: make(map[int64]string),
215 listenSockets: make(map[int64]string),
216 id: id,
217 }
218 db.get().addServer(id, svr)
219 return id
220}
221
222// RegisterListenSocket registers the given listen socket s in channelz database
223// with ref as its reference name, and add it to the child list of its parent
224// (identified by pid). It returns the unique channelz tracking id assigned to
225// this listen socket.
226func RegisterListenSocket(s Socket, pid int64, ref string) int64 {
227 if pid == 0 {
228 grpclog.Error("a ListenSocket's parent id cannot be 0")
229 return 0
230 }
231 id := idGen.genID()
232 ls := &listenSocket{refName: ref, s: s, id: id, pid: pid}
233 db.get().addListenSocket(id, ls, pid, ref)
234 return id
235}
236
237// RegisterNormalSocket registers the given normal socket s in channelz database
238// with ref as its reference name, and add it to the child list of its parent
239// (identified by pid). It returns the unique channelz tracking id assigned to
240// this normal socket.
241func RegisterNormalSocket(s Socket, pid int64, ref string) int64 {
242 if pid == 0 {
243 grpclog.Error("a NormalSocket's parent id cannot be 0")
244 return 0
245 }
246 id := idGen.genID()
247 ns := &normalSocket{refName: ref, s: s, id: id, pid: pid}
248 db.get().addNormalSocket(id, ns, pid, ref)
249 return id
250}
251
252// RemoveEntry removes an entry with unique channelz trakcing id to be id from
253// channelz database.
254func RemoveEntry(id int64) {
255 db.get().removeEntry(id)
256}
257
258// TraceEventDesc is what the caller of AddTraceEvent should provide to describe the event to be added
259// to the channel trace.
260// The Parent field is optional. It is used for event that will be recorded in the entity's parent
261// trace also.
262type TraceEventDesc struct {
263 Desc string
264 Severity Severity
265 Parent *TraceEventDesc
266}
267
268// AddTraceEvent adds trace related to the entity with specified id, using the provided TraceEventDesc.
269func AddTraceEvent(id int64, desc *TraceEventDesc) {
270 if getMaxTraceEntry() == 0 {
271 return
272 }
273 db.get().traceEvent(id, desc)
274}
275
276// channelMap is the storage data structure for channelz.
277// Methods of channelMap can be divided in two two categories with respect to locking.
278// 1. Methods acquire the global lock.
279// 2. Methods that can only be called when global lock is held.
280// A second type of method need always to be called inside a first type of method.
281type channelMap struct {
282 mu sync.RWMutex
283 topLevelChannels map[int64]struct{}
284 servers map[int64]*server
285 channels map[int64]*channel
286 subChannels map[int64]*subChannel
287 listenSockets map[int64]*listenSocket
288 normalSockets map[int64]*normalSocket
289}
290
291func (c *channelMap) addServer(id int64, s *server) {
292 c.mu.Lock()
293 s.cm = c
294 c.servers[id] = s
295 c.mu.Unlock()
296}
297
298func (c *channelMap) addChannel(id int64, cn *channel, isTopChannel bool, pid int64, ref string) {
299 c.mu.Lock()
300 cn.cm = c
301 cn.trace.cm = c
302 c.channels[id] = cn
303 if isTopChannel {
304 c.topLevelChannels[id] = struct{}{}
305 } else {
306 c.findEntry(pid).addChild(id, cn)
307 }
308 c.mu.Unlock()
309}
310
311func (c *channelMap) addSubChannel(id int64, sc *subChannel, pid int64, ref string) {
312 c.mu.Lock()
313 sc.cm = c
314 sc.trace.cm = c
315 c.subChannels[id] = sc
316 c.findEntry(pid).addChild(id, sc)
317 c.mu.Unlock()
318}
319
320func (c *channelMap) addListenSocket(id int64, ls *listenSocket, pid int64, ref string) {
321 c.mu.Lock()
322 ls.cm = c
323 c.listenSockets[id] = ls
324 c.findEntry(pid).addChild(id, ls)
325 c.mu.Unlock()
326}
327
328func (c *channelMap) addNormalSocket(id int64, ns *normalSocket, pid int64, ref string) {
329 c.mu.Lock()
330 ns.cm = c
331 c.normalSockets[id] = ns
332 c.findEntry(pid).addChild(id, ns)
333 c.mu.Unlock()
334}
335
336// removeEntry triggers the removal of an entry, which may not indeed delete the entry, if it has to
337// wait on the deletion of its children and until no other entity's channel trace references it.
338// It may lead to a chain of entry deletion. For example, deleting the last socket of a gracefully
339// shutting down server will lead to the server being also deleted.
340func (c *channelMap) removeEntry(id int64) {
341 c.mu.Lock()
342 c.findEntry(id).triggerDelete()
343 c.mu.Unlock()
344}
345
346// c.mu must be held by the caller
347func (c *channelMap) decrTraceRefCount(id int64) {
348 e := c.findEntry(id)
349 if v, ok := e.(tracedChannel); ok {
350 v.decrTraceRefCount()
351 e.deleteSelfIfReady()
352 }
353}
354
355// c.mu must be held by the caller.
356func (c *channelMap) findEntry(id int64) entry {
357 var v entry
358 var ok bool
359 if v, ok = c.channels[id]; ok {
360 return v
361 }
362 if v, ok = c.subChannels[id]; ok {
363 return v
364 }
365 if v, ok = c.servers[id]; ok {
366 return v
367 }
368 if v, ok = c.listenSockets[id]; ok {
369 return v
370 }
371 if v, ok = c.normalSockets[id]; ok {
372 return v
373 }
374 return &dummyEntry{idNotFound: id}
375}
376
377// c.mu must be held by the caller
378// deleteEntry simply deletes an entry from the channelMap. Before calling this
379// method, caller must check this entry is ready to be deleted, i.e removeEntry()
380// has been called on it, and no children still exist.
381// Conditionals are ordered by the expected frequency of deletion of each entity
382// type, in order to optimize performance.
383func (c *channelMap) deleteEntry(id int64) {
384 var ok bool
385 if _, ok = c.normalSockets[id]; ok {
386 delete(c.normalSockets, id)
387 return
388 }
389 if _, ok = c.subChannels[id]; ok {
390 delete(c.subChannels, id)
391 return
392 }
393 if _, ok = c.channels[id]; ok {
394 delete(c.channels, id)
395 delete(c.topLevelChannels, id)
396 return
397 }
398 if _, ok = c.listenSockets[id]; ok {
399 delete(c.listenSockets, id)
400 return
401 }
402 if _, ok = c.servers[id]; ok {
403 delete(c.servers, id)
404 return
405 }
406}
407
408func (c *channelMap) traceEvent(id int64, desc *TraceEventDesc) {
409 c.mu.Lock()
410 child := c.findEntry(id)
411 childTC, ok := child.(tracedChannel)
412 if !ok {
413 c.mu.Unlock()
414 return
415 }
416 childTC.getChannelTrace().append(&TraceEvent{Desc: desc.Desc, Severity: desc.Severity, Timestamp: time.Now()})
417 if desc.Parent != nil {
418 parent := c.findEntry(child.getParentID())
419 var chanType RefChannelType
420 switch child.(type) {
421 case *channel:
422 chanType = RefChannel
423 case *subChannel:
424 chanType = RefSubChannel
425 }
426 if parentTC, ok := parent.(tracedChannel); ok {
427 parentTC.getChannelTrace().append(&TraceEvent{
428 Desc: desc.Parent.Desc,
429 Severity: desc.Parent.Severity,
430 Timestamp: time.Now(),
431 RefID: id,
432 RefName: childTC.getRefName(),
433 RefType: chanType,
434 })
435 childTC.incrTraceRefCount()
436 }
437 }
438 c.mu.Unlock()
439}
440
441type int64Slice []int64
442
443func (s int64Slice) Len() int { return len(s) }
444func (s int64Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
445func (s int64Slice) Less(i, j int) bool { return s[i] < s[j] }
446
447func copyMap(m map[int64]string) map[int64]string {
448 n := make(map[int64]string)
449 for k, v := range m {
450 n[k] = v
451 }
452 return n
453}
454
455func min(a, b int64) int64 {
456 if a < b {
457 return a
458 }
459 return b
460}
461
462func (c *channelMap) GetTopChannels(id int64, maxResults int64) ([]*ChannelMetric, bool) {
463 if maxResults <= 0 {
464 maxResults = EntryPerPage
465 }
466 c.mu.RLock()
467 l := int64(len(c.topLevelChannels))
468 ids := make([]int64, 0, l)
469 cns := make([]*channel, 0, min(l, maxResults))
470
471 for k := range c.topLevelChannels {
472 ids = append(ids, k)
473 }
474 sort.Sort(int64Slice(ids))
475 idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= id })
476 count := int64(0)
477 var end bool
478 var t []*ChannelMetric
479 for i, v := range ids[idx:] {
480 if count == maxResults {
481 break
482 }
483 if cn, ok := c.channels[v]; ok {
484 cns = append(cns, cn)
485 t = append(t, &ChannelMetric{
486 NestedChans: copyMap(cn.nestedChans),
487 SubChans: copyMap(cn.subChans),
488 })
489 count++
490 }
491 if i == len(ids[idx:])-1 {
492 end = true
493 break
494 }
495 }
496 c.mu.RUnlock()
497 if count == 0 {
498 end = true
499 }
500
501 for i, cn := range cns {
502 t[i].ChannelData = cn.c.ChannelzMetric()
503 t[i].ID = cn.id
504 t[i].RefName = cn.refName
505 t[i].Trace = cn.trace.dumpData()
506 }
507 return t, end
508}
509
510func (c *channelMap) GetServers(id, maxResults int64) ([]*ServerMetric, bool) {
511 if maxResults <= 0 {
512 maxResults = EntryPerPage
513 }
514 c.mu.RLock()
515 l := int64(len(c.servers))
516 ids := make([]int64, 0, l)
517 ss := make([]*server, 0, min(l, maxResults))
518 for k := range c.servers {
519 ids = append(ids, k)
520 }
521 sort.Sort(int64Slice(ids))
522 idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= id })
523 count := int64(0)
524 var end bool
525 var s []*ServerMetric
526 for i, v := range ids[idx:] {
527 if count == maxResults {
528 break
529 }
530 if svr, ok := c.servers[v]; ok {
531 ss = append(ss, svr)
532 s = append(s, &ServerMetric{
533 ListenSockets: copyMap(svr.listenSockets),
534 })
535 count++
536 }
537 if i == len(ids[idx:])-1 {
538 end = true
539 break
540 }
541 }
542 c.mu.RUnlock()
543 if count == 0 {
544 end = true
545 }
546
547 for i, svr := range ss {
548 s[i].ServerData = svr.s.ChannelzMetric()
549 s[i].ID = svr.id
550 s[i].RefName = svr.refName
551 }
552 return s, end
553}
554
555func (c *channelMap) GetServerSockets(id int64, startID int64, maxResults int64) ([]*SocketMetric, bool) {
556 if maxResults <= 0 {
557 maxResults = EntryPerPage
558 }
559 var svr *server
560 var ok bool
561 c.mu.RLock()
562 if svr, ok = c.servers[id]; !ok {
563 // server with id doesn't exist.
564 c.mu.RUnlock()
565 return nil, true
566 }
567 svrskts := svr.sockets
568 l := int64(len(svrskts))
569 ids := make([]int64, 0, l)
570 sks := make([]*normalSocket, 0, min(l, maxResults))
571 for k := range svrskts {
572 ids = append(ids, k)
573 }
574 sort.Sort(int64Slice(ids))
575 idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= startID })
576 count := int64(0)
577 var end bool
578 for i, v := range ids[idx:] {
579 if count == maxResults {
580 break
581 }
582 if ns, ok := c.normalSockets[v]; ok {
583 sks = append(sks, ns)
584 count++
585 }
586 if i == len(ids[idx:])-1 {
587 end = true
588 break
589 }
590 }
591 c.mu.RUnlock()
592 if count == 0 {
593 end = true
594 }
595 var s []*SocketMetric
596 for _, ns := range sks {
597 sm := &SocketMetric{}
598 sm.SocketData = ns.s.ChannelzMetric()
599 sm.ID = ns.id
600 sm.RefName = ns.refName
601 s = append(s, sm)
602 }
603 return s, end
604}
605
606func (c *channelMap) GetChannel(id int64) *ChannelMetric {
607 cm := &ChannelMetric{}
608 var cn *channel
609 var ok bool
610 c.mu.RLock()
611 if cn, ok = c.channels[id]; !ok {
612 // channel with id doesn't exist.
613 c.mu.RUnlock()
614 return nil
615 }
616 cm.NestedChans = copyMap(cn.nestedChans)
617 cm.SubChans = copyMap(cn.subChans)
618 // cn.c can be set to &dummyChannel{} when deleteSelfFromMap is called. Save a copy of cn.c when
619 // holding the lock to prevent potential data race.
620 chanCopy := cn.c
621 c.mu.RUnlock()
622 cm.ChannelData = chanCopy.ChannelzMetric()
623 cm.ID = cn.id
624 cm.RefName = cn.refName
625 cm.Trace = cn.trace.dumpData()
626 return cm
627}
628
629func (c *channelMap) GetSubChannel(id int64) *SubChannelMetric {
630 cm := &SubChannelMetric{}
631 var sc *subChannel
632 var ok bool
633 c.mu.RLock()
634 if sc, ok = c.subChannels[id]; !ok {
635 // subchannel with id doesn't exist.
636 c.mu.RUnlock()
637 return nil
638 }
639 cm.Sockets = copyMap(sc.sockets)
640 // sc.c can be set to &dummyChannel{} when deleteSelfFromMap is called. Save a copy of sc.c when
641 // holding the lock to prevent potential data race.
642 chanCopy := sc.c
643 c.mu.RUnlock()
644 cm.ChannelData = chanCopy.ChannelzMetric()
645 cm.ID = sc.id
646 cm.RefName = sc.refName
647 cm.Trace = sc.trace.dumpData()
648 return cm
649}
650
651func (c *channelMap) GetSocket(id int64) *SocketMetric {
652 sm := &SocketMetric{}
653 c.mu.RLock()
654 if ls, ok := c.listenSockets[id]; ok {
655 c.mu.RUnlock()
656 sm.SocketData = ls.s.ChannelzMetric()
657 sm.ID = ls.id
658 sm.RefName = ls.refName
659 return sm
660 }
661 if ns, ok := c.normalSockets[id]; ok {
662 c.mu.RUnlock()
663 sm.SocketData = ns.s.ChannelzMetric()
664 sm.ID = ns.id
665 sm.RefName = ns.refName
666 return sm
667 }
668 c.mu.RUnlock()
669 return nil
670}
671
672func (c *channelMap) GetServer(id int64) *ServerMetric {
673 sm := &ServerMetric{}
674 var svr *server
675 var ok bool
676 c.mu.RLock()
677 if svr, ok = c.servers[id]; !ok {
678 c.mu.RUnlock()
679 return nil
680 }
681 sm.ListenSockets = copyMap(svr.listenSockets)
682 c.mu.RUnlock()
683 sm.ID = svr.id
684 sm.RefName = svr.refName
685 sm.ServerData = svr.s.ChannelzMetric()
686 return sm
687}
688
689type idGenerator struct {
690 id int64
691}
692
693func (i *idGenerator) reset() {
694 atomic.StoreInt64(&i.id, 0)
695}
696
697func (i *idGenerator) genID() int64 {
698 return atomic.AddInt64(&i.id, 1)
699}
diff --git a/vendor/google.golang.org/grpc/internal/channelz/types.go b/vendor/google.golang.org/grpc/internal/channelz/types.go
new file mode 100644
index 0000000..17c2274
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/channelz/types.go
@@ -0,0 +1,702 @@
1/*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package channelz
20
21import (
22 "net"
23 "sync"
24 "sync/atomic"
25 "time"
26
27 "google.golang.org/grpc/connectivity"
28 "google.golang.org/grpc/credentials"
29 "google.golang.org/grpc/grpclog"
30)
31
32// entry represents a node in the channelz database.
33type entry interface {
34 // addChild adds a child e, whose channelz id is id to child list
35 addChild(id int64, e entry)
36 // deleteChild deletes a child with channelz id to be id from child list
37 deleteChild(id int64)
38 // triggerDelete tries to delete self from channelz database. However, if child
39 // list is not empty, then deletion from the database is on hold until the last
40 // child is deleted from database.
41 triggerDelete()
42 // deleteSelfIfReady check whether triggerDelete() has been called before, and whether child
43 // list is now empty. If both conditions are met, then delete self from database.
44 deleteSelfIfReady()
45 // getParentID returns parent ID of the entry. 0 value parent ID means no parent.
46 getParentID() int64
47}
48
49// dummyEntry is a fake entry to handle entry not found case.
50type dummyEntry struct {
51 idNotFound int64
52}
53
54func (d *dummyEntry) addChild(id int64, e entry) {
55 // Note: It is possible for a normal program to reach here under race condition.
56 // For example, there could be a race between ClientConn.Close() info being propagated
57 // to addrConn and http2Client. ClientConn.Close() cancel the context and result
58 // in http2Client to error. The error info is then caught by transport monitor
59 // and before addrConn.tearDown() is called in side ClientConn.Close(). Therefore,
60 // the addrConn will create a new transport. And when registering the new transport in
61 // channelz, its parent addrConn could have already been torn down and deleted
62 // from channelz tracking, and thus reach the code here.
63 grpclog.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)
64}
65
66func (d *dummyEntry) deleteChild(id int64) {
67 // It is possible for a normal program to reach here under race condition.
68 // Refer to the example described in addChild().
69 grpclog.Infof("attempt to delete child with id %d from a parent (id=%d) that doesn't currently exist", id, d.idNotFound)
70}
71
72func (d *dummyEntry) triggerDelete() {
73 grpclog.Warningf("attempt to delete an entry (id=%d) that doesn't currently exist", d.idNotFound)
74}
75
76func (*dummyEntry) deleteSelfIfReady() {
77 // code should not reach here. deleteSelfIfReady is always called on an existing entry.
78}
79
80func (*dummyEntry) getParentID() int64 {
81 return 0
82}
83
84// ChannelMetric defines the info channelz provides for a specific Channel, which
85// includes ChannelInternalMetric and channelz-specific data, such as channelz id,
86// child list, etc.
87type ChannelMetric struct {
88 // ID is the channelz id of this channel.
89 ID int64
90 // RefName is the human readable reference string of this channel.
91 RefName string
92 // ChannelData contains channel internal metric reported by the channel through
93 // ChannelzMetric().
94 ChannelData *ChannelInternalMetric
95 // NestedChans tracks the nested channel type children of this channel in the format of
96 // a map from nested channel channelz id to corresponding reference string.
97 NestedChans map[int64]string
98 // SubChans tracks the subchannel type children of this channel in the format of a
99 // map from subchannel channelz id to corresponding reference string.
100 SubChans map[int64]string
101 // Sockets tracks the socket type children of this channel in the format of a map
102 // from socket channelz id to corresponding reference string.
103 // Note current grpc implementation doesn't allow channel having sockets directly,
104 // therefore, this is field is unused.
105 Sockets map[int64]string
106 // Trace contains the most recent traced events.
107 Trace *ChannelTrace
108}
109
110// SubChannelMetric defines the info channelz provides for a specific SubChannel,
111// which includes ChannelInternalMetric and channelz-specific data, such as
112// channelz id, child list, etc.
113type SubChannelMetric struct {
114 // ID is the channelz id of this subchannel.
115 ID int64
116 // RefName is the human readable reference string of this subchannel.
117 RefName string
118 // ChannelData contains subchannel internal metric reported by the subchannel
119 // through ChannelzMetric().
120 ChannelData *ChannelInternalMetric
121 // NestedChans tracks the nested channel type children of this subchannel in the format of
122 // a map from nested channel channelz id to corresponding reference string.
123 // Note current grpc implementation doesn't allow subchannel to have nested channels
124 // as children, therefore, this field is unused.
125 NestedChans map[int64]string
126 // SubChans tracks the subchannel type children of this subchannel in the format of a
127 // map from subchannel channelz id to corresponding reference string.
128 // Note current grpc implementation doesn't allow subchannel to have subchannels
129 // as children, therefore, this field is unused.
130 SubChans map[int64]string
131 // Sockets tracks the socket type children of this subchannel in the format of a map
132 // from socket channelz id to corresponding reference string.
133 Sockets map[int64]string
134 // Trace contains the most recent traced events.
135 Trace *ChannelTrace
136}
137
138// ChannelInternalMetric defines the struct that the implementor of Channel interface
139// should return from ChannelzMetric().
140type ChannelInternalMetric struct {
141 // current connectivity state of the channel.
142 State connectivity.State
143 // The target this channel originally tried to connect to. May be absent
144 Target string
145 // The number of calls started on the channel.
146 CallsStarted int64
147 // The number of calls that have completed with an OK status.
148 CallsSucceeded int64
149 // The number of calls that have a completed with a non-OK status.
150 CallsFailed int64
151 // The last time a call was started on the channel.
152 LastCallStartedTimestamp time.Time
153}
154
155// ChannelTrace stores traced events on a channel/subchannel and related info.
156type ChannelTrace struct {
157 // EventNum is the number of events that ever got traced (i.e. including those that have been deleted)
158 EventNum int64
159 // CreationTime is the creation time of the trace.
160 CreationTime time.Time
161 // Events stores the most recent trace events (up to $maxTraceEntry, newer event will overwrite the
162 // oldest one)
163 Events []*TraceEvent
164}
165
166// TraceEvent represent a single trace event
167type TraceEvent struct {
168 // Desc is a simple description of the trace event.
169 Desc string
170 // Severity states the severity of this trace event.
171 Severity Severity
172 // Timestamp is the event time.
173 Timestamp time.Time
174 // RefID is the id of the entity that gets referenced in the event. RefID is 0 if no other entity is
175 // involved in this event.
176 // e.g. SubChannel (id: 4[]) Created. --> RefID = 4, RefName = "" (inside [])
177 RefID int64
178 // RefName is the reference name for the entity that gets referenced in the event.
179 RefName string
180 // RefType indicates the referenced entity type, i.e Channel or SubChannel.
181 RefType RefChannelType
182}
183
184// Channel is the interface that should be satisfied in order to be tracked by
185// channelz as Channel or SubChannel.
186type Channel interface {
187 ChannelzMetric() *ChannelInternalMetric
188}
189
190type dummyChannel struct{}
191
192func (d *dummyChannel) ChannelzMetric() *ChannelInternalMetric {
193 return &ChannelInternalMetric{}
194}
195
196type channel struct {
197 refName string
198 c Channel
199 closeCalled bool
200 nestedChans map[int64]string
201 subChans map[int64]string
202 id int64
203 pid int64
204 cm *channelMap
205 trace *channelTrace
206 // traceRefCount is the number of trace events that reference this channel.
207 // Non-zero traceRefCount means the trace of this channel cannot be deleted.
208 traceRefCount int32
209}
210
211func (c *channel) addChild(id int64, e entry) {
212 switch v := e.(type) {
213 case *subChannel:
214 c.subChans[id] = v.refName
215 case *channel:
216 c.nestedChans[id] = v.refName
217 default:
218 grpclog.Errorf("cannot add a child (id = %d) of type %T to a channel", id, e)
219 }
220}
221
222func (c *channel) deleteChild(id int64) {
223 delete(c.subChans, id)
224 delete(c.nestedChans, id)
225 c.deleteSelfIfReady()
226}
227
228func (c *channel) triggerDelete() {
229 c.closeCalled = true
230 c.deleteSelfIfReady()
231}
232
233func (c *channel) getParentID() int64 {
234 return c.pid
235}
236
237// deleteSelfFromTree tries to delete the channel from the channelz entry relation tree, which means
238// deleting the channel reference from its parent's child list.
239//
240// In order for a channel to be deleted from the tree, it must meet the criteria that, removal of the
241// corresponding grpc object has been invoked, and the channel does not have any children left.
242//
243// The returned boolean value indicates whether the channel has been successfully deleted from tree.
244func (c *channel) deleteSelfFromTree() (deleted bool) {
245 if !c.closeCalled || len(c.subChans)+len(c.nestedChans) != 0 {
246 return false
247 }
248 // not top channel
249 if c.pid != 0 {
250 c.cm.findEntry(c.pid).deleteChild(c.id)
251 }
252 return true
253}
254
255// deleteSelfFromMap checks whether it is valid to delete the channel from the map, which means
256// deleting the channel from channelz's tracking entirely. Users can no longer use id to query the
257// channel, and its memory will be garbage collected.
258//
259// The trace reference count of the channel must be 0 in order to be deleted from the map. This is
260// specified in the channel tracing gRFC that as long as some other trace has reference to an entity,
261// the trace of the referenced entity must not be deleted. In order to release the resource allocated
262// by grpc, the reference to the grpc object is reset to a dummy object.
263//
264// deleteSelfFromMap must be called after deleteSelfFromTree returns true.
265//
266// It returns a bool to indicate whether the channel can be safely deleted from map.
267func (c *channel) deleteSelfFromMap() (delete bool) {
268 if c.getTraceRefCount() != 0 {
269 c.c = &dummyChannel{}
270 return false
271 }
272 return true
273}
274
275// deleteSelfIfReady tries to delete the channel itself from the channelz database.
276// The delete process includes two steps:
277// 1. delete the channel from the entry relation tree, i.e. delete the channel reference from its
278// parent's child list.
279// 2. delete the channel from the map, i.e. delete the channel entirely from channelz. Lookup by id
280// will return entry not found error.
281func (c *channel) deleteSelfIfReady() {
282 if !c.deleteSelfFromTree() {
283 return
284 }
285 if !c.deleteSelfFromMap() {
286 return
287 }
288 c.cm.deleteEntry(c.id)
289 c.trace.clear()
290}
291
292func (c *channel) getChannelTrace() *channelTrace {
293 return c.trace
294}
295
296func (c *channel) incrTraceRefCount() {
297 atomic.AddInt32(&c.traceRefCount, 1)
298}
299
300func (c *channel) decrTraceRefCount() {
301 atomic.AddInt32(&c.traceRefCount, -1)
302}
303
304func (c *channel) getTraceRefCount() int {
305 i := atomic.LoadInt32(&c.traceRefCount)
306 return int(i)
307}
308
309func (c *channel) getRefName() string {
310 return c.refName
311}
312
313type subChannel struct {
314 refName string
315 c Channel
316 closeCalled bool
317 sockets map[int64]string
318 id int64
319 pid int64
320 cm *channelMap
321 trace *channelTrace
322 traceRefCount int32
323}
324
325func (sc *subChannel) addChild(id int64, e entry) {
326 if v, ok := e.(*normalSocket); ok {
327 sc.sockets[id] = v.refName
328 } else {
329 grpclog.Errorf("cannot add a child (id = %d) of type %T to a subChannel", id, e)
330 }
331}
332
333func (sc *subChannel) deleteChild(id int64) {
334 delete(sc.sockets, id)
335 sc.deleteSelfIfReady()
336}
337
338func (sc *subChannel) triggerDelete() {
339 sc.closeCalled = true
340 sc.deleteSelfIfReady()
341}
342
343func (sc *subChannel) getParentID() int64 {
344 return sc.pid
345}
346
347// deleteSelfFromTree tries to delete the subchannel from the channelz entry relation tree, which
348// means deleting the subchannel reference from its parent's child list.
349//
350// In order for a subchannel to be deleted from the tree, it must meet the criteria that, removal of
351// the corresponding grpc object has been invoked, and the subchannel does not have any children left.
352//
353// The returned boolean value indicates whether the channel has been successfully deleted from tree.
354func (sc *subChannel) deleteSelfFromTree() (deleted bool) {
355 if !sc.closeCalled || len(sc.sockets) != 0 {
356 return false
357 }
358 sc.cm.findEntry(sc.pid).deleteChild(sc.id)
359 return true
360}
361
362// deleteSelfFromMap checks whether it is valid to delete the subchannel from the map, which means
363// deleting the subchannel from channelz's tracking entirely. Users can no longer use id to query
364// the subchannel, and its memory will be garbage collected.
365//
366// The trace reference count of the subchannel must be 0 in order to be deleted from the map. This is
367// specified in the channel tracing gRFC that as long as some other trace has reference to an entity,
368// the trace of the referenced entity must not be deleted. In order to release the resource allocated
369// by grpc, the reference to the grpc object is reset to a dummy object.
370//
371// deleteSelfFromMap must be called after deleteSelfFromTree returns true.
372//
373// It returns a bool to indicate whether the channel can be safely deleted from map.
374func (sc *subChannel) deleteSelfFromMap() (delete bool) {
375 if sc.getTraceRefCount() != 0 {
376 // free the grpc struct (i.e. addrConn)
377 sc.c = &dummyChannel{}
378 return false
379 }
380 return true
381}
382
383// deleteSelfIfReady tries to delete the subchannel itself from the channelz database.
384// The delete process includes two steps:
385// 1. delete the subchannel from the entry relation tree, i.e. delete the subchannel reference from
386// its parent's child list.
387// 2. delete the subchannel from the map, i.e. delete the subchannel entirely from channelz. Lookup
388// by id will return entry not found error.
389func (sc *subChannel) deleteSelfIfReady() {
390 if !sc.deleteSelfFromTree() {
391 return
392 }
393 if !sc.deleteSelfFromMap() {
394 return
395 }
396 sc.cm.deleteEntry(sc.id)
397 sc.trace.clear()
398}
399
400func (sc *subChannel) getChannelTrace() *channelTrace {
401 return sc.trace
402}
403
404func (sc *subChannel) incrTraceRefCount() {
405 atomic.AddInt32(&sc.traceRefCount, 1)
406}
407
408func (sc *subChannel) decrTraceRefCount() {
409 atomic.AddInt32(&sc.traceRefCount, -1)
410}
411
412func (sc *subChannel) getTraceRefCount() int {
413 i := atomic.LoadInt32(&sc.traceRefCount)
414 return int(i)
415}
416
417func (sc *subChannel) getRefName() string {
418 return sc.refName
419}
420
421// SocketMetric defines the info channelz provides for a specific Socket, which
422// includes SocketInternalMetric and channelz-specific data, such as channelz id, etc.
423type SocketMetric struct {
424 // ID is the channelz id of this socket.
425 ID int64
426 // RefName is the human readable reference string of this socket.
427 RefName string
428 // SocketData contains socket internal metric reported by the socket through
429 // ChannelzMetric().
430 SocketData *SocketInternalMetric
431}
432
433// SocketInternalMetric defines the struct that the implementor of Socket interface
434// should return from ChannelzMetric().
435type SocketInternalMetric struct {
436 // The number of streams that have been started.
437 StreamsStarted int64
438 // The number of streams that have ended successfully:
439 // On client side, receiving frame with eos bit set.
440 // On server side, sending frame with eos bit set.
441 StreamsSucceeded int64
442 // The number of streams that have ended unsuccessfully:
443 // On client side, termination without receiving frame with eos bit set.
444 // On server side, termination without sending frame with eos bit set.
445 StreamsFailed int64
446 // The number of messages successfully sent on this socket.
447 MessagesSent int64
448 MessagesReceived int64
449 // The number of keep alives sent. This is typically implemented with HTTP/2
450 // ping messages.
451 KeepAlivesSent int64
452 // The last time a stream was created by this endpoint. Usually unset for
453 // servers.
454 LastLocalStreamCreatedTimestamp time.Time
455 // The last time a stream was created by the remote endpoint. Usually unset
456 // for clients.
457 LastRemoteStreamCreatedTimestamp time.Time
458 // The last time a message was sent by this endpoint.
459 LastMessageSentTimestamp time.Time
460 // The last time a message was received by this endpoint.
461 LastMessageReceivedTimestamp time.Time
462 // The amount of window, granted to the local endpoint by the remote endpoint.
463 // This may be slightly out of date due to network latency. This does NOT
464 // include stream level or TCP level flow control info.
465 LocalFlowControlWindow int64
466 // The amount of window, granted to the remote endpoint by the local endpoint.
467 // This may be slightly out of date due to network latency. This does NOT
468 // include stream level or TCP level flow control info.
469 RemoteFlowControlWindow int64
470 // The locally bound address.
471 LocalAddr net.Addr
472 // The remote bound address. May be absent.
473 RemoteAddr net.Addr
474 // Optional, represents the name of the remote endpoint, if different than
475 // the original target name.
476 RemoteName string
477 SocketOptions *SocketOptionData
478 Security credentials.ChannelzSecurityValue
479}
480
481// Socket is the interface that should be satisfied in order to be tracked by
482// channelz as Socket.
483type Socket interface {
484 ChannelzMetric() *SocketInternalMetric
485}
486
487type listenSocket struct {
488 refName string
489 s Socket
490 id int64
491 pid int64
492 cm *channelMap
493}
494
495func (ls *listenSocket) addChild(id int64, e entry) {
496 grpclog.Errorf("cannot add a child (id = %d) of type %T to a listen socket", id, e)
497}
498
499func (ls *listenSocket) deleteChild(id int64) {
500 grpclog.Errorf("cannot delete a child (id = %d) from a listen socket", id)
501}
502
503func (ls *listenSocket) triggerDelete() {
504 ls.cm.deleteEntry(ls.id)
505 ls.cm.findEntry(ls.pid).deleteChild(ls.id)
506}
507
508func (ls *listenSocket) deleteSelfIfReady() {
509 grpclog.Errorf("cannot call deleteSelfIfReady on a listen socket")
510}
511
512func (ls *listenSocket) getParentID() int64 {
513 return ls.pid
514}
515
516type normalSocket struct {
517 refName string
518 s Socket
519 id int64
520 pid int64
521 cm *channelMap
522}
523
524func (ns *normalSocket) addChild(id int64, e entry) {
525 grpclog.Errorf("cannot add a child (id = %d) of type %T to a normal socket", id, e)
526}
527
528func (ns *normalSocket) deleteChild(id int64) {
529 grpclog.Errorf("cannot delete a child (id = %d) from a normal socket", id)
530}
531
532func (ns *normalSocket) triggerDelete() {
533 ns.cm.deleteEntry(ns.id)
534 ns.cm.findEntry(ns.pid).deleteChild(ns.id)
535}
536
537func (ns *normalSocket) deleteSelfIfReady() {
538 grpclog.Errorf("cannot call deleteSelfIfReady on a normal socket")
539}
540
541func (ns *normalSocket) getParentID() int64 {
542 return ns.pid
543}
544
545// ServerMetric defines the info channelz provides for a specific Server, which
546// includes ServerInternalMetric and channelz-specific data, such as channelz id,
547// child list, etc.
548type ServerMetric struct {
549 // ID is the channelz id of this server.
550 ID int64
551 // RefName is the human readable reference string of this server.
552 RefName string
553 // ServerData contains server internal metric reported by the server through
554 // ChannelzMetric().
555 ServerData *ServerInternalMetric
556 // ListenSockets tracks the listener socket type children of this server in the
557 // format of a map from socket channelz id to corresponding reference string.
558 ListenSockets map[int64]string
559}
560
561// ServerInternalMetric defines the struct that the implementor of Server interface
562// should return from ChannelzMetric().
563type ServerInternalMetric struct {
564 // The number of incoming calls started on the server.
565 CallsStarted int64
566 // The number of incoming calls that have completed with an OK status.
567 CallsSucceeded int64
568 // The number of incoming calls that have a completed with a non-OK status.
569 CallsFailed int64
570 // The last time a call was started on the server.
571 LastCallStartedTimestamp time.Time
572}
573
574// Server is the interface to be satisfied in order to be tracked by channelz as
575// Server.
576type Server interface {
577 ChannelzMetric() *ServerInternalMetric
578}
579
580type server struct {
581 refName string
582 s Server
583 closeCalled bool
584 sockets map[int64]string
585 listenSockets map[int64]string
586 id int64
587 cm *channelMap
588}
589
590func (s *server) addChild(id int64, e entry) {
591 switch v := e.(type) {
592 case *normalSocket:
593 s.sockets[id] = v.refName
594 case *listenSocket:
595 s.listenSockets[id] = v.refName
596 default:
597 grpclog.Errorf("cannot add a child (id = %d) of type %T to a server", id, e)
598 }
599}
600
601func (s *server) deleteChild(id int64) {
602 delete(s.sockets, id)
603 delete(s.listenSockets, id)
604 s.deleteSelfIfReady()
605}
606
607func (s *server) triggerDelete() {
608 s.closeCalled = true
609 s.deleteSelfIfReady()
610}
611
612func (s *server) deleteSelfIfReady() {
613 if !s.closeCalled || len(s.sockets)+len(s.listenSockets) != 0 {
614 return
615 }
616 s.cm.deleteEntry(s.id)
617}
618
619func (s *server) getParentID() int64 {
620 return 0
621}
622
623type tracedChannel interface {
624 getChannelTrace() *channelTrace
625 incrTraceRefCount()
626 decrTraceRefCount()
627 getRefName() string
628}
629
630type channelTrace struct {
631 cm *channelMap
632 createdTime time.Time
633 eventCount int64
634 mu sync.Mutex
635 events []*TraceEvent
636}
637
638func (c *channelTrace) append(e *TraceEvent) {
639 c.mu.Lock()
640 if len(c.events) == getMaxTraceEntry() {
641 del := c.events[0]
642 c.events = c.events[1:]
643 if del.RefID != 0 {
644 // start recursive cleanup in a goroutine to not block the call originated from grpc.
645 go func() {
646 // need to acquire c.cm.mu lock to call the unlocked attemptCleanup func.
647 c.cm.mu.Lock()
648 c.cm.decrTraceRefCount(del.RefID)
649 c.cm.mu.Unlock()
650 }()
651 }
652 }
653 e.Timestamp = time.Now()
654 c.events = append(c.events, e)
655 c.eventCount++
656 c.mu.Unlock()
657}
658
659func (c *channelTrace) clear() {
660 c.mu.Lock()
661 for _, e := range c.events {
662 if e.RefID != 0 {
663 // caller should have already held the c.cm.mu lock.
664 c.cm.decrTraceRefCount(e.RefID)
665 }
666 }
667 c.mu.Unlock()
668}
669
670// Severity is the severity level of a trace event.
671// The canonical enumeration of all valid values is here:
672// https://github.com/grpc/grpc-proto/blob/9b13d199cc0d4703c7ea26c9c330ba695866eb23/grpc/channelz/v1/channelz.proto#L126.
673type Severity int
674
675const (
676 // CtUNKNOWN indicates unknown severity of a trace event.
677 CtUNKNOWN Severity = iota
678 // CtINFO indicates info level severity of a trace event.
679 CtINFO
680 // CtWarning indicates warning level severity of a trace event.
681 CtWarning
682 // CtError indicates error level severity of a trace event.
683 CtError
684)
685
686// RefChannelType is the type of the entity being referenced in a trace event.
687type RefChannelType int
688
689const (
690 // RefChannel indicates the referenced entity is a Channel.
691 RefChannel RefChannelType = iota
692 // RefSubChannel indicates the referenced entity is a SubChannel.
693 RefSubChannel
694)
695
696func (c *channelTrace) dumpData() *ChannelTrace {
697 c.mu.Lock()
698 ct := &ChannelTrace{EventNum: c.eventCount, CreationTime: c.createdTime}
699 ct.Events = c.events[:len(c.events)]
700 c.mu.Unlock()
701 return ct
702}
diff --git a/vendor/google.golang.org/grpc/internal/channelz/types_linux.go b/vendor/google.golang.org/grpc/internal/channelz/types_linux.go
new file mode 100644
index 0000000..692dd61
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/channelz/types_linux.go
@@ -0,0 +1,53 @@
1// +build !appengine
2
3/*
4 *
5 * Copyright 2018 gRPC authors.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */
20
21package channelz
22
23import (
24 "syscall"
25
26 "golang.org/x/sys/unix"
27)
28
29// SocketOptionData defines the struct to hold socket option data, and related
30// getter function to obtain info from fd.
31type SocketOptionData struct {
32 Linger *unix.Linger
33 RecvTimeout *unix.Timeval
34 SendTimeout *unix.Timeval
35 TCPInfo *unix.TCPInfo
36}
37
38// Getsockopt defines the function to get socket options requested by channelz.
39// It is to be passed to syscall.RawConn.Control().
40func (s *SocketOptionData) Getsockopt(fd uintptr) {
41 if v, err := unix.GetsockoptLinger(int(fd), syscall.SOL_SOCKET, syscall.SO_LINGER); err == nil {
42 s.Linger = v
43 }
44 if v, err := unix.GetsockoptTimeval(int(fd), syscall.SOL_SOCKET, syscall.SO_RCVTIMEO); err == nil {
45 s.RecvTimeout = v
46 }
47 if v, err := unix.GetsockoptTimeval(int(fd), syscall.SOL_SOCKET, syscall.SO_SNDTIMEO); err == nil {
48 s.SendTimeout = v
49 }
50 if v, err := unix.GetsockoptTCPInfo(int(fd), syscall.SOL_TCP, syscall.TCP_INFO); err == nil {
51 s.TCPInfo = v
52 }
53}
diff --git a/vendor/google.golang.org/grpc/internal/channelz/types_nonlinux.go b/vendor/google.golang.org/grpc/internal/channelz/types_nonlinux.go
new file mode 100644
index 0000000..79edbef
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/channelz/types_nonlinux.go
@@ -0,0 +1,44 @@
1// +build !linux appengine
2
3/*
4 *
5 * Copyright 2018 gRPC authors.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */
20
21package channelz
22
23import (
24 "sync"
25
26 "google.golang.org/grpc/grpclog"
27)
28
29var once sync.Once
30
31// SocketOptionData defines the struct to hold socket option data, and related
32// getter function to obtain info from fd.
33// Windows OS doesn't support Socket Option
34type SocketOptionData struct {
35}
36
37// Getsockopt defines the function to get socket options requested by channelz.
38// It is to be passed to syscall.RawConn.Control().
39// Windows OS doesn't support Socket Option
40func (s *SocketOptionData) Getsockopt(fd uintptr) {
41 once.Do(func() {
42 grpclog.Warningln("Channelz: socket options are not supported on non-linux os and appengine.")
43 })
44}
diff --git a/vendor/google.golang.org/grpc/credentials/credentials_util_go18.go b/vendor/google.golang.org/grpc/internal/channelz/util_linux.go
index 93f0e1d..fdf409d 100644
--- a/vendor/google.golang.org/grpc/credentials/credentials_util_go18.go
+++ b/vendor/google.golang.org/grpc/internal/channelz/util_linux.go
@@ -1,8 +1,8 @@
1// +build go1.8 1// +build linux,!appengine
2 2
3/* 3/*
4 * 4 *
5 * Copyright 2017 gRPC authors. 5 * Copyright 2018 gRPC authors.
6 * 6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License. 8 * you may not use this file except in compliance with the License.
@@ -18,21 +18,22 @@
18 * 18 *
19 */ 19 */
20 20
21package credentials 21package channelz
22 22
23import ( 23import (
24 "crypto/tls" 24 "syscall"
25) 25)
26 26
27// cloneTLSConfig returns a shallow clone of the exported 27// GetSocketOption gets the socket option info of the conn.
28// fields of cfg, ignoring the unexported sync.Once, which 28func GetSocketOption(socket interface{}) *SocketOptionData {
29// contains a mutex and must not be copied. 29 c, ok := socket.(syscall.Conn)
30// 30 if !ok {
31// If cfg is nil, a new zero tls.Config is returned. 31 return nil
32func cloneTLSConfig(cfg *tls.Config) *tls.Config {
33 if cfg == nil {
34 return &tls.Config{}
35 } 32 }
36 33 data := &SocketOptionData{}
37 return cfg.Clone() 34 if rawConn, err := c.SyscallConn(); err == nil {
35 rawConn.Control(data.Getsockopt)
36 return data
37 }
38 return nil
38} 39}
diff --git a/vendor/google.golang.org/grpc/internal/channelz/util_nonlinux.go b/vendor/google.golang.org/grpc/internal/channelz/util_nonlinux.go
new file mode 100644
index 0000000..8864a08
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/channelz/util_nonlinux.go
@@ -0,0 +1,26 @@
1// +build !linux appengine
2
3/*
4 *
5 * Copyright 2018 gRPC authors.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */
20
21package channelz
22
23// GetSocketOption gets the socket option info of the conn.
24func GetSocketOption(c interface{}) *SocketOptionData {
25 return nil
26}
diff --git a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
new file mode 100644
index 0000000..d2193b3
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
@@ -0,0 +1,70 @@
1/*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// Package envconfig contains grpc settings configured by environment variables.
20package envconfig
21
22import (
23 "os"
24 "strings"
25)
26
27const (
28 prefix = "GRPC_GO_"
29 retryStr = prefix + "RETRY"
30 requireHandshakeStr = prefix + "REQUIRE_HANDSHAKE"
31)
32
33// RequireHandshakeSetting describes the settings for handshaking.
34type RequireHandshakeSetting int
35
36const (
37 // RequireHandshakeHybrid (default, deprecated) indicates to not wait for
38 // handshake before considering a connection ready, but wait before
39 // considering successful.
40 RequireHandshakeHybrid RequireHandshakeSetting = iota
41 // RequireHandshakeOn (default after the 1.17 release) indicates to wait
42 // for handshake before considering a connection ready/successful.
43 RequireHandshakeOn
44 // RequireHandshakeOff indicates to not wait for handshake before
45 // considering a connection ready/successful.
46 RequireHandshakeOff
47)
48
49var (
50 // Retry is set if retry is explicitly enabled via "GRPC_GO_RETRY=on".
51 Retry = strings.EqualFold(os.Getenv(retryStr), "on")
52 // RequireHandshake is set based upon the GRPC_GO_REQUIRE_HANDSHAKE
53 // environment variable.
54 //
55 // Will be removed after the 1.18 release.
56 RequireHandshake RequireHandshakeSetting
57)
58
59func init() {
60 switch strings.ToLower(os.Getenv(requireHandshakeStr)) {
61 case "on":
62 default:
63 RequireHandshake = RequireHandshakeOn
64 case "off":
65 RequireHandshake = RequireHandshakeOff
66 case "hybrid":
67 // Will be removed after the 1.17 release.
68 RequireHandshake = RequireHandshakeHybrid
69 }
70}
diff --git a/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go b/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go
new file mode 100644
index 0000000..200b115
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go
@@ -0,0 +1,56 @@
1/*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// Package grpcrand implements math/rand functions in a concurrent-safe way
20// with a global random source, independent of math/rand's global source.
21package grpcrand
22
23import (
24 "math/rand"
25 "sync"
26 "time"
27)
28
29var (
30 r = rand.New(rand.NewSource(time.Now().UnixNano()))
31 mu sync.Mutex
32)
33
34// Int63n implements rand.Int63n on the grpcrand global source.
35func Int63n(n int64) int64 {
36 mu.Lock()
37 res := r.Int63n(n)
38 mu.Unlock()
39 return res
40}
41
42// Intn implements rand.Intn on the grpcrand global source.
43func Intn(n int) int {
44 mu.Lock()
45 res := r.Intn(n)
46 mu.Unlock()
47 return res
48}
49
50// Float64 implements rand.Float64 on the grpcrand global source.
51func Float64() float64 {
52 mu.Lock()
53 res := r.Float64()
54 mu.Unlock()
55 return res
56}
diff --git a/vendor/google.golang.org/grpc/internal/grpcsync/event.go b/vendor/google.golang.org/grpc/internal/grpcsync/event.go
new file mode 100644
index 0000000..fbe697c
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/grpcsync/event.go
@@ -0,0 +1,61 @@
1/*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// Package grpcsync implements additional synchronization primitives built upon
20// the sync package.
21package grpcsync
22
23import (
24 "sync"
25 "sync/atomic"
26)
27
28// Event represents a one-time event that may occur in the future.
29type Event struct {
30 fired int32
31 c chan struct{}
32 o sync.Once
33}
34
35// Fire causes e to complete. It is safe to call multiple times, and
36// concurrently. It returns true iff this call to Fire caused the signaling
37// channel returned by Done to close.
38func (e *Event) Fire() bool {
39 ret := false
40 e.o.Do(func() {
41 atomic.StoreInt32(&e.fired, 1)
42 close(e.c)
43 ret = true
44 })
45 return ret
46}
47
48// Done returns a channel that will be closed when Fire is called.
49func (e *Event) Done() <-chan struct{} {
50 return e.c
51}
52
53// HasFired returns true if Fire has been called.
54func (e *Event) HasFired() bool {
55 return atomic.LoadInt32(&e.fired) == 1
56}
57
58// NewEvent returns a new, ready-to-use Event.
59func NewEvent() *Event {
60 return &Event{c: make(chan struct{})}
61}
diff --git a/vendor/google.golang.org/grpc/internal/internal.go b/vendor/google.golang.org/grpc/internal/internal.go
index 0708383..eaa54d4 100644
--- a/vendor/google.golang.org/grpc/internal/internal.go
+++ b/vendor/google.golang.org/grpc/internal/internal.go
@@ -15,20 +15,36 @@
15 * 15 *
16 */ 16 */
17 17
18// Package internal contains gRPC-internal code for testing, to avoid polluting 18// Package internal contains gRPC-internal code, to avoid polluting
19// the godoc of the top-level grpc package. 19// the godoc of the top-level grpc package. It must not import any grpc
20// symbols to avoid circular dependencies.
20package internal 21package internal
21 22
22// TestingCloseConns closes all existing transports but keeps 23import "context"
23// grpcServer.lis accepting new connections.
24//
25// The provided grpcServer must be of type *grpc.Server. It is untyped
26// for circular dependency reasons.
27var TestingCloseConns func(grpcServer interface{})
28 24
29// TestingUseHandlerImpl enables the http.Handler-based server implementation. 25var (
30// It must be called before Serve and requires TLS credentials. 26 // WithContextDialer is exported by dialoptions.go
31// 27 WithContextDialer interface{} // func(context.Context, string) (net.Conn, error) grpc.DialOption
32// The provided grpcServer must be of type *grpc.Server. It is untyped 28 // WithResolverBuilder is exported by dialoptions.go
33// for circular dependency reasons. 29 WithResolverBuilder interface{} // func (resolver.Builder) grpc.DialOption
34var TestingUseHandlerImpl func(grpcServer interface{}) 30 // WithHealthCheckFunc is not exported by dialoptions.go
31 WithHealthCheckFunc interface{} // func (HealthChecker) DialOption
32 // HealthCheckFunc is used to provide client-side LB channel health checking
33 HealthCheckFunc HealthChecker
34 // BalancerUnregister is exported by package balancer to unregister a balancer.
35 BalancerUnregister func(name string)
36)
37
38// HealthChecker defines the signature of the client-side LB channel health checking function.
39type HealthChecker func(ctx context.Context, newStream func() (interface{}, error), reportHealth func(bool), serviceName string) error
40
41const (
42 // CredsBundleModeFallback switches GoogleDefaultCreds to fallback mode.
43 CredsBundleModeFallback = "fallback"
44 // CredsBundleModeBalancer switches GoogleDefaultCreds to grpclb balancer
45 // mode.
46 CredsBundleModeBalancer = "balancer"
47 // CredsBundleModeBackendFromBalancer switches GoogleDefaultCreds to mode
48 // that supports backend returned by grpclb balancer.
49 CredsBundleModeBackendFromBalancer = "backend-from-balancer"
50)
diff --git a/vendor/google.golang.org/grpc/internal/syscall/syscall_linux.go b/vendor/google.golang.org/grpc/internal/syscall/syscall_linux.go
new file mode 100644
index 0000000..43281a3
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/syscall/syscall_linux.go
@@ -0,0 +1,114 @@
1// +build !appengine
2
3/*
4 *
5 * Copyright 2018 gRPC authors.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */
20
21// Package syscall provides functionalities that grpc uses to get low-level operating system
22// stats/info.
23package syscall
24
25import (
26 "fmt"
27 "net"
28 "syscall"
29 "time"
30
31 "golang.org/x/sys/unix"
32 "google.golang.org/grpc/grpclog"
33)
34
35// GetCPUTime returns the how much CPU time has passed since the start of this process.
36func GetCPUTime() int64 {
37 var ts unix.Timespec
38 if err := unix.ClockGettime(unix.CLOCK_PROCESS_CPUTIME_ID, &ts); err != nil {
39 grpclog.Fatal(err)
40 }
41 return ts.Nano()
42}
43
44// Rusage is an alias for syscall.Rusage under linux non-appengine environment.
45type Rusage syscall.Rusage
46
47// GetRusage returns the resource usage of current process.
48func GetRusage() (rusage *Rusage) {
49 rusage = new(Rusage)
50 syscall.Getrusage(syscall.RUSAGE_SELF, (*syscall.Rusage)(rusage))
51 return
52}
53
54// CPUTimeDiff returns the differences of user CPU time and system CPU time used
55// between two Rusage structs.
56func CPUTimeDiff(first *Rusage, latest *Rusage) (float64, float64) {
57 f := (*syscall.Rusage)(first)
58 l := (*syscall.Rusage)(latest)
59 var (
60 utimeDiffs = l.Utime.Sec - f.Utime.Sec
61 utimeDiffus = l.Utime.Usec - f.Utime.Usec
62 stimeDiffs = l.Stime.Sec - f.Stime.Sec
63 stimeDiffus = l.Stime.Usec - f.Stime.Usec
64 )
65
66 uTimeElapsed := float64(utimeDiffs) + float64(utimeDiffus)*1.0e-6
67 sTimeElapsed := float64(stimeDiffs) + float64(stimeDiffus)*1.0e-6
68
69 return uTimeElapsed, sTimeElapsed
70}
71
72// SetTCPUserTimeout sets the TCP user timeout on a connection's socket
73func SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error {
74 tcpconn, ok := conn.(*net.TCPConn)
75 if !ok {
76 // not a TCP connection. exit early
77 return nil
78 }
79 rawConn, err := tcpconn.SyscallConn()
80 if err != nil {
81 return fmt.Errorf("error getting raw connection: %v", err)
82 }
83 err = rawConn.Control(func(fd uintptr) {
84 err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, int(timeout/time.Millisecond))
85 })
86 if err != nil {
87 return fmt.Errorf("error setting option on socket: %v", err)
88 }
89
90 return nil
91}
92
93// GetTCPUserTimeout gets the TCP user timeout on a connection's socket
94func GetTCPUserTimeout(conn net.Conn) (opt int, err error) {
95 tcpconn, ok := conn.(*net.TCPConn)
96 if !ok {
97 err = fmt.Errorf("conn is not *net.TCPConn. got %T", conn)
98 return
99 }
100 rawConn, err := tcpconn.SyscallConn()
101 if err != nil {
102 err = fmt.Errorf("error getting raw connection: %v", err)
103 return
104 }
105 err = rawConn.Control(func(fd uintptr) {
106 opt, err = syscall.GetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT)
107 })
108 if err != nil {
109 err = fmt.Errorf("error getting option on socket: %v", err)
110 return
111 }
112
113 return
114}
diff --git a/vendor/google.golang.org/grpc/internal/syscall/syscall_nonlinux.go b/vendor/google.golang.org/grpc/internal/syscall/syscall_nonlinux.go
new file mode 100644
index 0000000..61678fe
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/syscall/syscall_nonlinux.go
@@ -0,0 +1,63 @@
1// +build !linux appengine
2
3/*
4 *
5 * Copyright 2018 gRPC authors.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */
20
21package syscall
22
23import (
24 "net"
25 "time"
26
27 "google.golang.org/grpc/grpclog"
28)
29
30func init() {
31 grpclog.Info("CPU time info is unavailable on non-linux or appengine environment.")
32}
33
34// GetCPUTime returns the how much CPU time has passed since the start of this process.
35// It always returns 0 under non-linux or appengine environment.
36func GetCPUTime() int64 {
37 return 0
38}
39
40// Rusage is an empty struct under non-linux or appengine environment.
41type Rusage struct{}
42
43// GetRusage is a no-op function under non-linux or appengine environment.
44func GetRusage() (rusage *Rusage) {
45 return nil
46}
47
48// CPUTimeDiff returns the differences of user CPU time and system CPU time used
49// between two Rusage structs. It a no-op function for non-linux or appengine environment.
50func CPUTimeDiff(first *Rusage, latest *Rusage) (float64, float64) {
51 return 0, 0
52}
53
54// SetTCPUserTimeout is a no-op function under non-linux or appengine environments
55func SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error {
56 return nil
57}
58
59// GetTCPUserTimeout is a no-op function under non-linux or appengine environments
60// a negative return value indicates the operation is not supported
61func GetTCPUserTimeout(conn net.Conn) (int, error) {
62 return -1, nil
63}
diff --git a/vendor/google.golang.org/grpc/transport/bdp_estimator.go b/vendor/google.golang.org/grpc/internal/transport/bdp_estimator.go
index 667edb8..070680e 100644
--- a/vendor/google.golang.org/grpc/transport/bdp_estimator.go
+++ b/vendor/google.golang.org/grpc/internal/transport/bdp_estimator.go
@@ -24,9 +24,10 @@ import (
24) 24)
25 25
26const ( 26const (
27 // bdpLimit is the maximum value the flow control windows 27 // bdpLimit is the maximum value the flow control windows will be increased
28 // will be increased to. 28 // to. TCP typically limits this to 4MB, but some systems go up to 16MB.
29 bdpLimit = (1 << 20) * 4 29 // Since this is only a limit, it is safe to make it optimistic.
30 bdpLimit = (1 << 20) * 16
30 // alpha is a constant factor used to keep a moving average 31 // alpha is a constant factor used to keep a moving average
31 // of RTTs. 32 // of RTTs.
32 alpha = 0.9 33 alpha = 0.9
@@ -41,12 +42,9 @@ const (
41 gamma = 2 42 gamma = 2
42) 43)
43 44
44var ( 45// Adding arbitrary data to ping so that its ack can be identified.
45 // Adding arbitrary data to ping so that its ack can be 46// Easter-egg: what does the ping message say?
46 // identified. 47var bdpPing = &ping{data: [8]byte{2, 4, 16, 16, 9, 14, 7, 7}}
47 // Easter-egg: what does the ping message say?
48 bdpPing = &ping{data: [8]byte{2, 4, 16, 16, 9, 14, 7, 7}}
49)
50 48
51type bdpEstimator struct { 49type bdpEstimator struct {
52 // sentAt is the time when the ping was sent. 50 // sentAt is the time when the ping was sent.
@@ -59,7 +57,7 @@ type bdpEstimator struct {
59 sample uint32 57 sample uint32
60 // bwMax is the maximum bandwidth noted so far (bytes/sec). 58 // bwMax is the maximum bandwidth noted so far (bytes/sec).
61 bwMax float64 59 bwMax float64
62 // bool to keep track of the begining of a new measurement cycle. 60 // bool to keep track of the beginning of a new measurement cycle.
63 isSent bool 61 isSent bool
64 // Callback to update the window sizes. 62 // Callback to update the window sizes.
65 updateFlowControl func(n uint32) 63 updateFlowControl func(n uint32)
@@ -70,7 +68,7 @@ type bdpEstimator struct {
70} 68}
71 69
72// timesnap registers the time bdp ping was sent out so that 70// timesnap registers the time bdp ping was sent out so that
73// network rtt can be calculated when its ack is recieved. 71// network rtt can be calculated when its ack is received.
74// It is called (by controller) when the bdpPing is 72// It is called (by controller) when the bdpPing is
75// being written on the wire. 73// being written on the wire.
76func (b *bdpEstimator) timesnap(d [8]byte) { 74func (b *bdpEstimator) timesnap(d [8]byte) {
@@ -119,7 +117,7 @@ func (b *bdpEstimator) calculate(d [8]byte) {
119 b.rtt += (rttSample - b.rtt) * float64(alpha) 117 b.rtt += (rttSample - b.rtt) * float64(alpha)
120 } 118 }
121 b.isSent = false 119 b.isSent = false
122 // The number of bytes accumalated so far in the sample is smaller 120 // The number of bytes accumulated so far in the sample is smaller
123 // than or equal to 1.5 times the real BDP on a saturated connection. 121 // than or equal to 1.5 times the real BDP on a saturated connection.
124 bwCurrent := float64(b.sample) / (b.rtt * float64(1.5)) 122 bwCurrent := float64(b.sample) / (b.rtt * float64(1.5))
125 if bwCurrent > b.bwMax { 123 if bwCurrent > b.bwMax {
diff --git a/vendor/google.golang.org/grpc/internal/transport/controlbuf.go b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
new file mode 100644
index 0000000..204ba15
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
@@ -0,0 +1,852 @@
1/*
2 *
3 * Copyright 2014 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package transport
20
21import (
22 "bytes"
23 "fmt"
24 "runtime"
25 "sync"
26
27 "golang.org/x/net/http2"
28 "golang.org/x/net/http2/hpack"
29)
30
31var updateHeaderTblSize = func(e *hpack.Encoder, v uint32) {
32 e.SetMaxDynamicTableSizeLimit(v)
33}
34
35type itemNode struct {
36 it interface{}
37 next *itemNode
38}
39
40type itemList struct {
41 head *itemNode
42 tail *itemNode
43}
44
45func (il *itemList) enqueue(i interface{}) {
46 n := &itemNode{it: i}
47 if il.tail == nil {
48 il.head, il.tail = n, n
49 return
50 }
51 il.tail.next = n
52 il.tail = n
53}
54
55// peek returns the first item in the list without removing it from the
56// list.
57func (il *itemList) peek() interface{} {
58 return il.head.it
59}
60
61func (il *itemList) dequeue() interface{} {
62 if il.head == nil {
63 return nil
64 }
65 i := il.head.it
66 il.head = il.head.next
67 if il.head == nil {
68 il.tail = nil
69 }
70 return i
71}
72
73func (il *itemList) dequeueAll() *itemNode {
74 h := il.head
75 il.head, il.tail = nil, nil
76 return h
77}
78
79func (il *itemList) isEmpty() bool {
80 return il.head == nil
81}
82
83// The following defines various control items which could flow through
84// the control buffer of transport. They represent different aspects of
85// control tasks, e.g., flow control, settings, streaming resetting, etc.
86
87// registerStream is used to register an incoming stream with loopy writer.
88type registerStream struct {
89 streamID uint32
90 wq *writeQuota
91}
92
93// headerFrame is also used to register stream on the client-side.
94type headerFrame struct {
95 streamID uint32
96 hf []hpack.HeaderField
97 endStream bool // Valid on server side.
98 initStream func(uint32) (bool, error) // Used only on the client side.
99 onWrite func()
100 wq *writeQuota // write quota for the stream created.
101 cleanup *cleanupStream // Valid on the server side.
102 onOrphaned func(error) // Valid on client-side
103}
104
105type cleanupStream struct {
106 streamID uint32
107 rst bool
108 rstCode http2.ErrCode
109 onWrite func()
110}
111
112type dataFrame struct {
113 streamID uint32
114 endStream bool
115 h []byte
116 d []byte
117 // onEachWrite is called every time
118 // a part of d is written out.
119 onEachWrite func()
120}
121
122type incomingWindowUpdate struct {
123 streamID uint32
124 increment uint32
125}
126
127type outgoingWindowUpdate struct {
128 streamID uint32
129 increment uint32
130}
131
132type incomingSettings struct {
133 ss []http2.Setting
134}
135
136type outgoingSettings struct {
137 ss []http2.Setting
138}
139
140type incomingGoAway struct {
141}
142
143type goAway struct {
144 code http2.ErrCode
145 debugData []byte
146 headsUp bool
147 closeConn bool
148}
149
150type ping struct {
151 ack bool
152 data [8]byte
153}
154
155type outFlowControlSizeRequest struct {
156 resp chan uint32
157}
158
159type outStreamState int
160
161const (
162 active outStreamState = iota
163 empty
164 waitingOnStreamQuota
165)
166
167type outStream struct {
168 id uint32
169 state outStreamState
170 itl *itemList
171 bytesOutStanding int
172 wq *writeQuota
173
174 next *outStream
175 prev *outStream
176}
177
178func (s *outStream) deleteSelf() {
179 if s.prev != nil {
180 s.prev.next = s.next
181 }
182 if s.next != nil {
183 s.next.prev = s.prev
184 }
185 s.next, s.prev = nil, nil
186}
187
188type outStreamList struct {
189 // Following are sentinel objects that mark the
190 // beginning and end of the list. They do not
191 // contain any item lists. All valid objects are
192 // inserted in between them.
193 // This is needed so that an outStream object can
194 // deleteSelf() in O(1) time without knowing which
195 // list it belongs to.
196 head *outStream
197 tail *outStream
198}
199
200func newOutStreamList() *outStreamList {
201 head, tail := new(outStream), new(outStream)
202 head.next = tail
203 tail.prev = head
204 return &outStreamList{
205 head: head,
206 tail: tail,
207 }
208}
209
210func (l *outStreamList) enqueue(s *outStream) {
211 e := l.tail.prev
212 e.next = s
213 s.prev = e
214 s.next = l.tail
215 l.tail.prev = s
216}
217
218// remove from the beginning of the list.
219func (l *outStreamList) dequeue() *outStream {
220 b := l.head.next
221 if b == l.tail {
222 return nil
223 }
224 b.deleteSelf()
225 return b
226}
227
228// controlBuffer is a way to pass information to loopy.
229// Information is passed as specific struct types called control frames.
230// A control frame not only represents data, messages or headers to be sent out
231// but can also be used to instruct loopy to update its internal state.
232// It shouldn't be confused with an HTTP2 frame, although some of the control frames
233// like dataFrame and headerFrame do go out on wire as HTTP2 frames.
234type controlBuffer struct {
235 ch chan struct{}
236 done <-chan struct{}
237 mu sync.Mutex
238 consumerWaiting bool
239 list *itemList
240 err error
241}
242
243func newControlBuffer(done <-chan struct{}) *controlBuffer {
244 return &controlBuffer{
245 ch: make(chan struct{}, 1),
246 list: &itemList{},
247 done: done,
248 }
249}
250
251func (c *controlBuffer) put(it interface{}) error {
252 _, err := c.executeAndPut(nil, it)
253 return err
254}
255
256func (c *controlBuffer) executeAndPut(f func(it interface{}) bool, it interface{}) (bool, error) {
257 var wakeUp bool
258 c.mu.Lock()
259 if c.err != nil {
260 c.mu.Unlock()
261 return false, c.err
262 }
263 if f != nil {
264 if !f(it) { // f wasn't successful
265 c.mu.Unlock()
266 return false, nil
267 }
268 }
269 if c.consumerWaiting {
270 wakeUp = true
271 c.consumerWaiting = false
272 }
273 c.list.enqueue(it)
274 c.mu.Unlock()
275 if wakeUp {
276 select {
277 case c.ch <- struct{}{}:
278 default:
279 }
280 }
281 return true, nil
282}
283
284// Note argument f should never be nil.
285func (c *controlBuffer) execute(f func(it interface{}) bool, it interface{}) (bool, error) {
286 c.mu.Lock()
287 if c.err != nil {
288 c.mu.Unlock()
289 return false, c.err
290 }
291 if !f(it) { // f wasn't successful
292 c.mu.Unlock()
293 return false, nil
294 }
295 c.mu.Unlock()
296 return true, nil
297}
298
299func (c *controlBuffer) get(block bool) (interface{}, error) {
300 for {
301 c.mu.Lock()
302 if c.err != nil {
303 c.mu.Unlock()
304 return nil, c.err
305 }
306 if !c.list.isEmpty() {
307 h := c.list.dequeue()
308 c.mu.Unlock()
309 return h, nil
310 }
311 if !block {
312 c.mu.Unlock()
313 return nil, nil
314 }
315 c.consumerWaiting = true
316 c.mu.Unlock()
317 select {
318 case <-c.ch:
319 case <-c.done:
320 c.finish()
321 return nil, ErrConnClosing
322 }
323 }
324}
325
326func (c *controlBuffer) finish() {
327 c.mu.Lock()
328 if c.err != nil {
329 c.mu.Unlock()
330 return
331 }
332 c.err = ErrConnClosing
333 // There may be headers for streams in the control buffer.
334 // These streams need to be cleaned out since the transport
335 // is still not aware of these yet.
336 for head := c.list.dequeueAll(); head != nil; head = head.next {
337 hdr, ok := head.it.(*headerFrame)
338 if !ok {
339 continue
340 }
341 if hdr.onOrphaned != nil { // It will be nil on the server-side.
342 hdr.onOrphaned(ErrConnClosing)
343 }
344 }
345 c.mu.Unlock()
346}
347
348type side int
349
350const (
351 clientSide side = iota
352 serverSide
353)
354
355// Loopy receives frames from the control buffer.
356// Each frame is handled individually; most of the work done by loopy goes
357// into handling data frames. Loopy maintains a queue of active streams, and each
358// stream maintains a queue of data frames; as loopy receives data frames
359// it gets added to the queue of the relevant stream.
360// Loopy goes over this list of active streams by processing one node every iteration,
361// thereby closely resemebling to a round-robin scheduling over all streams. While
362// processing a stream, loopy writes out data bytes from this stream capped by the min
363// of http2MaxFrameLen, connection-level flow control and stream-level flow control.
364type loopyWriter struct {
365 side side
366 cbuf *controlBuffer
367 sendQuota uint32
368 oiws uint32 // outbound initial window size.
369 // estdStreams is map of all established streams that are not cleaned-up yet.
370 // On client-side, this is all streams whose headers were sent out.
371 // On server-side, this is all streams whose headers were received.
372 estdStreams map[uint32]*outStream // Established streams.
373 // activeStreams is a linked-list of all streams that have data to send and some
374 // stream-level flow control quota.
375 // Each of these streams internally have a list of data items(and perhaps trailers
376 // on the server-side) to be sent out.
377 activeStreams *outStreamList
378 framer *framer
379 hBuf *bytes.Buffer // The buffer for HPACK encoding.
380 hEnc *hpack.Encoder // HPACK encoder.
381 bdpEst *bdpEstimator
382 draining bool
383
384 // Side-specific handlers
385 ssGoAwayHandler func(*goAway) (bool, error)
386}
387
388func newLoopyWriter(s side, fr *framer, cbuf *controlBuffer, bdpEst *bdpEstimator) *loopyWriter {
389 var buf bytes.Buffer
390 l := &loopyWriter{
391 side: s,
392 cbuf: cbuf,
393 sendQuota: defaultWindowSize,
394 oiws: defaultWindowSize,
395 estdStreams: make(map[uint32]*outStream),
396 activeStreams: newOutStreamList(),
397 framer: fr,
398 hBuf: &buf,
399 hEnc: hpack.NewEncoder(&buf),
400 bdpEst: bdpEst,
401 }
402 return l
403}
404
405const minBatchSize = 1000
406
407// run should be run in a separate goroutine.
408// It reads control frames from controlBuf and processes them by:
409// 1. Updating loopy's internal state, or/and
410// 2. Writing out HTTP2 frames on the wire.
411//
412// Loopy keeps all active streams with data to send in a linked-list.
413// All streams in the activeStreams linked-list must have both:
414// 1. Data to send, and
415// 2. Stream level flow control quota available.
416//
417// In each iteration of run loop, other than processing the incoming control
418// frame, loopy calls processData, which processes one node from the activeStreams linked-list.
419// This results in writing of HTTP2 frames into an underlying write buffer.
420// When there's no more control frames to read from controlBuf, loopy flushes the write buffer.
421// As an optimization, to increase the batch size for each flush, loopy yields the processor, once
422// if the batch size is too low to give stream goroutines a chance to fill it up.
423func (l *loopyWriter) run() (err error) {
424 defer func() {
425 if err == ErrConnClosing {
426 // Don't log ErrConnClosing as error since it happens
427 // 1. When the connection is closed by some other known issue.
428 // 2. User closed the connection.
429 // 3. A graceful close of connection.
430 infof("transport: loopyWriter.run returning. %v", err)
431 err = nil
432 }
433 }()
434 for {
435 it, err := l.cbuf.get(true)
436 if err != nil {
437 return err
438 }
439 if err = l.handle(it); err != nil {
440 return err
441 }
442 if _, err = l.processData(); err != nil {
443 return err
444 }
445 gosched := true
446 hasdata:
447 for {
448 it, err := l.cbuf.get(false)
449 if err != nil {
450 return err
451 }
452 if it != nil {
453 if err = l.handle(it); err != nil {
454 return err
455 }
456 if _, err = l.processData(); err != nil {
457 return err
458 }
459 continue hasdata
460 }
461 isEmpty, err := l.processData()
462 if err != nil {
463 return err
464 }
465 if !isEmpty {
466 continue hasdata
467 }
468 if gosched {
469 gosched = false
470 if l.framer.writer.offset < minBatchSize {
471 runtime.Gosched()
472 continue hasdata
473 }
474 }
475 l.framer.writer.Flush()
476 break hasdata
477
478 }
479 }
480}
481
482func (l *loopyWriter) outgoingWindowUpdateHandler(w *outgoingWindowUpdate) error {
483 return l.framer.fr.WriteWindowUpdate(w.streamID, w.increment)
484}
485
486func (l *loopyWriter) incomingWindowUpdateHandler(w *incomingWindowUpdate) error {
487 // Otherwise update the quota.
488 if w.streamID == 0 {
489 l.sendQuota += w.increment
490 return nil
491 }
492 // Find the stream and update it.
493 if str, ok := l.estdStreams[w.streamID]; ok {
494 str.bytesOutStanding -= int(w.increment)
495 if strQuota := int(l.oiws) - str.bytesOutStanding; strQuota > 0 && str.state == waitingOnStreamQuota {
496 str.state = active
497 l.activeStreams.enqueue(str)
498 return nil
499 }
500 }
501 return nil
502}
503
504func (l *loopyWriter) outgoingSettingsHandler(s *outgoingSettings) error {
505 return l.framer.fr.WriteSettings(s.ss...)
506}
507
508func (l *loopyWriter) incomingSettingsHandler(s *incomingSettings) error {
509 if err := l.applySettings(s.ss); err != nil {
510 return err
511 }
512 return l.framer.fr.WriteSettingsAck()
513}
514
515func (l *loopyWriter) registerStreamHandler(h *registerStream) error {
516 str := &outStream{
517 id: h.streamID,
518 state: empty,
519 itl: &itemList{},
520 wq: h.wq,
521 }
522 l.estdStreams[h.streamID] = str
523 return nil
524}
525
526func (l *loopyWriter) headerHandler(h *headerFrame) error {
527 if l.side == serverSide {
528 str, ok := l.estdStreams[h.streamID]
529 if !ok {
530 warningf("transport: loopy doesn't recognize the stream: %d", h.streamID)
531 return nil
532 }
533 // Case 1.A: Server is responding back with headers.
534 if !h.endStream {
535 return l.writeHeader(h.streamID, h.endStream, h.hf, h.onWrite)
536 }
537 // else: Case 1.B: Server wants to close stream.
538
539 if str.state != empty { // either active or waiting on stream quota.
540 // add it str's list of items.
541 str.itl.enqueue(h)
542 return nil
543 }
544 if err := l.writeHeader(h.streamID, h.endStream, h.hf, h.onWrite); err != nil {
545 return err
546 }
547 return l.cleanupStreamHandler(h.cleanup)
548 }
549 // Case 2: Client wants to originate stream.
550 str := &outStream{
551 id: h.streamID,
552 state: empty,
553 itl: &itemList{},
554 wq: h.wq,
555 }
556 str.itl.enqueue(h)
557 return l.originateStream(str)
558}
559
560func (l *loopyWriter) originateStream(str *outStream) error {
561 hdr := str.itl.dequeue().(*headerFrame)
562 sendPing, err := hdr.initStream(str.id)
563 if err != nil {
564 if err == ErrConnClosing {
565 return err
566 }
567 // Other errors(errStreamDrain) need not close transport.
568 return nil
569 }
570 if err = l.writeHeader(str.id, hdr.endStream, hdr.hf, hdr.onWrite); err != nil {
571 return err
572 }
573 l.estdStreams[str.id] = str
574 if sendPing {
575 return l.pingHandler(&ping{data: [8]byte{}})
576 }
577 return nil
578}
579
580func (l *loopyWriter) writeHeader(streamID uint32, endStream bool, hf []hpack.HeaderField, onWrite func()) error {
581 if onWrite != nil {
582 onWrite()
583 }
584 l.hBuf.Reset()
585 for _, f := range hf {
586 if err := l.hEnc.WriteField(f); err != nil {
587 warningf("transport: loopyWriter.writeHeader encountered error while encoding headers:", err)
588 }
589 }
590 var (
591 err error
592 endHeaders, first bool
593 )
594 first = true
595 for !endHeaders {
596 size := l.hBuf.Len()
597 if size > http2MaxFrameLen {
598 size = http2MaxFrameLen
599 } else {
600 endHeaders = true
601 }
602 if first {
603 first = false
604 err = l.framer.fr.WriteHeaders(http2.HeadersFrameParam{
605 StreamID: streamID,
606 BlockFragment: l.hBuf.Next(size),
607 EndStream: endStream,
608 EndHeaders: endHeaders,
609 })
610 } else {
611 err = l.framer.fr.WriteContinuation(
612 streamID,
613 endHeaders,
614 l.hBuf.Next(size),
615 )
616 }
617 if err != nil {
618 return err
619 }
620 }
621 return nil
622}
623
624func (l *loopyWriter) preprocessData(df *dataFrame) error {
625 str, ok := l.estdStreams[df.streamID]
626 if !ok {
627 return nil
628 }
629 // If we got data for a stream it means that
630 // stream was originated and the headers were sent out.
631 str.itl.enqueue(df)
632 if str.state == empty {
633 str.state = active
634 l.activeStreams.enqueue(str)
635 }
636 return nil
637}
638
639func (l *loopyWriter) pingHandler(p *ping) error {
640 if !p.ack {
641 l.bdpEst.timesnap(p.data)
642 }
643 return l.framer.fr.WritePing(p.ack, p.data)
644
645}
646
647func (l *loopyWriter) outFlowControlSizeRequestHandler(o *outFlowControlSizeRequest) error {
648 o.resp <- l.sendQuota
649 return nil
650}
651
652func (l *loopyWriter) cleanupStreamHandler(c *cleanupStream) error {
653 c.onWrite()
654 if str, ok := l.estdStreams[c.streamID]; ok {
655 // On the server side it could be a trailers-only response or
656 // a RST_STREAM before stream initialization thus the stream might
657 // not be established yet.
658 delete(l.estdStreams, c.streamID)
659 str.deleteSelf()
660 }
661 if c.rst { // If RST_STREAM needs to be sent.
662 if err := l.framer.fr.WriteRSTStream(c.streamID, c.rstCode); err != nil {
663 return err
664 }
665 }
666 if l.side == clientSide && l.draining && len(l.estdStreams) == 0 {
667 return ErrConnClosing
668 }
669 return nil
670}
671
672func (l *loopyWriter) incomingGoAwayHandler(*incomingGoAway) error {
673 if l.side == clientSide {
674 l.draining = true
675 if len(l.estdStreams) == 0 {
676 return ErrConnClosing
677 }
678 }
679 return nil
680}
681
682func (l *loopyWriter) goAwayHandler(g *goAway) error {
683 // Handling of outgoing GoAway is very specific to side.
684 if l.ssGoAwayHandler != nil {
685 draining, err := l.ssGoAwayHandler(g)
686 if err != nil {
687 return err
688 }
689 l.draining = draining
690 }
691 return nil
692}
693
694func (l *loopyWriter) handle(i interface{}) error {
695 switch i := i.(type) {
696 case *incomingWindowUpdate:
697 return l.incomingWindowUpdateHandler(i)
698 case *outgoingWindowUpdate:
699 return l.outgoingWindowUpdateHandler(i)
700 case *incomingSettings:
701 return l.incomingSettingsHandler(i)
702 case *outgoingSettings:
703 return l.outgoingSettingsHandler(i)
704 case *headerFrame:
705 return l.headerHandler(i)
706 case *registerStream:
707 return l.registerStreamHandler(i)
708 case *cleanupStream:
709 return l.cleanupStreamHandler(i)
710 case *incomingGoAway:
711 return l.incomingGoAwayHandler(i)
712 case *dataFrame:
713 return l.preprocessData(i)
714 case *ping:
715 return l.pingHandler(i)
716 case *goAway:
717 return l.goAwayHandler(i)
718 case *outFlowControlSizeRequest:
719 return l.outFlowControlSizeRequestHandler(i)
720 default:
721 return fmt.Errorf("transport: unknown control message type %T", i)
722 }
723}
724
725func (l *loopyWriter) applySettings(ss []http2.Setting) error {
726 for _, s := range ss {
727 switch s.ID {
728 case http2.SettingInitialWindowSize:
729 o := l.oiws
730 l.oiws = s.Val
731 if o < l.oiws {
732 // If the new limit is greater make all depleted streams active.
733 for _, stream := range l.estdStreams {
734 if stream.state == waitingOnStreamQuota {
735 stream.state = active
736 l.activeStreams.enqueue(stream)
737 }
738 }
739 }
740 case http2.SettingHeaderTableSize:
741 updateHeaderTblSize(l.hEnc, s.Val)
742 }
743 }
744 return nil
745}
746
747// processData removes the first stream from active streams, writes out at most 16KB
748// of its data and then puts it at the end of activeStreams if there's still more data
749// to be sent and stream has some stream-level flow control.
750func (l *loopyWriter) processData() (bool, error) {
751 if l.sendQuota == 0 {
752 return true, nil
753 }
754 str := l.activeStreams.dequeue() // Remove the first stream.
755 if str == nil {
756 return true, nil
757 }
758 dataItem := str.itl.peek().(*dataFrame) // Peek at the first data item this stream.
759 // A data item is represented by a dataFrame, since it later translates into
760 // multiple HTTP2 data frames.
761 // Every dataFrame has two buffers; h that keeps grpc-message header and d that is acutal data.
762 // As an optimization to keep wire traffic low, data from d is copied to h to make as big as the
763 // maximum possilbe HTTP2 frame size.
764
765 if len(dataItem.h) == 0 && len(dataItem.d) == 0 { // Empty data frame
766 // Client sends out empty data frame with endStream = true
767 if err := l.framer.fr.WriteData(dataItem.streamID, dataItem.endStream, nil); err != nil {
768 return false, err
769 }
770 str.itl.dequeue() // remove the empty data item from stream
771 if str.itl.isEmpty() {
772 str.state = empty
773 } else if trailer, ok := str.itl.peek().(*headerFrame); ok { // the next item is trailers.
774 if err := l.writeHeader(trailer.streamID, trailer.endStream, trailer.hf, trailer.onWrite); err != nil {
775 return false, err
776 }
777 if err := l.cleanupStreamHandler(trailer.cleanup); err != nil {
778 return false, nil
779 }
780 } else {
781 l.activeStreams.enqueue(str)
782 }
783 return false, nil
784 }
785 var (
786 idx int
787 buf []byte
788 )
789 if len(dataItem.h) != 0 { // data header has not been written out yet.
790 buf = dataItem.h
791 } else {
792 idx = 1
793 buf = dataItem.d
794 }
795 size := http2MaxFrameLen
796 if len(buf) < size {
797 size = len(buf)
798 }
799 if strQuota := int(l.oiws) - str.bytesOutStanding; strQuota <= 0 { // stream-level flow control.
800 str.state = waitingOnStreamQuota
801 return false, nil
802 } else if strQuota < size {
803 size = strQuota
804 }
805
806 if l.sendQuota < uint32(size) { // connection-level flow control.
807 size = int(l.sendQuota)
808 }
809 // Now that outgoing flow controls are checked we can replenish str's write quota
810 str.wq.replenish(size)
811 var endStream bool
812 // If this is the last data message on this stream and all of it can be written in this iteration.
813 if dataItem.endStream && size == len(buf) {
814 // buf contains either data or it contains header but data is empty.
815 if idx == 1 || len(dataItem.d) == 0 {
816 endStream = true
817 }
818 }
819 if dataItem.onEachWrite != nil {
820 dataItem.onEachWrite()
821 }
822 if err := l.framer.fr.WriteData(dataItem.streamID, endStream, buf[:size]); err != nil {
823 return false, err
824 }
825 buf = buf[size:]
826 str.bytesOutStanding += size
827 l.sendQuota -= uint32(size)
828 if idx == 0 {
829 dataItem.h = buf
830 } else {
831 dataItem.d = buf
832 }
833
834 if len(dataItem.h) == 0 && len(dataItem.d) == 0 { // All the data from that message was written out.
835 str.itl.dequeue()
836 }
837 if str.itl.isEmpty() {
838 str.state = empty
839 } else if trailer, ok := str.itl.peek().(*headerFrame); ok { // The next item is trailers.
840 if err := l.writeHeader(trailer.streamID, trailer.endStream, trailer.hf, trailer.onWrite); err != nil {
841 return false, err
842 }
843 if err := l.cleanupStreamHandler(trailer.cleanup); err != nil {
844 return false, err
845 }
846 } else if int(l.oiws)-str.bytesOutStanding <= 0 { // Ran out of stream quota.
847 str.state = waitingOnStreamQuota
848 } else { // Otherwise add it back to the list of active streams.
849 l.activeStreams.enqueue(str)
850 }
851 return false, nil
852}
diff --git a/vendor/google.golang.org/grpc/internal/transport/defaults.go b/vendor/google.golang.org/grpc/internal/transport/defaults.go
new file mode 100644
index 0000000..9fa306b
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/transport/defaults.go
@@ -0,0 +1,49 @@
1/*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package transport
20
21import (
22 "math"
23 "time"
24)
25
26const (
27 // The default value of flow control window size in HTTP2 spec.
28 defaultWindowSize = 65535
29 // The initial window size for flow control.
30 initialWindowSize = defaultWindowSize // for an RPC
31 infinity = time.Duration(math.MaxInt64)
32 defaultClientKeepaliveTime = infinity
33 defaultClientKeepaliveTimeout = 20 * time.Second
34 defaultMaxStreamsClient = 100
35 defaultMaxConnectionIdle = infinity
36 defaultMaxConnectionAge = infinity
37 defaultMaxConnectionAgeGrace = infinity
38 defaultServerKeepaliveTime = 2 * time.Hour
39 defaultServerKeepaliveTimeout = 20 * time.Second
40 defaultKeepalivePolicyMinTime = 5 * time.Minute
41 // max window limit set by HTTP2 Specs.
42 maxWindowSize = math.MaxInt32
43 // defaultWriteQuota is the default value for number of data
44 // bytes that each stream can schedule before some of it being
45 // flushed out.
46 defaultWriteQuota = 64 * 1024
47 defaultClientMaxHeaderListSize = uint32(16 << 20)
48 defaultServerMaxHeaderListSize = uint32(16 << 20)
49)
diff --git a/vendor/google.golang.org/grpc/transport/control.go b/vendor/google.golang.org/grpc/internal/transport/flowcontrol.go
index 501eb03..5ea997a 100644
--- a/vendor/google.golang.org/grpc/transport/control.go
+++ b/vendor/google.golang.org/grpc/internal/transport/flowcontrol.go
@@ -22,128 +22,102 @@ import (
22 "fmt" 22 "fmt"
23 "math" 23 "math"
24 "sync" 24 "sync"
25 "time" 25 "sync/atomic"
26
27 "golang.org/x/net/http2"
28)
29
30const (
31 // The default value of flow control window size in HTTP2 spec.
32 defaultWindowSize = 65535
33 // The initial window size for flow control.
34 initialWindowSize = defaultWindowSize // for an RPC
35 infinity = time.Duration(math.MaxInt64)
36 defaultClientKeepaliveTime = infinity
37 defaultClientKeepaliveTimeout = time.Duration(20 * time.Second)
38 defaultMaxStreamsClient = 100
39 defaultMaxConnectionIdle = infinity
40 defaultMaxConnectionAge = infinity
41 defaultMaxConnectionAgeGrace = infinity
42 defaultServerKeepaliveTime = time.Duration(2 * time.Hour)
43 defaultServerKeepaliveTimeout = time.Duration(20 * time.Second)
44 defaultKeepalivePolicyMinTime = time.Duration(5 * time.Minute)
45 // max window limit set by HTTP2 Specs.
46 maxWindowSize = math.MaxInt32
47) 26)
48 27
49// The following defines various control items which could flow through 28// writeQuota is a soft limit on the amount of data a stream can
50// the control buffer of transport. They represent different aspects of 29// schedule before some of it is written out.
51// control tasks, e.g., flow control, settings, streaming resetting, etc. 30type writeQuota struct {
52type windowUpdate struct { 31 quota int32
53 streamID uint32 32 // get waits on read from when quota goes less than or equal to zero.
54 increment uint32 33 // replenish writes on it when quota goes positive again.
55 flush bool 34 ch chan struct{}
56} 35 // done is triggered in error case.
57 36 done <-chan struct{}
58func (*windowUpdate) item() {} 37 // replenish is called by loopyWriter to give quota back to.
59 38 // It is implemented as a field so that it can be updated
60type settings struct { 39 // by tests.
61 ack bool 40 replenish func(n int)
62 ss []http2.Setting 41}
42
43func newWriteQuota(sz int32, done <-chan struct{}) *writeQuota {
44 w := &writeQuota{
45 quota: sz,
46 ch: make(chan struct{}, 1),
47 done: done,
48 }
49 w.replenish = w.realReplenish
50 return w
63} 51}
64 52
65func (*settings) item() {} 53func (w *writeQuota) get(sz int32) error {
66 54 for {
67type resetStream struct { 55 if atomic.LoadInt32(&w.quota) > 0 {
68 streamID uint32 56 atomic.AddInt32(&w.quota, -sz)
69 code http2.ErrCode 57 return nil
58 }
59 select {
60 case <-w.ch:
61 continue
62 case <-w.done:
63 return errStreamDone
64 }
65 }
70} 66}
71 67
72func (*resetStream) item() {} 68func (w *writeQuota) realReplenish(n int) {
73 69 sz := int32(n)
74type goAway struct { 70 a := atomic.AddInt32(&w.quota, sz)
75 code http2.ErrCode 71 b := a - sz
76 debugData []byte 72 if b <= 0 && a > 0 {
77 headsUp bool 73 select {
78 closeConn bool 74 case w.ch <- struct{}{}:
75 default:
76 }
77 }
79} 78}
80 79
81func (*goAway) item() {} 80type trInFlow struct {
82 81 limit uint32
83type flushIO struct { 82 unacked uint32
83 effectiveWindowSize uint32
84} 84}
85 85
86func (*flushIO) item() {} 86func (f *trInFlow) newLimit(n uint32) uint32 {
87 87 d := n - f.limit
88type ping struct { 88 f.limit = n
89 ack bool 89 f.updateEffectiveWindowSize()
90 data [8]byte 90 return d
91} 91}
92 92
93func (*ping) item() {} 93func (f *trInFlow) onData(n uint32) uint32 {
94 94 f.unacked += n
95// quotaPool is a pool which accumulates the quota and sends it to acquire() 95 if f.unacked >= f.limit/4 {
96// when it is available. 96 w := f.unacked
97type quotaPool struct { 97 f.unacked = 0
98 c chan int 98 f.updateEffectiveWindowSize()
99 99 return w
100 mu sync.Mutex 100 }
101 quota int 101 f.updateEffectiveWindowSize()
102 return 0
102} 103}
103 104
104// newQuotaPool creates a quotaPool which has quota q available to consume. 105func (f *trInFlow) reset() uint32 {
105func newQuotaPool(q int) *quotaPool { 106 w := f.unacked
106 qb := &quotaPool{ 107 f.unacked = 0
107 c: make(chan int, 1), 108 f.updateEffectiveWindowSize()
108 } 109 return w
109 if q > 0 {
110 qb.c <- q
111 } else {
112 qb.quota = q
113 }
114 return qb
115} 110}
116 111
117// add cancels the pending quota sent on acquired, incremented by v and sends 112func (f *trInFlow) updateEffectiveWindowSize() {
118// it back on acquire. 113 atomic.StoreUint32(&f.effectiveWindowSize, f.limit-f.unacked)
119func (qb *quotaPool) add(v int) {
120 qb.mu.Lock()
121 defer qb.mu.Unlock()
122 select {
123 case n := <-qb.c:
124 qb.quota += n
125 default:
126 }
127 qb.quota += v
128 if qb.quota <= 0 {
129 return
130 }
131 // After the pool has been created, this is the only place that sends on
132 // the channel. Since mu is held at this point and any quota that was sent
133 // on the channel has been retrieved, we know that this code will always
134 // place any positive quota value on the channel.
135 select {
136 case qb.c <- qb.quota:
137 qb.quota = 0
138 default:
139 }
140} 114}
141 115
142// acquire returns the channel on which available quota amounts are sent. 116func (f *trInFlow) getSize() uint32 {
143func (qb *quotaPool) acquire() <-chan int { 117 return atomic.LoadUint32(&f.effectiveWindowSize)
144 return qb.c
145} 118}
146 119
120// TODO(mmukhi): Simplify this code.
147// inFlow deals with inbound flow control 121// inFlow deals with inbound flow control
148type inFlow struct { 122type inFlow struct {
149 mu sync.Mutex 123 mu sync.Mutex
@@ -164,9 +138,9 @@ type inFlow struct {
164// It assumes that n is always greater than the old limit. 138// It assumes that n is always greater than the old limit.
165func (f *inFlow) newLimit(n uint32) uint32 { 139func (f *inFlow) newLimit(n uint32) uint32 {
166 f.mu.Lock() 140 f.mu.Lock()
167 defer f.mu.Unlock()
168 d := n - f.limit 141 d := n - f.limit
169 f.limit = n 142 f.limit = n
143 f.mu.Unlock()
170 return d 144 return d
171} 145}
172 146
@@ -175,7 +149,6 @@ func (f *inFlow) maybeAdjust(n uint32) uint32 {
175 n = uint32(math.MaxInt32) 149 n = uint32(math.MaxInt32)
176 } 150 }
177 f.mu.Lock() 151 f.mu.Lock()
178 defer f.mu.Unlock()
179 // estSenderQuota is the receiver's view of the maximum number of bytes the sender 152 // estSenderQuota is the receiver's view of the maximum number of bytes the sender
180 // can send without a window update. 153 // can send without a window update.
181 estSenderQuota := int32(f.limit - (f.pendingData + f.pendingUpdate)) 154 estSenderQuota := int32(f.limit - (f.pendingData + f.pendingUpdate))
@@ -187,7 +160,7 @@ func (f *inFlow) maybeAdjust(n uint32) uint32 {
187 // for this message. Therefore we must send an update over the limit since there's an active read 160 // for this message. Therefore we must send an update over the limit since there's an active read
188 // request from the application. 161 // request from the application.
189 if estUntransmittedData > estSenderQuota { 162 if estUntransmittedData > estSenderQuota {
190 // Sender's window shouldn't go more than 2^31 - 1 as speecified in the HTTP spec. 163 // Sender's window shouldn't go more than 2^31 - 1 as specified in the HTTP spec.
191 if f.limit+n > maxWindowSize { 164 if f.limit+n > maxWindowSize {
192 f.delta = maxWindowSize - f.limit 165 f.delta = maxWindowSize - f.limit
193 } else { 166 } else {
@@ -196,19 +169,24 @@ func (f *inFlow) maybeAdjust(n uint32) uint32 {
196 // is padded; We will fallback on the current available window(at least a 1/4th of the limit). 169 // is padded; We will fallback on the current available window(at least a 1/4th of the limit).
197 f.delta = n 170 f.delta = n
198 } 171 }
172 f.mu.Unlock()
199 return f.delta 173 return f.delta
200 } 174 }
175 f.mu.Unlock()
201 return 0 176 return 0
202} 177}
203 178
204// onData is invoked when some data frame is received. It updates pendingData. 179// onData is invoked when some data frame is received. It updates pendingData.
205func (f *inFlow) onData(n uint32) error { 180func (f *inFlow) onData(n uint32) error {
206 f.mu.Lock() 181 f.mu.Lock()
207 defer f.mu.Unlock()
208 f.pendingData += n 182 f.pendingData += n
209 if f.pendingData+f.pendingUpdate > f.limit+f.delta { 183 if f.pendingData+f.pendingUpdate > f.limit+f.delta {
210 return fmt.Errorf("received %d-bytes data exceeding the limit %d bytes", f.pendingData+f.pendingUpdate, f.limit) 184 limit := f.limit
185 rcvd := f.pendingData + f.pendingUpdate
186 f.mu.Unlock()
187 return fmt.Errorf("received %d-bytes data exceeding the limit %d bytes", rcvd, limit)
211 } 188 }
189 f.mu.Unlock()
212 return nil 190 return nil
213} 191}
214 192
@@ -216,8 +194,8 @@ func (f *inFlow) onData(n uint32) error {
216// to be sent to the peer. 194// to be sent to the peer.
217func (f *inFlow) onRead(n uint32) uint32 { 195func (f *inFlow) onRead(n uint32) uint32 {
218 f.mu.Lock() 196 f.mu.Lock()
219 defer f.mu.Unlock()
220 if f.pendingData == 0 { 197 if f.pendingData == 0 {
198 f.mu.Unlock()
221 return 0 199 return 0
222 } 200 }
223 f.pendingData -= n 201 f.pendingData -= n
@@ -232,15 +210,9 @@ func (f *inFlow) onRead(n uint32) uint32 {
232 if f.pendingUpdate >= f.limit/4 { 210 if f.pendingUpdate >= f.limit/4 {
233 wu := f.pendingUpdate 211 wu := f.pendingUpdate
234 f.pendingUpdate = 0 212 f.pendingUpdate = 0
213 f.mu.Unlock()
235 return wu 214 return wu
236 } 215 }
216 f.mu.Unlock()
237 return 0 217 return 0
238} 218}
239
240func (f *inFlow) resetPendingUpdate() uint32 {
241 f.mu.Lock()
242 defer f.mu.Unlock()
243 n := f.pendingUpdate
244 f.pendingUpdate = 0
245 return n
246}
diff --git a/vendor/google.golang.org/grpc/transport/handler_server.go b/vendor/google.golang.org/grpc/internal/transport/handler_server.go
index 27372b5..73b41ea 100644
--- a/vendor/google.golang.org/grpc/transport/handler_server.go
+++ b/vendor/google.golang.org/grpc/internal/transport/handler_server.go
@@ -24,6 +24,7 @@
24package transport 24package transport
25 25
26import ( 26import (
27 "context"
27 "errors" 28 "errors"
28 "fmt" 29 "fmt"
29 "io" 30 "io"
@@ -33,26 +34,30 @@ import (
33 "sync" 34 "sync"
34 "time" 35 "time"
35 36
36 "golang.org/x/net/context" 37 "github.com/golang/protobuf/proto"
37 "golang.org/x/net/http2" 38 "golang.org/x/net/http2"
38 "google.golang.org/grpc/codes" 39 "google.golang.org/grpc/codes"
39 "google.golang.org/grpc/credentials" 40 "google.golang.org/grpc/credentials"
40 "google.golang.org/grpc/metadata" 41 "google.golang.org/grpc/metadata"
41 "google.golang.org/grpc/peer" 42 "google.golang.org/grpc/peer"
43 "google.golang.org/grpc/stats"
42 "google.golang.org/grpc/status" 44 "google.golang.org/grpc/status"
43) 45)
44 46
45// NewServerHandlerTransport returns a ServerTransport handling gRPC 47// NewServerHandlerTransport returns a ServerTransport handling gRPC
46// from inside an http.Handler. It requires that the http Server 48// from inside an http.Handler. It requires that the http Server
47// supports HTTP/2. 49// supports HTTP/2.
48func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request) (ServerTransport, error) { 50func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats stats.Handler) (ServerTransport, error) {
49 if r.ProtoMajor != 2 { 51 if r.ProtoMajor != 2 {
50 return nil, errors.New("gRPC requires HTTP/2") 52 return nil, errors.New("gRPC requires HTTP/2")
51 } 53 }
52 if r.Method != "POST" { 54 if r.Method != "POST" {
53 return nil, errors.New("invalid gRPC request method") 55 return nil, errors.New("invalid gRPC request method")
54 } 56 }
55 if !validContentType(r.Header.Get("Content-Type")) { 57 contentType := r.Header.Get("Content-Type")
58 // TODO: do we assume contentType is lowercase? we did before
59 contentSubtype, validContentType := contentSubtype(contentType)
60 if !validContentType {
56 return nil, errors.New("invalid gRPC request content-type") 61 return nil, errors.New("invalid gRPC request content-type")
57 } 62 }
58 if _, ok := w.(http.Flusher); !ok { 63 if _, ok := w.(http.Flusher); !ok {
@@ -63,34 +68,37 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request) (ServerTr
63 } 68 }
64 69
65 st := &serverHandlerTransport{ 70 st := &serverHandlerTransport{
66 rw: w, 71 rw: w,
67 req: r, 72 req: r,
68 closedCh: make(chan struct{}), 73 closedCh: make(chan struct{}),
69 writes: make(chan func()), 74 writes: make(chan func()),
75 contentType: contentType,
76 contentSubtype: contentSubtype,
77 stats: stats,
70 } 78 }
71 79
72 if v := r.Header.Get("grpc-timeout"); v != "" { 80 if v := r.Header.Get("grpc-timeout"); v != "" {
73 to, err := decodeTimeout(v) 81 to, err := decodeTimeout(v)
74 if err != nil { 82 if err != nil {
75 return nil, streamErrorf(codes.Internal, "malformed time-out: %v", err) 83 return nil, status.Errorf(codes.Internal, "malformed time-out: %v", err)
76 } 84 }
77 st.timeoutSet = true 85 st.timeoutSet = true
78 st.timeout = to 86 st.timeout = to
79 } 87 }
80 88
81 var metakv []string 89 metakv := []string{"content-type", contentType}
82 if r.Host != "" { 90 if r.Host != "" {
83 metakv = append(metakv, ":authority", r.Host) 91 metakv = append(metakv, ":authority", r.Host)
84 } 92 }
85 for k, vv := range r.Header { 93 for k, vv := range r.Header {
86 k = strings.ToLower(k) 94 k = strings.ToLower(k)
87 if isReservedHeader(k) && !isWhitelistedPseudoHeader(k) { 95 if isReservedHeader(k) && !isWhitelistedHeader(k) {
88 continue 96 continue
89 } 97 }
90 for _, v := range vv { 98 for _, v := range vv {
91 v, err := decodeMetadataHeader(k, v) 99 v, err := decodeMetadataHeader(k, v)
92 if err != nil { 100 if err != nil {
93 return nil, streamErrorf(codes.InvalidArgument, "malformed binary metadata: %v", err) 101 return nil, status.Errorf(codes.Internal, "malformed binary metadata: %v", err)
94 } 102 }
95 metakv = append(metakv, k, v) 103 metakv = append(metakv, k, v)
96 } 104 }
@@ -121,6 +129,18 @@ type serverHandlerTransport struct {
121 // ServeHTTP (HandleStreams) goroutine. The channel is closed 129 // ServeHTTP (HandleStreams) goroutine. The channel is closed
122 // when WriteStatus is called. 130 // when WriteStatus is called.
123 writes chan func() 131 writes chan func()
132
133 // block concurrent WriteStatus calls
134 // e.g. grpc/(*serverStream).SendMsg/RecvMsg
135 writeStatusMu sync.Mutex
136
137 // we just mirror the request content-type
138 contentType string
139 // we store both contentType and contentSubtype so we don't keep recreating them
140 // TODO make sure this is consistent across handler_server and http2_server
141 contentSubtype string
142
143 stats stats.Handler
124} 144}
125 145
126func (ht *serverHandlerTransport) Close() error { 146func (ht *serverHandlerTransport) Close() error {
@@ -167,11 +187,13 @@ func (ht *serverHandlerTransport) do(fn func()) error {
167 case <-ht.closedCh: 187 case <-ht.closedCh:
168 return ErrConnClosing 188 return ErrConnClosing
169 } 189 }
170
171 } 190 }
172} 191}
173 192
174func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) error { 193func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) error {
194 ht.writeStatusMu.Lock()
195 defer ht.writeStatusMu.Unlock()
196
175 err := ht.do(func() { 197 err := ht.do(func() {
176 ht.writeCommonHeaders(s) 198 ht.writeCommonHeaders(s)
177 199
@@ -186,7 +208,15 @@ func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) erro
186 h.Set("Grpc-Message", encodeGrpcMessage(m)) 208 h.Set("Grpc-Message", encodeGrpcMessage(m))
187 } 209 }
188 210
189 // TODO: Support Grpc-Status-Details-Bin 211 if p := st.Proto(); p != nil && len(p.Details) > 0 {
212 stBytes, err := proto.Marshal(p)
213 if err != nil {
214 // TODO: return error instead, when callers are able to handle it.
215 panic(err)
216 }
217
218 h.Set("Grpc-Status-Details-Bin", encodeBinHeader(stBytes))
219 }
190 220
191 if md := s.Trailer(); len(md) > 0 { 221 if md := s.Trailer(); len(md) > 0 {
192 for k, vv := range md { 222 for k, vv := range md {
@@ -202,7 +232,14 @@ func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) erro
202 } 232 }
203 } 233 }
204 }) 234 })
205 close(ht.writes) 235
236 if err == nil { // transport has not been closed
237 if ht.stats != nil {
238 ht.stats.HandleRPC(s.Context(), &stats.OutTrailer{})
239 }
240 close(ht.writes)
241 }
242 ht.Close()
206 return err 243 return err
207} 244}
208 245
@@ -216,7 +253,7 @@ func (ht *serverHandlerTransport) writeCommonHeaders(s *Stream) {
216 253
217 h := ht.rw.Header() 254 h := ht.rw.Header()
218 h["Date"] = nil // suppress Date to make tests happy; TODO: restore 255 h["Date"] = nil // suppress Date to make tests happy; TODO: restore
219 h.Set("Content-Type", "application/grpc") 256 h.Set("Content-Type", ht.contentType)
220 257
221 // Predeclare trailers we'll set later in WriteStatus (after the body). 258 // Predeclare trailers we'll set later in WriteStatus (after the body).
222 // This is a SHOULD in the HTTP RFC, and the way you add (known) 259 // This is a SHOULD in the HTTP RFC, and the way you add (known)
@@ -225,25 +262,24 @@ func (ht *serverHandlerTransport) writeCommonHeaders(s *Stream) {
225 // and https://golang.org/pkg/net/http/#example_ResponseWriter_trailers 262 // and https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
226 h.Add("Trailer", "Grpc-Status") 263 h.Add("Trailer", "Grpc-Status")
227 h.Add("Trailer", "Grpc-Message") 264 h.Add("Trailer", "Grpc-Message")
228 // TODO: Support Grpc-Status-Details-Bin 265 h.Add("Trailer", "Grpc-Status-Details-Bin")
229 266
230 if s.sendCompress != "" { 267 if s.sendCompress != "" {
231 h.Set("Grpc-Encoding", s.sendCompress) 268 h.Set("Grpc-Encoding", s.sendCompress)
232 } 269 }
233} 270}
234 271
235func (ht *serverHandlerTransport) Write(s *Stream, data []byte, opts *Options) error { 272func (ht *serverHandlerTransport) Write(s *Stream, hdr []byte, data []byte, opts *Options) error {
236 return ht.do(func() { 273 return ht.do(func() {
237 ht.writeCommonHeaders(s) 274 ht.writeCommonHeaders(s)
275 ht.rw.Write(hdr)
238 ht.rw.Write(data) 276 ht.rw.Write(data)
239 if !opts.Delay { 277 ht.rw.(http.Flusher).Flush()
240 ht.rw.(http.Flusher).Flush()
241 }
242 }) 278 })
243} 279}
244 280
245func (ht *serverHandlerTransport) WriteHeader(s *Stream, md metadata.MD) error { 281func (ht *serverHandlerTransport) WriteHeader(s *Stream, md metadata.MD) error {
246 return ht.do(func() { 282 err := ht.do(func() {
247 ht.writeCommonHeaders(s) 283 ht.writeCommonHeaders(s)
248 h := ht.rw.Header() 284 h := ht.rw.Header()
249 for k, vv := range md { 285 for k, vv := range md {
@@ -259,17 +295,24 @@ func (ht *serverHandlerTransport) WriteHeader(s *Stream, md metadata.MD) error {
259 ht.rw.WriteHeader(200) 295 ht.rw.WriteHeader(200)
260 ht.rw.(http.Flusher).Flush() 296 ht.rw.(http.Flusher).Flush()
261 }) 297 })
298
299 if err == nil {
300 if ht.stats != nil {
301 ht.stats.HandleRPC(s.Context(), &stats.OutHeader{})
302 }
303 }
304 return err
262} 305}
263 306
264func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream), traceCtx func(context.Context, string) context.Context) { 307func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream), traceCtx func(context.Context, string) context.Context) {
265 // With this transport type there will be exactly 1 stream: this HTTP request. 308 // With this transport type there will be exactly 1 stream: this HTTP request.
266 309
267 var ctx context.Context 310 ctx := ht.req.Context()
268 var cancel context.CancelFunc 311 var cancel context.CancelFunc
269 if ht.timeoutSet { 312 if ht.timeoutSet {
270 ctx, cancel = context.WithTimeout(context.Background(), ht.timeout) 313 ctx, cancel = context.WithTimeout(ctx, ht.timeout)
271 } else { 314 } else {
272 ctx, cancel = context.WithCancel(context.Background()) 315 ctx, cancel = context.WithCancel(ctx)
273 } 316 }
274 317
275 // requestOver is closed when either the request's context is done 318 // requestOver is closed when either the request's context is done
@@ -283,23 +326,24 @@ func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream), trace
283 go func() { 326 go func() {
284 select { 327 select {
285 case <-requestOver: 328 case <-requestOver:
286 return
287 case <-ht.closedCh: 329 case <-ht.closedCh:
288 case <-clientGone: 330 case <-clientGone:
289 } 331 }
290 cancel() 332 cancel()
333 ht.Close()
291 }() 334 }()
292 335
293 req := ht.req 336 req := ht.req
294 337
295 s := &Stream{ 338 s := &Stream{
296 id: 0, // irrelevant 339 id: 0, // irrelevant
297 requestRead: func(int) {}, 340 requestRead: func(int) {},
298 cancel: cancel, 341 cancel: cancel,
299 buf: newRecvBuffer(), 342 buf: newRecvBuffer(),
300 st: ht, 343 st: ht,
301 method: req.URL.Path, 344 method: req.URL.Path,
302 recvCompress: req.Header.Get("grpc-encoding"), 345 recvCompress: req.Header.Get("grpc-encoding"),
346 contentSubtype: ht.contentSubtype,
303 } 347 }
304 pr := &peer.Peer{ 348 pr := &peer.Peer{
305 Addr: ht.RemoteAddr(), 349 Addr: ht.RemoteAddr(),
@@ -308,10 +352,18 @@ func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream), trace
308 pr.AuthInfo = credentials.TLSInfo{State: *req.TLS} 352 pr.AuthInfo = credentials.TLSInfo{State: *req.TLS}
309 } 353 }
310 ctx = metadata.NewIncomingContext(ctx, ht.headerMD) 354 ctx = metadata.NewIncomingContext(ctx, ht.headerMD)
311 ctx = peer.NewContext(ctx, pr) 355 s.ctx = peer.NewContext(ctx, pr)
312 s.ctx = newContextWithStream(ctx, s) 356 if ht.stats != nil {
357 s.ctx = ht.stats.TagRPC(s.ctx, &stats.RPCTagInfo{FullMethodName: s.method})
358 inHeader := &stats.InHeader{
359 FullMethod: s.method,
360 RemoteAddr: ht.RemoteAddr(),
361 Compression: s.recvCompress,
362 }
363 ht.stats.HandleRPC(s.ctx, inHeader)
364 }
313 s.trReader = &transportReader{ 365 s.trReader = &transportReader{
314 reader: &recvBufferReader{ctx: s.ctx, recv: s.buf}, 366 reader: &recvBufferReader{ctx: s.ctx, ctxDone: s.ctx.Done(), recv: s.buf},
315 windowHandler: func(int) {}, 367 windowHandler: func(int) {},
316 } 368 }
317 369
@@ -366,6 +418,10 @@ func (ht *serverHandlerTransport) runStream() {
366 } 418 }
367} 419}
368 420
421func (ht *serverHandlerTransport) IncrMsgSent() {}
422
423func (ht *serverHandlerTransport) IncrMsgRecv() {}
424
369func (ht *serverHandlerTransport) Drain() { 425func (ht *serverHandlerTransport) Drain() {
370 panic("Drain() is not implemented") 426 panic("Drain() is not implemented")
371} 427}
@@ -376,18 +432,18 @@ func (ht *serverHandlerTransport) Drain() {
376// * io.EOF 432// * io.EOF
377// * io.ErrUnexpectedEOF 433// * io.ErrUnexpectedEOF
378// * of type transport.ConnectionError 434// * of type transport.ConnectionError
379// * of type transport.StreamError 435// * an error from the status package
380func mapRecvMsgError(err error) error { 436func mapRecvMsgError(err error) error {
381 if err == io.EOF || err == io.ErrUnexpectedEOF { 437 if err == io.EOF || err == io.ErrUnexpectedEOF {
382 return err 438 return err
383 } 439 }
384 if se, ok := err.(http2.StreamError); ok { 440 if se, ok := err.(http2.StreamError); ok {
385 if code, ok := http2ErrConvTab[se.Code]; ok { 441 if code, ok := http2ErrConvTab[se.Code]; ok {
386 return StreamError{ 442 return status.Error(code, se.Error())
387 Code: code,
388 Desc: se.Error(),
389 }
390 } 443 }
391 } 444 }
445 if strings.Contains(err.Error(), "body closed by handler") {
446 return status.Error(codes.Canceled, err.Error())
447 }
392 return connectionErrorf(true, err, err.Error()) 448 return connectionErrorf(true, err, err.Error())
393} 449}
diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_client.go b/vendor/google.golang.org/grpc/internal/transport/http2_client.go
new file mode 100644
index 0000000..babcaee
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/transport/http2_client.go
@@ -0,0 +1,1380 @@
1/*
2 *
3 * Copyright 2014 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package transport
20
21import (
22 "context"
23 "fmt"
24 "io"
25 "math"
26 "net"
27 "strconv"
28 "strings"
29 "sync"
30 "sync/atomic"
31 "time"
32
33 "golang.org/x/net/http2"
34 "golang.org/x/net/http2/hpack"
35
36 "google.golang.org/grpc/codes"
37 "google.golang.org/grpc/credentials"
38 "google.golang.org/grpc/internal/channelz"
39 "google.golang.org/grpc/internal/syscall"
40 "google.golang.org/grpc/keepalive"
41 "google.golang.org/grpc/metadata"
42 "google.golang.org/grpc/peer"
43 "google.golang.org/grpc/stats"
44 "google.golang.org/grpc/status"
45)
46
47// http2Client implements the ClientTransport interface with HTTP2.
48type http2Client struct {
49 ctx context.Context
50 cancel context.CancelFunc
51 ctxDone <-chan struct{} // Cache the ctx.Done() chan.
52 userAgent string
53 md interface{}
54 conn net.Conn // underlying communication channel
55 loopy *loopyWriter
56 remoteAddr net.Addr
57 localAddr net.Addr
58 authInfo credentials.AuthInfo // auth info about the connection
59
60 readerDone chan struct{} // sync point to enable testing.
61 writerDone chan struct{} // sync point to enable testing.
62 // goAway is closed to notify the upper layer (i.e., addrConn.transportMonitor)
63 // that the server sent GoAway on this transport.
64 goAway chan struct{}
65 // awakenKeepalive is used to wake up keepalive when after it has gone dormant.
66 awakenKeepalive chan struct{}
67
68 framer *framer
69 // controlBuf delivers all the control related tasks (e.g., window
70 // updates, reset streams, and various settings) to the controller.
71 controlBuf *controlBuffer
72 fc *trInFlow
73 // The scheme used: https if TLS is on, http otherwise.
74 scheme string
75
76 isSecure bool
77
78 perRPCCreds []credentials.PerRPCCredentials
79
80 // Boolean to keep track of reading activity on transport.
81 // 1 is true and 0 is false.
82 activity uint32 // Accessed atomically.
83 kp keepalive.ClientParameters
84 keepaliveEnabled bool
85
86 statsHandler stats.Handler
87
88 initialWindowSize int32
89
90 // configured by peer through SETTINGS_MAX_HEADER_LIST_SIZE
91 maxSendHeaderListSize *uint32
92
93 bdpEst *bdpEstimator
94 // onPrefaceReceipt is a callback that client transport calls upon
95 // receiving server preface to signal that a succefull HTTP2
96 // connection was established.
97 onPrefaceReceipt func()
98
99 maxConcurrentStreams uint32
100 streamQuota int64
101 streamsQuotaAvailable chan struct{}
102 waitingStreams uint32
103 nextID uint32
104
105 mu sync.Mutex // guard the following variables
106 state transportState
107 activeStreams map[uint32]*Stream
108 // prevGoAway ID records the Last-Stream-ID in the previous GOAway frame.
109 prevGoAwayID uint32
110 // goAwayReason records the http2.ErrCode and debug data received with the
111 // GoAway frame.
112 goAwayReason GoAwayReason
113
114 // Fields below are for channelz metric collection.
115 channelzID int64 // channelz unique identification number
116 czData *channelzData
117
118 onGoAway func(GoAwayReason)
119 onClose func()
120}
121
122func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error), addr string) (net.Conn, error) {
123 if fn != nil {
124 return fn(ctx, addr)
125 }
126 return (&net.Dialer{}).DialContext(ctx, "tcp", addr)
127}
128
129func isTemporary(err error) bool {
130 switch err := err.(type) {
131 case interface {
132 Temporary() bool
133 }:
134 return err.Temporary()
135 case interface {
136 Timeout() bool
137 }:
138 // Timeouts may be resolved upon retry, and are thus treated as
139 // temporary.
140 return err.Timeout()
141 }
142 return true
143}
144
145// newHTTP2Client constructs a connected ClientTransport to addr based on HTTP2
146// and starts to receive messages on it. Non-nil error returns if construction
147// fails.
148func newHTTP2Client(connectCtx, ctx context.Context, addr TargetInfo, opts ConnectOptions, onPrefaceReceipt func(), onGoAway func(GoAwayReason), onClose func()) (_ *http2Client, err error) {
149 scheme := "http"
150 ctx, cancel := context.WithCancel(ctx)
151 defer func() {
152 if err != nil {
153 cancel()
154 }
155 }()
156
157 conn, err := dial(connectCtx, opts.Dialer, addr.Addr)
158 if err != nil {
159 if opts.FailOnNonTempDialError {
160 return nil, connectionErrorf(isTemporary(err), err, "transport: error while dialing: %v", err)
161 }
162 return nil, connectionErrorf(true, err, "transport: Error while dialing %v", err)
163 }
164 // Any further errors will close the underlying connection
165 defer func(conn net.Conn) {
166 if err != nil {
167 conn.Close()
168 }
169 }(conn)
170 kp := opts.KeepaliveParams
171 // Validate keepalive parameters.
172 if kp.Time == 0 {
173 kp.Time = defaultClientKeepaliveTime
174 }
175 if kp.Timeout == 0 {
176 kp.Timeout = defaultClientKeepaliveTimeout
177 }
178 keepaliveEnabled := false
179 if kp.Time != infinity {
180 if err = syscall.SetTCPUserTimeout(conn, kp.Timeout); err != nil {
181 return nil, connectionErrorf(false, err, "transport: failed to set TCP_USER_TIMEOUT: %v", err)
182 }
183 keepaliveEnabled = true
184 }
185 var (
186 isSecure bool
187 authInfo credentials.AuthInfo
188 )
189 transportCreds := opts.TransportCredentials
190 perRPCCreds := opts.PerRPCCredentials
191
192 if b := opts.CredsBundle; b != nil {
193 if t := b.TransportCredentials(); t != nil {
194 transportCreds = t
195 }
196 if t := b.PerRPCCredentials(); t != nil {
197 perRPCCreds = append(perRPCCreds, t)
198 }
199 }
200 if transportCreds != nil {
201 scheme = "https"
202 conn, authInfo, err = transportCreds.ClientHandshake(connectCtx, addr.Authority, conn)
203 if err != nil {
204 return nil, connectionErrorf(isTemporary(err), err, "transport: authentication handshake failed: %v", err)
205 }
206 isSecure = true
207 }
208 dynamicWindow := true
209 icwz := int32(initialWindowSize)
210 if opts.InitialConnWindowSize >= defaultWindowSize {
211 icwz = opts.InitialConnWindowSize
212 dynamicWindow = false
213 }
214 writeBufSize := opts.WriteBufferSize
215 readBufSize := opts.ReadBufferSize
216 maxHeaderListSize := defaultClientMaxHeaderListSize
217 if opts.MaxHeaderListSize != nil {
218 maxHeaderListSize = *opts.MaxHeaderListSize
219 }
220 t := &http2Client{
221 ctx: ctx,
222 ctxDone: ctx.Done(), // Cache Done chan.
223 cancel: cancel,
224 userAgent: opts.UserAgent,
225 md: addr.Metadata,
226 conn: conn,
227 remoteAddr: conn.RemoteAddr(),
228 localAddr: conn.LocalAddr(),
229 authInfo: authInfo,
230 readerDone: make(chan struct{}),
231 writerDone: make(chan struct{}),
232 goAway: make(chan struct{}),
233 awakenKeepalive: make(chan struct{}, 1),
234 framer: newFramer(conn, writeBufSize, readBufSize, maxHeaderListSize),
235 fc: &trInFlow{limit: uint32(icwz)},
236 scheme: scheme,
237 activeStreams: make(map[uint32]*Stream),
238 isSecure: isSecure,
239 perRPCCreds: perRPCCreds,
240 kp: kp,
241 statsHandler: opts.StatsHandler,
242 initialWindowSize: initialWindowSize,
243 onPrefaceReceipt: onPrefaceReceipt,
244 nextID: 1,
245 maxConcurrentStreams: defaultMaxStreamsClient,
246 streamQuota: defaultMaxStreamsClient,
247 streamsQuotaAvailable: make(chan struct{}, 1),
248 czData: new(channelzData),
249 onGoAway: onGoAway,
250 onClose: onClose,
251 keepaliveEnabled: keepaliveEnabled,
252 }
253 t.controlBuf = newControlBuffer(t.ctxDone)
254 if opts.InitialWindowSize >= defaultWindowSize {
255 t.initialWindowSize = opts.InitialWindowSize
256 dynamicWindow = false
257 }
258 if dynamicWindow {
259 t.bdpEst = &bdpEstimator{
260 bdp: initialWindowSize,
261 updateFlowControl: t.updateFlowControl,
262 }
263 }
264 // Make sure awakenKeepalive can't be written upon.
265 // keepalive routine will make it writable, if need be.
266 t.awakenKeepalive <- struct{}{}
267 if t.statsHandler != nil {
268 t.ctx = t.statsHandler.TagConn(t.ctx, &stats.ConnTagInfo{
269 RemoteAddr: t.remoteAddr,
270 LocalAddr: t.localAddr,
271 })
272 connBegin := &stats.ConnBegin{
273 Client: true,
274 }
275 t.statsHandler.HandleConn(t.ctx, connBegin)
276 }
277 if channelz.IsOn() {
278 t.channelzID = channelz.RegisterNormalSocket(t, opts.ChannelzParentID, fmt.Sprintf("%s -> %s", t.localAddr, t.remoteAddr))
279 }
280 if t.keepaliveEnabled {
281 go t.keepalive()
282 }
283 // Start the reader goroutine for incoming message. Each transport has
284 // a dedicated goroutine which reads HTTP2 frame from network. Then it
285 // dispatches the frame to the corresponding stream entity.
286 go t.reader()
287
288 // Send connection preface to server.
289 n, err := t.conn.Write(clientPreface)
290 if err != nil {
291 t.Close()
292 return nil, connectionErrorf(true, err, "transport: failed to write client preface: %v", err)
293 }
294 if n != len(clientPreface) {
295 t.Close()
296 return nil, connectionErrorf(true, err, "transport: preface mismatch, wrote %d bytes; want %d", n, len(clientPreface))
297 }
298 var ss []http2.Setting
299
300 if t.initialWindowSize != defaultWindowSize {
301 ss = append(ss, http2.Setting{
302 ID: http2.SettingInitialWindowSize,
303 Val: uint32(t.initialWindowSize),
304 })
305 }
306 if opts.MaxHeaderListSize != nil {
307 ss = append(ss, http2.Setting{
308 ID: http2.SettingMaxHeaderListSize,
309 Val: *opts.MaxHeaderListSize,
310 })
311 }
312 err = t.framer.fr.WriteSettings(ss...)
313 if err != nil {
314 t.Close()
315 return nil, connectionErrorf(true, err, "transport: failed to write initial settings frame: %v", err)
316 }
317 // Adjust the connection flow control window if needed.
318 if delta := uint32(icwz - defaultWindowSize); delta > 0 {
319 if err := t.framer.fr.WriteWindowUpdate(0, delta); err != nil {
320 t.Close()
321 return nil, connectionErrorf(true, err, "transport: failed to write window update: %v", err)
322 }
323 }
324
325 t.framer.writer.Flush()
326 go func() {
327 t.loopy = newLoopyWriter(clientSide, t.framer, t.controlBuf, t.bdpEst)
328 err := t.loopy.run()
329 if err != nil {
330 errorf("transport: loopyWriter.run returning. Err: %v", err)
331 }
332 // If it's a connection error, let reader goroutine handle it
333 // since there might be data in the buffers.
334 if _, ok := err.(net.Error); !ok {
335 t.conn.Close()
336 }
337 close(t.writerDone)
338 }()
339 return t, nil
340}
341
342func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *Stream {
343 // TODO(zhaoq): Handle uint32 overflow of Stream.id.
344 s := &Stream{
345 done: make(chan struct{}),
346 method: callHdr.Method,
347 sendCompress: callHdr.SendCompress,
348 buf: newRecvBuffer(),
349 headerChan: make(chan struct{}),
350 contentSubtype: callHdr.ContentSubtype,
351 }
352 s.wq = newWriteQuota(defaultWriteQuota, s.done)
353 s.requestRead = func(n int) {
354 t.adjustWindow(s, uint32(n))
355 }
356 // The client side stream context should have exactly the same life cycle with the user provided context.
357 // That means, s.ctx should be read-only. And s.ctx is done iff ctx is done.
358 // So we use the original context here instead of creating a copy.
359 s.ctx = ctx
360 s.trReader = &transportReader{
361 reader: &recvBufferReader{
362 ctx: s.ctx,
363 ctxDone: s.ctx.Done(),
364 recv: s.buf,
365 closeStream: func(err error) {
366 t.CloseStream(s, err)
367 },
368 },
369 windowHandler: func(n int) {
370 t.updateWindow(s, uint32(n))
371 },
372 }
373 return s
374}
375
376func (t *http2Client) getPeer() *peer.Peer {
377 pr := &peer.Peer{
378 Addr: t.remoteAddr,
379 }
380 // Attach Auth info if there is any.
381 if t.authInfo != nil {
382 pr.AuthInfo = t.authInfo
383 }
384 return pr
385}
386
387func (t *http2Client) createHeaderFields(ctx context.Context, callHdr *CallHdr) ([]hpack.HeaderField, error) {
388 aud := t.createAudience(callHdr)
389 authData, err := t.getTrAuthData(ctx, aud)
390 if err != nil {
391 return nil, err
392 }
393 callAuthData, err := t.getCallAuthData(ctx, aud, callHdr)
394 if err != nil {
395 return nil, err
396 }
397 // TODO(mmukhi): Benchmark if the performance gets better if count the metadata and other header fields
398 // first and create a slice of that exact size.
399 // Make the slice of certain predictable size to reduce allocations made by append.
400 hfLen := 7 // :method, :scheme, :path, :authority, content-type, user-agent, te
401 hfLen += len(authData) + len(callAuthData)
402 headerFields := make([]hpack.HeaderField, 0, hfLen)
403 headerFields = append(headerFields, hpack.HeaderField{Name: ":method", Value: "POST"})
404 headerFields = append(headerFields, hpack.HeaderField{Name: ":scheme", Value: t.scheme})
405 headerFields = append(headerFields, hpack.HeaderField{Name: ":path", Value: callHdr.Method})
406 headerFields = append(headerFields, hpack.HeaderField{Name: ":authority", Value: callHdr.Host})
407 headerFields = append(headerFields, hpack.HeaderField{Name: "content-type", Value: contentType(callHdr.ContentSubtype)})
408 headerFields = append(headerFields, hpack.HeaderField{Name: "user-agent", Value: t.userAgent})
409 headerFields = append(headerFields, hpack.HeaderField{Name: "te", Value: "trailers"})
410 if callHdr.PreviousAttempts > 0 {
411 headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-previous-rpc-attempts", Value: strconv.Itoa(callHdr.PreviousAttempts)})
412 }
413
414 if callHdr.SendCompress != "" {
415 headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-encoding", Value: callHdr.SendCompress})
416 }
417 if dl, ok := ctx.Deadline(); ok {
418 // Send out timeout regardless its value. The server can detect timeout context by itself.
419 // TODO(mmukhi): Perhaps this field should be updated when actually writing out to the wire.
420 timeout := dl.Sub(time.Now())
421 headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-timeout", Value: encodeTimeout(timeout)})
422 }
423 for k, v := range authData {
424 headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
425 }
426 for k, v := range callAuthData {
427 headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
428 }
429 if b := stats.OutgoingTags(ctx); b != nil {
430 headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-tags-bin", Value: encodeBinHeader(b)})
431 }
432 if b := stats.OutgoingTrace(ctx); b != nil {
433 headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-trace-bin", Value: encodeBinHeader(b)})
434 }
435
436 if md, added, ok := metadata.FromOutgoingContextRaw(ctx); ok {
437 var k string
438 for _, vv := range added {
439 for i, v := range vv {
440 if i%2 == 0 {
441 k = v
442 continue
443 }
444 // HTTP doesn't allow you to set pseudoheaders after non pseudoheaders were set.
445 if isReservedHeader(k) {
446 continue
447 }
448 headerFields = append(headerFields, hpack.HeaderField{Name: strings.ToLower(k), Value: encodeMetadataHeader(k, v)})
449 }
450 }
451 for k, vv := range md {
452 // HTTP doesn't allow you to set pseudoheaders after non pseudoheaders were set.
453 if isReservedHeader(k) {
454 continue
455 }
456 for _, v := range vv {
457 headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
458 }
459 }
460 }
461 if md, ok := t.md.(*metadata.MD); ok {
462 for k, vv := range *md {
463 if isReservedHeader(k) {
464 continue
465 }
466 for _, v := range vv {
467 headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
468 }
469 }
470 }
471 return headerFields, nil
472}
473
474func (t *http2Client) createAudience(callHdr *CallHdr) string {
475 // Create an audience string only if needed.
476 if len(t.perRPCCreds) == 0 && callHdr.Creds == nil {
477 return ""
478 }
479 // Construct URI required to get auth request metadata.
480 // Omit port if it is the default one.
481 host := strings.TrimSuffix(callHdr.Host, ":443")
482 pos := strings.LastIndex(callHdr.Method, "/")
483 if pos == -1 {
484 pos = len(callHdr.Method)
485 }
486 return "https://" + host + callHdr.Method[:pos]
487}
488
489func (t *http2Client) getTrAuthData(ctx context.Context, audience string) (map[string]string, error) {
490 authData := map[string]string{}
491 for _, c := range t.perRPCCreds {
492 data, err := c.GetRequestMetadata(ctx, audience)
493 if err != nil {
494 if _, ok := status.FromError(err); ok {
495 return nil, err
496 }
497
498 return nil, status.Errorf(codes.Unauthenticated, "transport: %v", err)
499 }
500 for k, v := range data {
501 // Capital header names are illegal in HTTP/2.
502 k = strings.ToLower(k)
503 authData[k] = v
504 }
505 }
506 return authData, nil
507}
508
509func (t *http2Client) getCallAuthData(ctx context.Context, audience string, callHdr *CallHdr) (map[string]string, error) {
510 callAuthData := map[string]string{}
511 // Check if credentials.PerRPCCredentials were provided via call options.
512 // Note: if these credentials are provided both via dial options and call
513 // options, then both sets of credentials will be applied.
514 if callCreds := callHdr.Creds; callCreds != nil {
515 if !t.isSecure && callCreds.RequireTransportSecurity() {
516 return nil, status.Error(codes.Unauthenticated, "transport: cannot send secure credentials on an insecure connection")
517 }
518 data, err := callCreds.GetRequestMetadata(ctx, audience)
519 if err != nil {
520 return nil, status.Errorf(codes.Internal, "transport: %v", err)
521 }
522 for k, v := range data {
523 // Capital header names are illegal in HTTP/2
524 k = strings.ToLower(k)
525 callAuthData[k] = v
526 }
527 }
528 return callAuthData, nil
529}
530
531// NewStream creates a stream and registers it into the transport as "active"
532// streams.
533func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Stream, err error) {
534 ctx = peer.NewContext(ctx, t.getPeer())
535 headerFields, err := t.createHeaderFields(ctx, callHdr)
536 if err != nil {
537 return nil, err
538 }
539 s := t.newStream(ctx, callHdr)
540 cleanup := func(err error) {
541 if s.swapState(streamDone) == streamDone {
542 // If it was already done, return.
543 return
544 }
545 // The stream was unprocessed by the server.
546 atomic.StoreUint32(&s.unprocessed, 1)
547 s.write(recvMsg{err: err})
548 close(s.done)
549 // If headerChan isn't closed, then close it.
550 if atomic.SwapUint32(&s.headerDone, 1) == 0 {
551 close(s.headerChan)
552 }
553
554 }
555 hdr := &headerFrame{
556 hf: headerFields,
557 endStream: false,
558 initStream: func(id uint32) (bool, error) {
559 t.mu.Lock()
560 if state := t.state; state != reachable {
561 t.mu.Unlock()
562 // Do a quick cleanup.
563 err := error(errStreamDrain)
564 if state == closing {
565 err = ErrConnClosing
566 }
567 cleanup(err)
568 return false, err
569 }
570 t.activeStreams[id] = s
571 if channelz.IsOn() {
572 atomic.AddInt64(&t.czData.streamsStarted, 1)
573 atomic.StoreInt64(&t.czData.lastStreamCreatedTime, time.Now().UnixNano())
574 }
575 var sendPing bool
576 // If the number of active streams change from 0 to 1, then check if keepalive
577 // has gone dormant. If so, wake it up.
578 if len(t.activeStreams) == 1 && t.keepaliveEnabled {
579 select {
580 case t.awakenKeepalive <- struct{}{}:
581 sendPing = true
582 // Fill the awakenKeepalive channel again as this channel must be
583 // kept non-writable except at the point that the keepalive()
584 // goroutine is waiting either to be awaken or shutdown.
585 t.awakenKeepalive <- struct{}{}
586 default:
587 }
588 }
589 t.mu.Unlock()
590 return sendPing, nil
591 },
592 onOrphaned: cleanup,
593 wq: s.wq,
594 }
595 firstTry := true
596 var ch chan struct{}
597 checkForStreamQuota := func(it interface{}) bool {
598 if t.streamQuota <= 0 { // Can go negative if server decreases it.
599 if firstTry {
600 t.waitingStreams++
601 }
602 ch = t.streamsQuotaAvailable
603 return false
604 }
605 if !firstTry {
606 t.waitingStreams--
607 }
608 t.streamQuota--
609 h := it.(*headerFrame)
610 h.streamID = t.nextID
611 t.nextID += 2
612 s.id = h.streamID
613 s.fc = &inFlow{limit: uint32(t.initialWindowSize)}
614 if t.streamQuota > 0 && t.waitingStreams > 0 {
615 select {
616 case t.streamsQuotaAvailable <- struct{}{}:
617 default:
618 }
619 }
620 return true
621 }
622 var hdrListSizeErr error
623 checkForHeaderListSize := func(it interface{}) bool {
624 if t.maxSendHeaderListSize == nil {
625 return true
626 }
627 hdrFrame := it.(*headerFrame)
628 var sz int64
629 for _, f := range hdrFrame.hf {
630 if sz += int64(f.Size()); sz > int64(*t.maxSendHeaderListSize) {
631 hdrListSizeErr = status.Errorf(codes.Internal, "header list size to send violates the maximum size (%d bytes) set by server", *t.maxSendHeaderListSize)
632 return false
633 }
634 }
635 return true
636 }
637 for {
638 success, err := t.controlBuf.executeAndPut(func(it interface{}) bool {
639 if !checkForStreamQuota(it) {
640 return false
641 }
642 if !checkForHeaderListSize(it) {
643 return false
644 }
645 return true
646 }, hdr)
647 if err != nil {
648 return nil, err
649 }
650 if success {
651 break
652 }
653 if hdrListSizeErr != nil {
654 return nil, hdrListSizeErr
655 }
656 firstTry = false
657 select {
658 case <-ch:
659 case <-s.ctx.Done():
660 return nil, ContextErr(s.ctx.Err())
661 case <-t.goAway:
662 return nil, errStreamDrain
663 case <-t.ctx.Done():
664 return nil, ErrConnClosing
665 }
666 }
667 if t.statsHandler != nil {
668 outHeader := &stats.OutHeader{
669 Client: true,
670 FullMethod: callHdr.Method,
671 RemoteAddr: t.remoteAddr,
672 LocalAddr: t.localAddr,
673 Compression: callHdr.SendCompress,
674 }
675 t.statsHandler.HandleRPC(s.ctx, outHeader)
676 }
677 return s, nil
678}
679
680// CloseStream clears the footprint of a stream when the stream is not needed any more.
681// This must not be executed in reader's goroutine.
682func (t *http2Client) CloseStream(s *Stream, err error) {
683 var (
684 rst bool
685 rstCode http2.ErrCode
686 )
687 if err != nil {
688 rst = true
689 rstCode = http2.ErrCodeCancel
690 }
691 t.closeStream(s, err, rst, rstCode, status.Convert(err), nil, false)
692}
693
694func (t *http2Client) closeStream(s *Stream, err error, rst bool, rstCode http2.ErrCode, st *status.Status, mdata map[string][]string, eosReceived bool) {
695 // Set stream status to done.
696 if s.swapState(streamDone) == streamDone {
697 // If it was already done, return. If multiple closeStream calls
698 // happen simultaneously, wait for the first to finish.
699 <-s.done
700 return
701 }
702 // status and trailers can be updated here without any synchronization because the stream goroutine will
703 // only read it after it sees an io.EOF error from read or write and we'll write those errors
704 // only after updating this.
705 s.status = st
706 if len(mdata) > 0 {
707 s.trailer = mdata
708 }
709 if err != nil {
710 // This will unblock reads eventually.
711 s.write(recvMsg{err: err})
712 }
713 // If headerChan isn't closed, then close it.
714 if atomic.SwapUint32(&s.headerDone, 1) == 0 {
715 s.noHeaders = true
716 close(s.headerChan)
717 }
718 cleanup := &cleanupStream{
719 streamID: s.id,
720 onWrite: func() {
721 t.mu.Lock()
722 if t.activeStreams != nil {
723 delete(t.activeStreams, s.id)
724 }
725 t.mu.Unlock()
726 if channelz.IsOn() {
727 if eosReceived {
728 atomic.AddInt64(&t.czData.streamsSucceeded, 1)
729 } else {
730 atomic.AddInt64(&t.czData.streamsFailed, 1)
731 }
732 }
733 },
734 rst: rst,
735 rstCode: rstCode,
736 }
737 addBackStreamQuota := func(interface{}) bool {
738 t.streamQuota++
739 if t.streamQuota > 0 && t.waitingStreams > 0 {
740 select {
741 case t.streamsQuotaAvailable <- struct{}{}:
742 default:
743 }
744 }
745 return true
746 }
747 t.controlBuf.executeAndPut(addBackStreamQuota, cleanup)
748 // This will unblock write.
749 close(s.done)
750}
751
752// Close kicks off the shutdown process of the transport. This should be called
753// only once on a transport. Once it is called, the transport should not be
754// accessed any more.
755//
756// This method blocks until the addrConn that initiated this transport is
757// re-connected. This happens because t.onClose() begins reconnect logic at the
758// addrConn level and blocks until the addrConn is successfully connected.
759func (t *http2Client) Close() error {
760 t.mu.Lock()
761 // Make sure we only Close once.
762 if t.state == closing {
763 t.mu.Unlock()
764 return nil
765 }
766 t.state = closing
767 streams := t.activeStreams
768 t.activeStreams = nil
769 t.mu.Unlock()
770 t.controlBuf.finish()
771 t.cancel()
772 err := t.conn.Close()
773 if channelz.IsOn() {
774 channelz.RemoveEntry(t.channelzID)
775 }
776 // Notify all active streams.
777 for _, s := range streams {
778 t.closeStream(s, ErrConnClosing, false, http2.ErrCodeNo, status.New(codes.Unavailable, ErrConnClosing.Desc), nil, false)
779 }
780 if t.statsHandler != nil {
781 connEnd := &stats.ConnEnd{
782 Client: true,
783 }
784 t.statsHandler.HandleConn(t.ctx, connEnd)
785 }
786 t.onClose()
787 return err
788}
789
790// GracefulClose sets the state to draining, which prevents new streams from
791// being created and causes the transport to be closed when the last active
792// stream is closed. If there are no active streams, the transport is closed
793// immediately. This does nothing if the transport is already draining or
794// closing.
795func (t *http2Client) GracefulClose() error {
796 t.mu.Lock()
797 // Make sure we move to draining only from active.
798 if t.state == draining || t.state == closing {
799 t.mu.Unlock()
800 return nil
801 }
802 t.state = draining
803 active := len(t.activeStreams)
804 t.mu.Unlock()
805 if active == 0 {
806 return t.Close()
807 }
808 t.controlBuf.put(&incomingGoAway{})
809 return nil
810}
811
812// Write formats the data into HTTP2 data frame(s) and sends it out. The caller
813// should proceed only if Write returns nil.
814func (t *http2Client) Write(s *Stream, hdr []byte, data []byte, opts *Options) error {
815 if opts.Last {
816 // If it's the last message, update stream state.
817 if !s.compareAndSwapState(streamActive, streamWriteDone) {
818 return errStreamDone
819 }
820 } else if s.getState() != streamActive {
821 return errStreamDone
822 }
823 df := &dataFrame{
824 streamID: s.id,
825 endStream: opts.Last,
826 }
827 if hdr != nil || data != nil { // If it's not an empty data frame.
828 // Add some data to grpc message header so that we can equally
829 // distribute bytes across frames.
830 emptyLen := http2MaxFrameLen - len(hdr)
831 if emptyLen > len(data) {
832 emptyLen = len(data)
833 }
834 hdr = append(hdr, data[:emptyLen]...)
835 data = data[emptyLen:]
836 df.h, df.d = hdr, data
837 // TODO(mmukhi): The above logic in this if can be moved to loopyWriter's data handler.
838 if err := s.wq.get(int32(len(hdr) + len(data))); err != nil {
839 return err
840 }
841 }
842 return t.controlBuf.put(df)
843}
844
845func (t *http2Client) getStream(f http2.Frame) (*Stream, bool) {
846 t.mu.Lock()
847 defer t.mu.Unlock()
848 s, ok := t.activeStreams[f.Header().StreamID]
849 return s, ok
850}
851
852// adjustWindow sends out extra window update over the initial window size
853// of stream if the application is requesting data larger in size than
854// the window.
855func (t *http2Client) adjustWindow(s *Stream, n uint32) {
856 if w := s.fc.maybeAdjust(n); w > 0 {
857 t.controlBuf.put(&outgoingWindowUpdate{streamID: s.id, increment: w})
858 }
859}
860
861// updateWindow adjusts the inbound quota for the stream.
862// Window updates will be sent out when the cumulative quota
863// exceeds the corresponding threshold.
864func (t *http2Client) updateWindow(s *Stream, n uint32) {
865 if w := s.fc.onRead(n); w > 0 {
866 t.controlBuf.put(&outgoingWindowUpdate{streamID: s.id, increment: w})
867 }
868}
869
870// updateFlowControl updates the incoming flow control windows
871// for the transport and the stream based on the current bdp
872// estimation.
873func (t *http2Client) updateFlowControl(n uint32) {
874 t.mu.Lock()
875 for _, s := range t.activeStreams {
876 s.fc.newLimit(n)
877 }
878 t.mu.Unlock()
879 updateIWS := func(interface{}) bool {
880 t.initialWindowSize = int32(n)
881 return true
882 }
883 t.controlBuf.executeAndPut(updateIWS, &outgoingWindowUpdate{streamID: 0, increment: t.fc.newLimit(n)})
884 t.controlBuf.put(&outgoingSettings{
885 ss: []http2.Setting{
886 {
887 ID: http2.SettingInitialWindowSize,
888 Val: n,
889 },
890 },
891 })
892}
893
894func (t *http2Client) handleData(f *http2.DataFrame) {
895 size := f.Header().Length
896 var sendBDPPing bool
897 if t.bdpEst != nil {
898 sendBDPPing = t.bdpEst.add(size)
899 }
900 // Decouple connection's flow control from application's read.
901 // An update on connection's flow control should not depend on
902 // whether user application has read the data or not. Such a
903 // restriction is already imposed on the stream's flow control,
904 // and therefore the sender will be blocked anyways.
905 // Decoupling the connection flow control will prevent other
906 // active(fast) streams from starving in presence of slow or
907 // inactive streams.
908 //
909 if w := t.fc.onData(size); w > 0 {
910 t.controlBuf.put(&outgoingWindowUpdate{
911 streamID: 0,
912 increment: w,
913 })
914 }
915 if sendBDPPing {
916 // Avoid excessive ping detection (e.g. in an L7 proxy)
917 // by sending a window update prior to the BDP ping.
918
919 if w := t.fc.reset(); w > 0 {
920 t.controlBuf.put(&outgoingWindowUpdate{
921 streamID: 0,
922 increment: w,
923 })
924 }
925
926 t.controlBuf.put(bdpPing)
927 }
928 // Select the right stream to dispatch.
929 s, ok := t.getStream(f)
930 if !ok {
931 return
932 }
933 if size > 0 {
934 if err := s.fc.onData(size); err != nil {
935 t.closeStream(s, io.EOF, true, http2.ErrCodeFlowControl, status.New(codes.Internal, err.Error()), nil, false)
936 return
937 }
938 if f.Header().Flags.Has(http2.FlagDataPadded) {
939 if w := s.fc.onRead(size - uint32(len(f.Data()))); w > 0 {
940 t.controlBuf.put(&outgoingWindowUpdate{s.id, w})
941 }
942 }
943 // TODO(bradfitz, zhaoq): A copy is required here because there is no
944 // guarantee f.Data() is consumed before the arrival of next frame.
945 // Can this copy be eliminated?
946 if len(f.Data()) > 0 {
947 data := make([]byte, len(f.Data()))
948 copy(data, f.Data())
949 s.write(recvMsg{data: data})
950 }
951 }
952 // The server has closed the stream without sending trailers. Record that
953 // the read direction is closed, and set the status appropriately.
954 if f.FrameHeader.Flags.Has(http2.FlagDataEndStream) {
955 t.closeStream(s, io.EOF, false, http2.ErrCodeNo, status.New(codes.Internal, "server closed the stream without sending trailers"), nil, true)
956 }
957}
958
959func (t *http2Client) handleRSTStream(f *http2.RSTStreamFrame) {
960 s, ok := t.getStream(f)
961 if !ok {
962 return
963 }
964 if f.ErrCode == http2.ErrCodeRefusedStream {
965 // The stream was unprocessed by the server.
966 atomic.StoreUint32(&s.unprocessed, 1)
967 }
968 statusCode, ok := http2ErrConvTab[f.ErrCode]
969 if !ok {
970 warningf("transport: http2Client.handleRSTStream found no mapped gRPC status for the received http2 error %v", f.ErrCode)
971 statusCode = codes.Unknown
972 }
973 if statusCode == codes.Canceled {
974 // Our deadline was already exceeded, and that was likely the cause of
975 // this cancelation. Alter the status code accordingly.
976 if d, ok := s.ctx.Deadline(); ok && d.After(time.Now()) {
977 statusCode = codes.DeadlineExceeded
978 }
979 }
980 t.closeStream(s, io.EOF, false, http2.ErrCodeNo, status.Newf(statusCode, "stream terminated by RST_STREAM with error code: %v", f.ErrCode), nil, false)
981}
982
983func (t *http2Client) handleSettings(f *http2.SettingsFrame, isFirst bool) {
984 if f.IsAck() {
985 return
986 }
987 var maxStreams *uint32
988 var ss []http2.Setting
989 var updateFuncs []func()
990 f.ForeachSetting(func(s http2.Setting) error {
991 switch s.ID {
992 case http2.SettingMaxConcurrentStreams:
993 maxStreams = new(uint32)
994 *maxStreams = s.Val
995 case http2.SettingMaxHeaderListSize:
996 updateFuncs = append(updateFuncs, func() {
997 t.maxSendHeaderListSize = new(uint32)
998 *t.maxSendHeaderListSize = s.Val
999 })
1000 default:
1001 ss = append(ss, s)
1002 }
1003 return nil
1004 })
1005 if isFirst && maxStreams == nil {
1006 maxStreams = new(uint32)
1007 *maxStreams = math.MaxUint32
1008 }
1009 sf := &incomingSettings{
1010 ss: ss,
1011 }
1012 if maxStreams != nil {
1013 updateStreamQuota := func() {
1014 delta := int64(*maxStreams) - int64(t.maxConcurrentStreams)
1015 t.maxConcurrentStreams = *maxStreams
1016 t.streamQuota += delta
1017 if delta > 0 && t.waitingStreams > 0 {
1018 close(t.streamsQuotaAvailable) // wake all of them up.
1019 t.streamsQuotaAvailable = make(chan struct{}, 1)
1020 }
1021 }
1022 updateFuncs = append(updateFuncs, updateStreamQuota)
1023 }
1024 t.controlBuf.executeAndPut(func(interface{}) bool {
1025 for _, f := range updateFuncs {
1026 f()
1027 }
1028 return true
1029 }, sf)
1030}
1031
1032func (t *http2Client) handlePing(f *http2.PingFrame) {
1033 if f.IsAck() {
1034 // Maybe it's a BDP ping.
1035 if t.bdpEst != nil {
1036 t.bdpEst.calculate(f.Data)
1037 }
1038 return
1039 }
1040 pingAck := &ping{ack: true}
1041 copy(pingAck.data[:], f.Data[:])
1042 t.controlBuf.put(pingAck)
1043}
1044
1045func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) {
1046 t.mu.Lock()
1047 if t.state == closing {
1048 t.mu.Unlock()
1049 return
1050 }
1051 if f.ErrCode == http2.ErrCodeEnhanceYourCalm {
1052 infof("Client received GoAway with http2.ErrCodeEnhanceYourCalm.")
1053 }
1054 id := f.LastStreamID
1055 if id > 0 && id%2 != 1 {
1056 t.mu.Unlock()
1057 t.Close()
1058 return
1059 }
1060 // A client can receive multiple GoAways from the server (see
1061 // https://github.com/grpc/grpc-go/issues/1387). The idea is that the first
1062 // GoAway will be sent with an ID of MaxInt32 and the second GoAway will be
1063 // sent after an RTT delay with the ID of the last stream the server will
1064 // process.
1065 //
1066 // Therefore, when we get the first GoAway we don't necessarily close any
1067 // streams. While in case of second GoAway we close all streams created after
1068 // the GoAwayId. This way streams that were in-flight while the GoAway from
1069 // server was being sent don't get killed.
1070 select {
1071 case <-t.goAway: // t.goAway has been closed (i.e.,multiple GoAways).
1072 // If there are multiple GoAways the first one should always have an ID greater than the following ones.
1073 if id > t.prevGoAwayID {
1074 t.mu.Unlock()
1075 t.Close()
1076 return
1077 }
1078 default:
1079 t.setGoAwayReason(f)
1080 close(t.goAway)
1081 t.state = draining
1082 t.controlBuf.put(&incomingGoAway{})
1083
1084 // This has to be a new goroutine because we're still using the current goroutine to read in the transport.
1085 t.onGoAway(t.goAwayReason)
1086 }
1087 // All streams with IDs greater than the GoAwayId
1088 // and smaller than the previous GoAway ID should be killed.
1089 upperLimit := t.prevGoAwayID
1090 if upperLimit == 0 { // This is the first GoAway Frame.
1091 upperLimit = math.MaxUint32 // Kill all streams after the GoAway ID.
1092 }
1093 for streamID, stream := range t.activeStreams {
1094 if streamID > id && streamID <= upperLimit {
1095 // The stream was unprocessed by the server.
1096 atomic.StoreUint32(&stream.unprocessed, 1)
1097 t.closeStream(stream, errStreamDrain, false, http2.ErrCodeNo, statusGoAway, nil, false)
1098 }
1099 }
1100 t.prevGoAwayID = id
1101 active := len(t.activeStreams)
1102 t.mu.Unlock()
1103 if active == 0 {
1104 t.Close()
1105 }
1106}
1107
1108// setGoAwayReason sets the value of t.goAwayReason based
1109// on the GoAway frame received.
1110// It expects a lock on transport's mutext to be held by
1111// the caller.
1112func (t *http2Client) setGoAwayReason(f *http2.GoAwayFrame) {
1113 t.goAwayReason = GoAwayNoReason
1114 switch f.ErrCode {
1115 case http2.ErrCodeEnhanceYourCalm:
1116 if string(f.DebugData()) == "too_many_pings" {
1117 t.goAwayReason = GoAwayTooManyPings
1118 }
1119 }
1120}
1121
1122func (t *http2Client) GetGoAwayReason() GoAwayReason {
1123 t.mu.Lock()
1124 defer t.mu.Unlock()
1125 return t.goAwayReason
1126}
1127
1128func (t *http2Client) handleWindowUpdate(f *http2.WindowUpdateFrame) {
1129 t.controlBuf.put(&incomingWindowUpdate{
1130 streamID: f.Header().StreamID,
1131 increment: f.Increment,
1132 })
1133}
1134
1135// operateHeaders takes action on the decoded headers.
1136func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
1137 s, ok := t.getStream(frame)
1138 if !ok {
1139 return
1140 }
1141 atomic.StoreUint32(&s.bytesReceived, 1)
1142 var state decodeState
1143 if err := state.decodeHeader(frame); err != nil {
1144 t.closeStream(s, err, true, http2.ErrCodeProtocol, status.New(codes.Internal, err.Error()), nil, false)
1145 // Something wrong. Stops reading even when there is remaining.
1146 return
1147 }
1148
1149 endStream := frame.StreamEnded()
1150 var isHeader bool
1151 defer func() {
1152 if t.statsHandler != nil {
1153 if isHeader {
1154 inHeader := &stats.InHeader{
1155 Client: true,
1156 WireLength: int(frame.Header().Length),
1157 }
1158 t.statsHandler.HandleRPC(s.ctx, inHeader)
1159 } else {
1160 inTrailer := &stats.InTrailer{
1161 Client: true,
1162 WireLength: int(frame.Header().Length),
1163 }
1164 t.statsHandler.HandleRPC(s.ctx, inTrailer)
1165 }
1166 }
1167 }()
1168 // If headers haven't been received yet.
1169 if atomic.SwapUint32(&s.headerDone, 1) == 0 {
1170 if !endStream {
1171 // Headers frame is not actually a trailers-only frame.
1172 isHeader = true
1173 // These values can be set without any synchronization because
1174 // stream goroutine will read it only after seeing a closed
1175 // headerChan which we'll close after setting this.
1176 s.recvCompress = state.encoding
1177 if len(state.mdata) > 0 {
1178 s.header = state.mdata
1179 }
1180 } else {
1181 s.noHeaders = true
1182 }
1183 close(s.headerChan)
1184 }
1185 if !endStream {
1186 return
1187 }
1188 // if client received END_STREAM from server while stream was still active, send RST_STREAM
1189 rst := s.getState() == streamActive
1190 t.closeStream(s, io.EOF, rst, http2.ErrCodeNo, state.status(), state.mdata, true)
1191}
1192
1193// reader runs as a separate goroutine in charge of reading data from network
1194// connection.
1195//
1196// TODO(zhaoq): currently one reader per transport. Investigate whether this is
1197// optimal.
1198// TODO(zhaoq): Check the validity of the incoming frame sequence.
1199func (t *http2Client) reader() {
1200 defer close(t.readerDone)
1201 // Check the validity of server preface.
1202 frame, err := t.framer.fr.ReadFrame()
1203 if err != nil {
1204 t.Close() // this kicks off resetTransport, so must be last before return
1205 return
1206 }
1207 t.conn.SetReadDeadline(time.Time{}) // reset deadline once we get the settings frame (we didn't time out, yay!)
1208 if t.keepaliveEnabled {
1209 atomic.CompareAndSwapUint32(&t.activity, 0, 1)
1210 }
1211 sf, ok := frame.(*http2.SettingsFrame)
1212 if !ok {
1213 t.Close() // this kicks off resetTransport, so must be last before return
1214 return
1215 }
1216 t.onPrefaceReceipt()
1217 t.handleSettings(sf, true)
1218
1219 // loop to keep reading incoming messages on this transport.
1220 for {
1221 frame, err := t.framer.fr.ReadFrame()
1222 if t.keepaliveEnabled {
1223 atomic.CompareAndSwapUint32(&t.activity, 0, 1)
1224 }
1225 if err != nil {
1226 // Abort an active stream if the http2.Framer returns a
1227 // http2.StreamError. This can happen only if the server's response
1228 // is malformed http2.
1229 if se, ok := err.(http2.StreamError); ok {
1230 t.mu.Lock()
1231 s := t.activeStreams[se.StreamID]
1232 t.mu.Unlock()
1233 if s != nil {
1234 // use error detail to provide better err message
1235 code := http2ErrConvTab[se.Code]
1236 msg := t.framer.fr.ErrorDetail().Error()
1237 t.closeStream(s, status.Error(code, msg), true, http2.ErrCodeProtocol, status.New(code, msg), nil, false)
1238 }
1239 continue
1240 } else {
1241 // Transport error.
1242 t.Close()
1243 return
1244 }
1245 }
1246 switch frame := frame.(type) {
1247 case *http2.MetaHeadersFrame:
1248 t.operateHeaders(frame)
1249 case *http2.DataFrame:
1250 t.handleData(frame)
1251 case *http2.RSTStreamFrame:
1252 t.handleRSTStream(frame)
1253 case *http2.SettingsFrame:
1254 t.handleSettings(frame, false)
1255 case *http2.PingFrame:
1256 t.handlePing(frame)
1257 case *http2.GoAwayFrame:
1258 t.handleGoAway(frame)
1259 case *http2.WindowUpdateFrame:
1260 t.handleWindowUpdate(frame)
1261 default:
1262 errorf("transport: http2Client.reader got unhandled frame type %v.", frame)
1263 }
1264 }
1265}
1266
1267// keepalive running in a separate goroutune makes sure the connection is alive by sending pings.
1268func (t *http2Client) keepalive() {
1269 p := &ping{data: [8]byte{}}
1270 timer := time.NewTimer(t.kp.Time)
1271 for {
1272 select {
1273 case <-timer.C:
1274 if atomic.CompareAndSwapUint32(&t.activity, 1, 0) {
1275 timer.Reset(t.kp.Time)
1276 continue
1277 }
1278 // Check if keepalive should go dormant.
1279 t.mu.Lock()
1280 if len(t.activeStreams) < 1 && !t.kp.PermitWithoutStream {
1281 // Make awakenKeepalive writable.
1282 <-t.awakenKeepalive
1283 t.mu.Unlock()
1284 select {
1285 case <-t.awakenKeepalive:
1286 // If the control gets here a ping has been sent
1287 // need to reset the timer with keepalive.Timeout.
1288 case <-t.ctx.Done():
1289 return
1290 }
1291 } else {
1292 t.mu.Unlock()
1293 if channelz.IsOn() {
1294 atomic.AddInt64(&t.czData.kpCount, 1)
1295 }
1296 // Send ping.
1297 t.controlBuf.put(p)
1298 }
1299
1300 // By the time control gets here a ping has been sent one way or the other.
1301 timer.Reset(t.kp.Timeout)
1302 select {
1303 case <-timer.C:
1304 if atomic.CompareAndSwapUint32(&t.activity, 1, 0) {
1305 timer.Reset(t.kp.Time)
1306 continue
1307 }
1308 t.Close()
1309 return
1310 case <-t.ctx.Done():
1311 if !timer.Stop() {
1312 <-timer.C
1313 }
1314 return
1315 }
1316 case <-t.ctx.Done():
1317 if !timer.Stop() {
1318 <-timer.C
1319 }
1320 return
1321 }
1322 }
1323}
1324
1325func (t *http2Client) Error() <-chan struct{} {
1326 return t.ctx.Done()
1327}
1328
1329func (t *http2Client) GoAway() <-chan struct{} {
1330 return t.goAway
1331}
1332
1333func (t *http2Client) ChannelzMetric() *channelz.SocketInternalMetric {
1334 s := channelz.SocketInternalMetric{
1335 StreamsStarted: atomic.LoadInt64(&t.czData.streamsStarted),
1336 StreamsSucceeded: atomic.LoadInt64(&t.czData.streamsSucceeded),
1337 StreamsFailed: atomic.LoadInt64(&t.czData.streamsFailed),
1338 MessagesSent: atomic.LoadInt64(&t.czData.msgSent),
1339 MessagesReceived: atomic.LoadInt64(&t.czData.msgRecv),
1340 KeepAlivesSent: atomic.LoadInt64(&t.czData.kpCount),
1341 LastLocalStreamCreatedTimestamp: time.Unix(0, atomic.LoadInt64(&t.czData.lastStreamCreatedTime)),
1342 LastMessageSentTimestamp: time.Unix(0, atomic.LoadInt64(&t.czData.lastMsgSentTime)),
1343 LastMessageReceivedTimestamp: time.Unix(0, atomic.LoadInt64(&t.czData.lastMsgRecvTime)),
1344 LocalFlowControlWindow: int64(t.fc.getSize()),
1345 SocketOptions: channelz.GetSocketOption(t.conn),
1346 LocalAddr: t.localAddr,
1347 RemoteAddr: t.remoteAddr,
1348 // RemoteName :
1349 }
1350 if au, ok := t.authInfo.(credentials.ChannelzSecurityInfo); ok {
1351 s.Security = au.GetSecurityValue()
1352 }
1353 s.RemoteFlowControlWindow = t.getOutFlowWindow()
1354 return &s
1355}
1356
1357func (t *http2Client) IncrMsgSent() {
1358 atomic.AddInt64(&t.czData.msgSent, 1)
1359 atomic.StoreInt64(&t.czData.lastMsgSentTime, time.Now().UnixNano())
1360}
1361
1362func (t *http2Client) IncrMsgRecv() {
1363 atomic.AddInt64(&t.czData.msgRecv, 1)
1364 atomic.StoreInt64(&t.czData.lastMsgRecvTime, time.Now().UnixNano())
1365}
1366
1367func (t *http2Client) getOutFlowWindow() int64 {
1368 resp := make(chan uint32, 1)
1369 timer := time.NewTimer(time.Second)
1370 defer timer.Stop()
1371 t.controlBuf.put(&outFlowControlSizeRequest{resp})
1372 select {
1373 case sz := <-resp:
1374 return int64(sz)
1375 case <-t.ctxDone:
1376 return -1
1377 case <-timer.C:
1378 return -2
1379 }
1380}
diff --git a/vendor/google.golang.org/grpc/transport/http2_server.go b/vendor/google.golang.org/grpc/internal/transport/http2_server.go
index b6f93e3..df27403 100644
--- a/vendor/google.golang.org/grpc/transport/http2_server.go
+++ b/vendor/google.golang.org/grpc/internal/transport/http2_server.go
@@ -20,10 +20,11 @@ package transport
20 20
21import ( 21import (
22 "bytes" 22 "bytes"
23 "context"
23 "errors" 24 "errors"
25 "fmt"
24 "io" 26 "io"
25 "math" 27 "math"
26 "math/rand"
27 "net" 28 "net"
28 "strconv" 29 "strconv"
29 "sync" 30 "sync"
@@ -31,11 +32,14 @@ import (
31 "time" 32 "time"
32 33
33 "github.com/golang/protobuf/proto" 34 "github.com/golang/protobuf/proto"
34 "golang.org/x/net/context"
35 "golang.org/x/net/http2" 35 "golang.org/x/net/http2"
36 "golang.org/x/net/http2/hpack" 36 "golang.org/x/net/http2/hpack"
37
37 "google.golang.org/grpc/codes" 38 "google.golang.org/grpc/codes"
38 "google.golang.org/grpc/credentials" 39 "google.golang.org/grpc/credentials"
40 "google.golang.org/grpc/grpclog"
41 "google.golang.org/grpc/internal/channelz"
42 "google.golang.org/grpc/internal/grpcrand"
39 "google.golang.org/grpc/keepalive" 43 "google.golang.org/grpc/keepalive"
40 "google.golang.org/grpc/metadata" 44 "google.golang.org/grpc/metadata"
41 "google.golang.org/grpc/peer" 45 "google.golang.org/grpc/peer"
@@ -44,39 +48,37 @@ import (
44 "google.golang.org/grpc/tap" 48 "google.golang.org/grpc/tap"
45) 49)
46 50
47// ErrIllegalHeaderWrite indicates that setting header is illegal because of 51var (
48// the stream's state. 52 // ErrIllegalHeaderWrite indicates that setting header is illegal because of
49var ErrIllegalHeaderWrite = errors.New("transport: the stream is done or WriteHeader was already called") 53 // the stream's state.
54 ErrIllegalHeaderWrite = errors.New("transport: the stream is done or WriteHeader was already called")
55 // ErrHeaderListSizeLimitViolation indicates that the header list size is larger
56 // than the limit set by peer.
57 ErrHeaderListSizeLimitViolation = errors.New("transport: trying to send header list size larger than the limit set by peer")
58)
50 59
51// http2Server implements the ServerTransport interface with HTTP2. 60// http2Server implements the ServerTransport interface with HTTP2.
52type http2Server struct { 61type http2Server struct {
53 ctx context.Context 62 ctx context.Context
63 ctxDone <-chan struct{} // Cache the context.Done() chan
64 cancel context.CancelFunc
54 conn net.Conn 65 conn net.Conn
66 loopy *loopyWriter
67 readerDone chan struct{} // sync point to enable testing.
68 writerDone chan struct{} // sync point to enable testing.
55 remoteAddr net.Addr 69 remoteAddr net.Addr
56 localAddr net.Addr 70 localAddr net.Addr
57 maxStreamID uint32 // max stream ID ever seen 71 maxStreamID uint32 // max stream ID ever seen
58 authInfo credentials.AuthInfo // auth info about the connection 72 authInfo credentials.AuthInfo // auth info about the connection
59 inTapHandle tap.ServerInHandle 73 inTapHandle tap.ServerInHandle
60 // writableChan synchronizes write access to the transport. 74 framer *framer
61 // A writer acquires the write lock by receiving a value on writableChan
62 // and releases it by sending on writableChan.
63 writableChan chan int
64 // shutdownChan is closed when Close is called.
65 // Blocking operations should select on shutdownChan to avoid
66 // blocking forever after Close.
67 shutdownChan chan struct{}
68 framer *framer
69 hBuf *bytes.Buffer // the buffer for HPACK encoding
70 hEnc *hpack.Encoder // HPACK encoder
71 // The max number of concurrent streams. 75 // The max number of concurrent streams.
72 maxStreams uint32 76 maxStreams uint32
73 // controlBuf delivers all the control related tasks (e.g., window 77 // controlBuf delivers all the control related tasks (e.g., window
74 // updates, reset streams, and various settings) to the controller. 78 // updates, reset streams, and various settings) to the controller.
75 controlBuf *controlBuffer 79 controlBuf *controlBuffer
76 fc *inFlow 80 fc *trInFlow
77 // sendQuotaPool provides flow control to outbound message. 81 stats stats.Handler
78 sendQuotaPool *quotaPool
79 stats stats.Handler
80 // Flag to keep track of reading activity on transport. 82 // Flag to keep track of reading activity on transport.
81 // 1 is true and 0 is false. 83 // 1 is true and 0 is false.
82 activity uint32 // Accessed atomically. 84 activity uint32 // Accessed atomically.
@@ -92,11 +94,10 @@ type http2Server struct {
92 // Flag to signify that number of ping strikes should be reset to 0. 94 // Flag to signify that number of ping strikes should be reset to 0.
93 // This is set whenever data or header frames are sent. 95 // This is set whenever data or header frames are sent.
94 // 1 means yes. 96 // 1 means yes.
95 resetPingStrikes uint32 // Accessed atomically. 97 resetPingStrikes uint32 // Accessed atomically.
96 initialWindowSize int32 98 initialWindowSize int32
97 bdpEst *bdpEstimator 99 bdpEst *bdpEstimator
98 100 maxSendHeaderListSize *uint32
99 outQuotaVersion uint32
100 101
101 mu sync.Mutex // guard the following 102 mu sync.Mutex // guard the following
102 103
@@ -109,19 +110,27 @@ type http2Server struct {
109 drainChan chan struct{} 110 drainChan chan struct{}
110 state transportState 111 state transportState
111 activeStreams map[uint32]*Stream 112 activeStreams map[uint32]*Stream
112 // the per-stream outbound flow control window size set by the peer.
113 streamSendQuota uint32
114 // idle is the time instant when the connection went idle. 113 // idle is the time instant when the connection went idle.
115 // This is either the begining of the connection or when the number of 114 // This is either the beginning of the connection or when the number of
116 // RPCs go down to 0. 115 // RPCs go down to 0.
117 // When the connection is busy, this value is set to 0. 116 // When the connection is busy, this value is set to 0.
118 idle time.Time 117 idle time.Time
118
119 // Fields below are for channelz metric collection.
120 channelzID int64 // channelz unique identification number
121 czData *channelzData
119} 122}
120 123
121// newHTTP2Server constructs a ServerTransport based on HTTP2. ConnectionError is 124// newHTTP2Server constructs a ServerTransport based on HTTP2. ConnectionError is
122// returned if something goes wrong. 125// returned if something goes wrong.
123func newHTTP2Server(conn net.Conn, config *ServerConfig) (_ ServerTransport, err error) { 126func newHTTP2Server(conn net.Conn, config *ServerConfig) (_ ServerTransport, err error) {
124 framer := newFramer(conn) 127 writeBufSize := config.WriteBufferSize
128 readBufSize := config.ReadBufferSize
129 maxHeaderListSize := defaultServerMaxHeaderListSize
130 if config.MaxHeaderListSize != nil {
131 maxHeaderListSize = *config.MaxHeaderListSize
132 }
133 framer := newFramer(conn, writeBufSize, readBufSize, maxHeaderListSize)
125 // Send initial settings as connection preface to client. 134 // Send initial settings as connection preface to client.
126 var isettings []http2.Setting 135 var isettings []http2.Setting
127 // TODO(zhaoq): Have a better way to signal "no limit" because 0 is 136 // TODO(zhaoq): Have a better way to signal "no limit" because 0 is
@@ -151,13 +160,19 @@ func newHTTP2Server(conn net.Conn, config *ServerConfig) (_ ServerTransport, err
151 ID: http2.SettingInitialWindowSize, 160 ID: http2.SettingInitialWindowSize,
152 Val: uint32(iwz)}) 161 Val: uint32(iwz)})
153 } 162 }
154 if err := framer.writeSettings(true, isettings...); err != nil { 163 if config.MaxHeaderListSize != nil {
155 return nil, connectionErrorf(true, err, "transport: %v", err) 164 isettings = append(isettings, http2.Setting{
165 ID: http2.SettingMaxHeaderListSize,
166 Val: *config.MaxHeaderListSize,
167 })
168 }
169 if err := framer.fr.WriteSettings(isettings...); err != nil {
170 return nil, connectionErrorf(false, err, "transport: %v", err)
156 } 171 }
157 // Adjust the connection flow control window if needed. 172 // Adjust the connection flow control window if needed.
158 if delta := uint32(icwz - defaultWindowSize); delta > 0 { 173 if delta := uint32(icwz - defaultWindowSize); delta > 0 {
159 if err := framer.writeWindowUpdate(true, 0, delta); err != nil { 174 if err := framer.fr.WriteWindowUpdate(0, delta); err != nil {
160 return nil, connectionErrorf(true, err, "transport: %v", err) 175 return nil, connectionErrorf(false, err, "transport: %v", err)
161 } 176 }
162 } 177 }
163 kp := config.KeepaliveParams 178 kp := config.KeepaliveParams
@@ -182,32 +197,31 @@ func newHTTP2Server(conn net.Conn, config *ServerConfig) (_ ServerTransport, err
182 if kep.MinTime == 0 { 197 if kep.MinTime == 0 {
183 kep.MinTime = defaultKeepalivePolicyMinTime 198 kep.MinTime = defaultKeepalivePolicyMinTime
184 } 199 }
185 var buf bytes.Buffer 200 ctx, cancel := context.WithCancel(context.Background())
186 t := &http2Server{ 201 t := &http2Server{
187 ctx: context.Background(), 202 ctx: ctx,
203 cancel: cancel,
204 ctxDone: ctx.Done(),
188 conn: conn, 205 conn: conn,
189 remoteAddr: conn.RemoteAddr(), 206 remoteAddr: conn.RemoteAddr(),
190 localAddr: conn.LocalAddr(), 207 localAddr: conn.LocalAddr(),
191 authInfo: config.AuthInfo, 208 authInfo: config.AuthInfo,
192 framer: framer, 209 framer: framer,
193 hBuf: &buf, 210 readerDone: make(chan struct{}),
194 hEnc: hpack.NewEncoder(&buf), 211 writerDone: make(chan struct{}),
195 maxStreams: maxStreams, 212 maxStreams: maxStreams,
196 inTapHandle: config.InTapHandle, 213 inTapHandle: config.InTapHandle,
197 controlBuf: newControlBuffer(), 214 fc: &trInFlow{limit: uint32(icwz)},
198 fc: &inFlow{limit: uint32(icwz)},
199 sendQuotaPool: newQuotaPool(defaultWindowSize),
200 state: reachable, 215 state: reachable,
201 writableChan: make(chan int, 1),
202 shutdownChan: make(chan struct{}),
203 activeStreams: make(map[uint32]*Stream), 216 activeStreams: make(map[uint32]*Stream),
204 streamSendQuota: defaultWindowSize,
205 stats: config.StatsHandler, 217 stats: config.StatsHandler,
206 kp: kp, 218 kp: kp,
207 idle: time.Now(), 219 idle: time.Now(),
208 kep: kep, 220 kep: kep,
209 initialWindowSize: iwz, 221 initialWindowSize: iwz,
222 czData: new(channelzData),
210 } 223 }
224 t.controlBuf = newControlBuffer(t.ctxDone)
211 if dynamicWindow { 225 if dynamicWindow {
212 t.bdpEst = &bdpEstimator{ 226 t.bdpEst = &bdpEstimator{
213 bdp: initialWindowSize, 227 bdp: initialWindowSize,
@@ -222,37 +236,83 @@ func newHTTP2Server(conn net.Conn, config *ServerConfig) (_ ServerTransport, err
222 connBegin := &stats.ConnBegin{} 236 connBegin := &stats.ConnBegin{}
223 t.stats.HandleConn(t.ctx, connBegin) 237 t.stats.HandleConn(t.ctx, connBegin)
224 } 238 }
225 go t.controller() 239 if channelz.IsOn() {
240 t.channelzID = channelz.RegisterNormalSocket(t, config.ChannelzParentID, fmt.Sprintf("%s -> %s", t.remoteAddr, t.localAddr))
241 }
242 t.framer.writer.Flush()
243
244 defer func() {
245 if err != nil {
246 t.Close()
247 }
248 }()
249
250 // Check the validity of client preface.
251 preface := make([]byte, len(clientPreface))
252 if _, err := io.ReadFull(t.conn, preface); err != nil {
253 return nil, connectionErrorf(false, err, "transport: http2Server.HandleStreams failed to receive the preface from client: %v", err)
254 }
255 if !bytes.Equal(preface, clientPreface) {
256 return nil, connectionErrorf(false, nil, "transport: http2Server.HandleStreams received bogus greeting from client: %q", preface)
257 }
258
259 frame, err := t.framer.fr.ReadFrame()
260 if err == io.EOF || err == io.ErrUnexpectedEOF {
261 return nil, err
262 }
263 if err != nil {
264 return nil, connectionErrorf(false, err, "transport: http2Server.HandleStreams failed to read initial settings frame: %v", err)
265 }
266 atomic.StoreUint32(&t.activity, 1)
267 sf, ok := frame.(*http2.SettingsFrame)
268 if !ok {
269 return nil, connectionErrorf(false, nil, "transport: http2Server.HandleStreams saw invalid preface type %T from client", frame)
270 }
271 t.handleSettings(sf)
272
273 go func() {
274 t.loopy = newLoopyWriter(serverSide, t.framer, t.controlBuf, t.bdpEst)
275 t.loopy.ssGoAwayHandler = t.outgoingGoAwayHandler
276 if err := t.loopy.run(); err != nil {
277 errorf("transport: loopyWriter.run returning. Err: %v", err)
278 }
279 t.conn.Close()
280 close(t.writerDone)
281 }()
226 go t.keepalive() 282 go t.keepalive()
227 t.writableChan <- 0
228 return t, nil 283 return t, nil
229} 284}
230 285
231// operateHeader takes action on the decoded headers. 286// operateHeader takes action on the decoded headers.
232func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(*Stream), traceCtx func(context.Context, string) context.Context) (close bool) { 287func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(*Stream), traceCtx func(context.Context, string) context.Context) (fatal bool) {
233 buf := newRecvBuffer() 288 streamID := frame.Header().StreamID
234 s := &Stream{ 289 state := decodeState{serverSide: true}
235 id: frame.Header().StreamID, 290 if err := state.decodeHeader(frame); err != nil {
236 st: t, 291 if se, ok := status.FromError(err); ok {
237 buf: buf, 292 t.controlBuf.put(&cleanupStream{
238 fc: &inFlow{limit: uint32(t.initialWindowSize)}, 293 streamID: streamID,
239 } 294 rst: true,
240 295 rstCode: statusCodeConvTab[se.Code()],
241 var state decodeState 296 onWrite: func() {},
242 for _, hf := range frame.Fields { 297 })
243 if err := state.processHeaderField(hf); err != nil {
244 if se, ok := err.(StreamError); ok {
245 t.controlBuf.put(&resetStream{s.id, statusCodeConvTab[se.Code]})
246 }
247 return
248 } 298 }
299 return false
249 } 300 }
250 301
302 buf := newRecvBuffer()
303 s := &Stream{
304 id: streamID,
305 st: t,
306 buf: buf,
307 fc: &inFlow{limit: uint32(t.initialWindowSize)},
308 recvCompress: state.encoding,
309 method: state.method,
310 contentSubtype: state.contentSubtype,
311 }
251 if frame.StreamEnded() { 312 if frame.StreamEnded() {
252 // s is just created by the caller. No lock needed. 313 // s is just created by the caller. No lock needed.
253 s.state = streamReadDone 314 s.state = streamReadDone
254 } 315 }
255 s.recvCompress = state.encoding
256 if state.timeoutSet { 316 if state.timeoutSet {
257 s.ctx, s.cancel = context.WithTimeout(t.ctx, state.timeout) 317 s.ctx, s.cancel = context.WithTimeout(t.ctx, state.timeout)
258 } else { 318 } else {
@@ -266,25 +326,16 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
266 pr.AuthInfo = t.authInfo 326 pr.AuthInfo = t.authInfo
267 } 327 }
268 s.ctx = peer.NewContext(s.ctx, pr) 328 s.ctx = peer.NewContext(s.ctx, pr)
269 // Cache the current stream to the context so that the server application
270 // can find out. Required when the server wants to send some metadata
271 // back to the client (unary call only).
272 s.ctx = newContextWithStream(s.ctx, s)
273 // Attach the received metadata to the context. 329 // Attach the received metadata to the context.
274 if len(state.mdata) > 0 { 330 if len(state.mdata) > 0 {
275 s.ctx = metadata.NewIncomingContext(s.ctx, state.mdata) 331 s.ctx = metadata.NewIncomingContext(s.ctx, state.mdata)
276 } 332 }
277 s.trReader = &transportReader{ 333 if state.statsTags != nil {
278 reader: &recvBufferReader{ 334 s.ctx = stats.SetIncomingTags(s.ctx, state.statsTags)
279 ctx: s.ctx, 335 }
280 recv: s.buf, 336 if state.statsTrace != nil {
281 }, 337 s.ctx = stats.SetIncomingTrace(s.ctx, state.statsTrace)
282 windowHandler: func(n int) {
283 t.updateWindow(s, uint32(n))
284 },
285 } 338 }
286 s.recvCompress = state.encoding
287 s.method = state.method
288 if t.inTapHandle != nil { 339 if t.inTapHandle != nil {
289 var err error 340 var err error
290 info := &tap.Info{ 341 info := &tap.Info{
@@ -293,33 +344,46 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
293 s.ctx, err = t.inTapHandle(s.ctx, info) 344 s.ctx, err = t.inTapHandle(s.ctx, info)
294 if err != nil { 345 if err != nil {
295 warningf("transport: http2Server.operateHeaders got an error from InTapHandle: %v", err) 346 warningf("transport: http2Server.operateHeaders got an error from InTapHandle: %v", err)
296 t.controlBuf.put(&resetStream{s.id, http2.ErrCodeRefusedStream}) 347 t.controlBuf.put(&cleanupStream{
297 return 348 streamID: s.id,
349 rst: true,
350 rstCode: http2.ErrCodeRefusedStream,
351 onWrite: func() {},
352 })
353 return false
298 } 354 }
299 } 355 }
300 t.mu.Lock() 356 t.mu.Lock()
301 if t.state != reachable { 357 if t.state != reachable {
302 t.mu.Unlock() 358 t.mu.Unlock()
303 return 359 return false
304 } 360 }
305 if uint32(len(t.activeStreams)) >= t.maxStreams { 361 if uint32(len(t.activeStreams)) >= t.maxStreams {
306 t.mu.Unlock() 362 t.mu.Unlock()
307 t.controlBuf.put(&resetStream{s.id, http2.ErrCodeRefusedStream}) 363 t.controlBuf.put(&cleanupStream{
308 return 364 streamID: streamID,
365 rst: true,
366 rstCode: http2.ErrCodeRefusedStream,
367 onWrite: func() {},
368 })
369 return false
309 } 370 }
310 if s.id%2 != 1 || s.id <= t.maxStreamID { 371 if streamID%2 != 1 || streamID <= t.maxStreamID {
311 t.mu.Unlock() 372 t.mu.Unlock()
312 // illegal gRPC stream id. 373 // illegal gRPC stream id.
313 errorf("transport: http2Server.HandleStreams received an illegal stream id: %v", s.id) 374 errorf("transport: http2Server.HandleStreams received an illegal stream id: %v", streamID)
314 return true 375 return true
315 } 376 }
316 t.maxStreamID = s.id 377 t.maxStreamID = streamID
317 s.sendQuotaPool = newQuotaPool(int(t.streamSendQuota)) 378 t.activeStreams[streamID] = s
318 t.activeStreams[s.id] = s
319 if len(t.activeStreams) == 1 { 379 if len(t.activeStreams) == 1 {
320 t.idle = time.Time{} 380 t.idle = time.Time{}
321 } 381 }
322 t.mu.Unlock() 382 t.mu.Unlock()
383 if channelz.IsOn() {
384 atomic.AddInt64(&t.czData.streamsStarted, 1)
385 atomic.StoreInt64(&t.czData.lastStreamCreatedTime, time.Now().UnixNano())
386 }
323 s.requestRead = func(n int) { 387 s.requestRead = func(n int) {
324 t.adjustWindow(s, uint32(n)) 388 t.adjustWindow(s, uint32(n))
325 } 389 }
@@ -335,61 +399,51 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
335 } 399 }
336 t.stats.HandleRPC(s.ctx, inHeader) 400 t.stats.HandleRPC(s.ctx, inHeader)
337 } 401 }
402 s.ctxDone = s.ctx.Done()
403 s.wq = newWriteQuota(defaultWriteQuota, s.ctxDone)
404 s.trReader = &transportReader{
405 reader: &recvBufferReader{
406 ctx: s.ctx,
407 ctxDone: s.ctxDone,
408 recv: s.buf,
409 },
410 windowHandler: func(n int) {
411 t.updateWindow(s, uint32(n))
412 },
413 }
414 // Register the stream with loopy.
415 t.controlBuf.put(&registerStream{
416 streamID: s.id,
417 wq: s.wq,
418 })
338 handle(s) 419 handle(s)
339 return 420 return false
340} 421}
341 422
342// HandleStreams receives incoming streams using the given handler. This is 423// HandleStreams receives incoming streams using the given handler. This is
343// typically run in a separate goroutine. 424// typically run in a separate goroutine.
344// traceCtx attaches trace to ctx and returns the new context. 425// traceCtx attaches trace to ctx and returns the new context.
345func (t *http2Server) HandleStreams(handle func(*Stream), traceCtx func(context.Context, string) context.Context) { 426func (t *http2Server) HandleStreams(handle func(*Stream), traceCtx func(context.Context, string) context.Context) {
346 // Check the validity of client preface. 427 defer close(t.readerDone)
347 preface := make([]byte, len(clientPreface))
348 if _, err := io.ReadFull(t.conn, preface); err != nil {
349 // Only log if it isn't a simple tcp accept check (ie: tcp balancer doing open/close socket)
350 if err != io.EOF {
351 errorf("transport: http2Server.HandleStreams failed to receive the preface from client: %v", err)
352 }
353 t.Close()
354 return
355 }
356 if !bytes.Equal(preface, clientPreface) {
357 errorf("transport: http2Server.HandleStreams received bogus greeting from client: %q", preface)
358 t.Close()
359 return
360 }
361
362 frame, err := t.framer.readFrame()
363 if err == io.EOF || err == io.ErrUnexpectedEOF {
364 t.Close()
365 return
366 }
367 if err != nil {
368 errorf("transport: http2Server.HandleStreams failed to read initial settings frame: %v", err)
369 t.Close()
370 return
371 }
372 atomic.StoreUint32(&t.activity, 1)
373 sf, ok := frame.(*http2.SettingsFrame)
374 if !ok {
375 errorf("transport: http2Server.HandleStreams saw invalid preface type %T from client", frame)
376 t.Close()
377 return
378 }
379 t.handleSettings(sf)
380
381 for { 428 for {
382 frame, err := t.framer.readFrame() 429 frame, err := t.framer.fr.ReadFrame()
383 atomic.StoreUint32(&t.activity, 1) 430 atomic.StoreUint32(&t.activity, 1)
384 if err != nil { 431 if err != nil {
385 if se, ok := err.(http2.StreamError); ok { 432 if se, ok := err.(http2.StreamError); ok {
433 warningf("transport: http2Server.HandleStreams encountered http2.StreamError: %v", se)
386 t.mu.Lock() 434 t.mu.Lock()
387 s := t.activeStreams[se.StreamID] 435 s := t.activeStreams[se.StreamID]
388 t.mu.Unlock() 436 t.mu.Unlock()
389 if s != nil { 437 if s != nil {
390 t.closeStream(s) 438 t.closeStream(s, true, se.Code, nil, false)
439 } else {
440 t.controlBuf.put(&cleanupStream{
441 streamID: se.StreamID,
442 rst: true,
443 rstCode: se.Code,
444 onWrite: func() {},
445 })
391 } 446 }
392 t.controlBuf.put(&resetStream{se.StreamID, se.Code})
393 continue 447 continue
394 } 448 }
395 if err == io.EOF || err == io.ErrUnexpectedEOF { 449 if err == io.EOF || err == io.ErrUnexpectedEOF {
@@ -443,33 +497,20 @@ func (t *http2Server) getStream(f http2.Frame) (*Stream, bool) {
443// of stream if the application is requesting data larger in size than 497// of stream if the application is requesting data larger in size than
444// the window. 498// the window.
445func (t *http2Server) adjustWindow(s *Stream, n uint32) { 499func (t *http2Server) adjustWindow(s *Stream, n uint32) {
446 s.mu.Lock()
447 defer s.mu.Unlock()
448 if s.state == streamDone {
449 return
450 }
451 if w := s.fc.maybeAdjust(n); w > 0 { 500 if w := s.fc.maybeAdjust(n); w > 0 {
452 if cw := t.fc.resetPendingUpdate(); cw > 0 { 501 t.controlBuf.put(&outgoingWindowUpdate{streamID: s.id, increment: w})
453 t.controlBuf.put(&windowUpdate{0, cw, false})
454 }
455 t.controlBuf.put(&windowUpdate{s.id, w, true})
456 } 502 }
503
457} 504}
458 505
459// updateWindow adjusts the inbound quota for the stream and the transport. 506// updateWindow adjusts the inbound quota for the stream and the transport.
460// Window updates will deliver to the controller for sending when 507// Window updates will deliver to the controller for sending when
461// the cumulative quota exceeds the corresponding threshold. 508// the cumulative quota exceeds the corresponding threshold.
462func (t *http2Server) updateWindow(s *Stream, n uint32) { 509func (t *http2Server) updateWindow(s *Stream, n uint32) {
463 s.mu.Lock()
464 defer s.mu.Unlock()
465 if s.state == streamDone {
466 return
467 }
468 if w := s.fc.onRead(n); w > 0 { 510 if w := s.fc.onRead(n); w > 0 {
469 if cw := t.fc.resetPendingUpdate(); cw > 0 { 511 t.controlBuf.put(&outgoingWindowUpdate{streamID: s.id,
470 t.controlBuf.put(&windowUpdate{0, cw, false}) 512 increment: w,
471 } 513 })
472 t.controlBuf.put(&windowUpdate{s.id, w, true})
473 } 514 }
474} 515}
475 516
@@ -483,13 +524,15 @@ func (t *http2Server) updateFlowControl(n uint32) {
483 } 524 }
484 t.initialWindowSize = int32(n) 525 t.initialWindowSize = int32(n)
485 t.mu.Unlock() 526 t.mu.Unlock()
486 t.controlBuf.put(&windowUpdate{0, t.fc.newLimit(n), false}) 527 t.controlBuf.put(&outgoingWindowUpdate{
487 t.controlBuf.put(&settings{ 528 streamID: 0,
488 ack: false, 529 increment: t.fc.newLimit(n),
530 })
531 t.controlBuf.put(&outgoingSettings{
489 ss: []http2.Setting{ 532 ss: []http2.Setting{
490 { 533 {
491 ID: http2.SettingInitialWindowSize, 534 ID: http2.SettingInitialWindowSize,
492 Val: uint32(n), 535 Val: n,
493 }, 536 },
494 }, 537 },
495 }) 538 })
@@ -500,7 +543,7 @@ func (t *http2Server) handleData(f *http2.DataFrame) {
500 size := f.Header().Length 543 size := f.Header().Length
501 var sendBDPPing bool 544 var sendBDPPing bool
502 if t.bdpEst != nil { 545 if t.bdpEst != nil {
503 sendBDPPing = t.bdpEst.add(uint32(size)) 546 sendBDPPing = t.bdpEst.add(size)
504 } 547 }
505 // Decouple connection's flow control from application's read. 548 // Decouple connection's flow control from application's read.
506 // An update on connection's flow control should not depend on 549 // An update on connection's flow control should not depend on
@@ -510,21 +553,22 @@ func (t *http2Server) handleData(f *http2.DataFrame) {
510 // Decoupling the connection flow control will prevent other 553 // Decoupling the connection flow control will prevent other
511 // active(fast) streams from starving in presence of slow or 554 // active(fast) streams from starving in presence of slow or
512 // inactive streams. 555 // inactive streams.
513 // 556 if w := t.fc.onData(size); w > 0 {
514 // Furthermore, if a bdpPing is being sent out we can piggyback 557 t.controlBuf.put(&outgoingWindowUpdate{
515 // connection's window update for the bytes we just received. 558 streamID: 0,
559 increment: w,
560 })
561 }
516 if sendBDPPing { 562 if sendBDPPing {
517 t.controlBuf.put(&windowUpdate{0, uint32(size), false}) 563 // Avoid excessive ping detection (e.g. in an L7 proxy)
518 t.controlBuf.put(bdpPing) 564 // by sending a window update prior to the BDP ping.
519 } else { 565 if w := t.fc.reset(); w > 0 {
520 if err := t.fc.onData(uint32(size)); err != nil { 566 t.controlBuf.put(&outgoingWindowUpdate{
521 errorf("transport: http2Server %v", err) 567 streamID: 0,
522 t.Close() 568 increment: w,
523 return 569 })
524 }
525 if w := t.fc.onRead(uint32(size)); w > 0 {
526 t.controlBuf.put(&windowUpdate{0, w, true})
527 } 570 }
571 t.controlBuf.put(bdpPing)
528 } 572 }
529 // Select the right stream to dispatch. 573 // Select the right stream to dispatch.
530 s, ok := t.getStream(f) 574 s, ok := t.getStream(f)
@@ -532,23 +576,15 @@ func (t *http2Server) handleData(f *http2.DataFrame) {
532 return 576 return
533 } 577 }
534 if size > 0 { 578 if size > 0 {
535 s.mu.Lock() 579 if err := s.fc.onData(size); err != nil {
536 if s.state == streamDone { 580 t.closeStream(s, true, http2.ErrCodeFlowControl, nil, false)
537 s.mu.Unlock()
538 return
539 }
540 if err := s.fc.onData(uint32(size)); err != nil {
541 s.mu.Unlock()
542 t.closeStream(s)
543 t.controlBuf.put(&resetStream{s.id, http2.ErrCodeFlowControl})
544 return 581 return
545 } 582 }
546 if f.Header().Flags.Has(http2.FlagDataPadded) { 583 if f.Header().Flags.Has(http2.FlagDataPadded) {
547 if w := s.fc.onRead(uint32(size) - uint32(len(f.Data()))); w > 0 { 584 if w := s.fc.onRead(size - uint32(len(f.Data()))); w > 0 {
548 t.controlBuf.put(&windowUpdate{s.id, w, true}) 585 t.controlBuf.put(&outgoingWindowUpdate{s.id, w})
549 } 586 }
550 } 587 }
551 s.mu.Unlock()
552 // TODO(bradfitz, zhaoq): A copy is required here because there is no 588 // TODO(bradfitz, zhaoq): A copy is required here because there is no
553 // guarantee f.Data() is consumed before the arrival of next frame. 589 // guarantee f.Data() is consumed before the arrival of next frame.
554 // Can this copy be eliminated? 590 // Can this copy be eliminated?
@@ -560,11 +596,7 @@ func (t *http2Server) handleData(f *http2.DataFrame) {
560 } 596 }
561 if f.Header().Flags.Has(http2.FlagDataEndStream) { 597 if f.Header().Flags.Has(http2.FlagDataEndStream) {
562 // Received the end of stream from the client. 598 // Received the end of stream from the client.
563 s.mu.Lock() 599 s.compareAndSwapState(streamActive, streamReadDone)
564 if s.state != streamDone {
565 s.state = streamReadDone
566 }
567 s.mu.Unlock()
568 s.write(recvMsg{err: io.EOF}) 600 s.write(recvMsg{err: io.EOF})
569 } 601 }
570} 602}
@@ -574,7 +606,7 @@ func (t *http2Server) handleRSTStream(f *http2.RSTStreamFrame) {
574 if !ok { 606 if !ok {
575 return 607 return
576 } 608 }
577 t.closeStream(s) 609 t.closeStream(s, false, 0, nil, false)
578} 610}
579 611
580func (t *http2Server) handleSettings(f *http2.SettingsFrame) { 612func (t *http2Server) handleSettings(f *http2.SettingsFrame) {
@@ -582,12 +614,27 @@ func (t *http2Server) handleSettings(f *http2.SettingsFrame) {
582 return 614 return
583 } 615 }
584 var ss []http2.Setting 616 var ss []http2.Setting
617 var updateFuncs []func()
585 f.ForeachSetting(func(s http2.Setting) error { 618 f.ForeachSetting(func(s http2.Setting) error {
586 ss = append(ss, s) 619 switch s.ID {
620 case http2.SettingMaxHeaderListSize:
621 updateFuncs = append(updateFuncs, func() {
622 t.maxSendHeaderListSize = new(uint32)
623 *t.maxSendHeaderListSize = s.Val
624 })
625 default:
626 ss = append(ss, s)
627 }
587 return nil 628 return nil
588 }) 629 })
589 // The settings will be applied once the ack is sent. 630 t.controlBuf.executeAndPut(func(interface{}) bool {
590 t.controlBuf.put(&settings{ack: true, ss: ss}) 631 for _, f := range updateFuncs {
632 f()
633 }
634 return true
635 }, &incomingSettings{
636 ss: ss,
637 })
591} 638}
592 639
593const ( 640const (
@@ -627,7 +674,7 @@ func (t *http2Server) handlePing(f *http2.PingFrame) {
627 t.mu.Unlock() 674 t.mu.Unlock()
628 if ns < 1 && !t.kep.PermitWithoutStream { 675 if ns < 1 && !t.kep.PermitWithoutStream {
629 // Keepalive shouldn't be active thus, this new ping should 676 // Keepalive shouldn't be active thus, this new ping should
630 // have come after atleast defaultPingTimeout. 677 // have come after at least defaultPingTimeout.
631 if t.lastPingAt.Add(defaultPingTimeout).After(now) { 678 if t.lastPingAt.Add(defaultPingTimeout).After(now) {
632 t.pingStrikes++ 679 t.pingStrikes++
633 } 680 }
@@ -640,69 +687,52 @@ func (t *http2Server) handlePing(f *http2.PingFrame) {
640 687
641 if t.pingStrikes > maxPingStrikes { 688 if t.pingStrikes > maxPingStrikes {
642 // Send goaway and close the connection. 689 // Send goaway and close the connection.
690 errorf("transport: Got too many pings from the client, closing the connection.")
643 t.controlBuf.put(&goAway{code: http2.ErrCodeEnhanceYourCalm, debugData: []byte("too_many_pings"), closeConn: true}) 691 t.controlBuf.put(&goAway{code: http2.ErrCodeEnhanceYourCalm, debugData: []byte("too_many_pings"), closeConn: true})
644 } 692 }
645} 693}
646 694
647func (t *http2Server) handleWindowUpdate(f *http2.WindowUpdateFrame) { 695func (t *http2Server) handleWindowUpdate(f *http2.WindowUpdateFrame) {
648 id := f.Header().StreamID 696 t.controlBuf.put(&incomingWindowUpdate{
649 incr := f.Increment 697 streamID: f.Header().StreamID,
650 if id == 0 { 698 increment: f.Increment,
651 t.sendQuotaPool.add(int(incr)) 699 })
652 return
653 }
654 if s, ok := t.getStream(f); ok {
655 s.sendQuotaPool.add(int(incr))
656 }
657} 700}
658 701
659func (t *http2Server) writeHeaders(s *Stream, b *bytes.Buffer, endStream bool) error { 702func appendHeaderFieldsFromMD(headerFields []hpack.HeaderField, md metadata.MD) []hpack.HeaderField {
660 first := true 703 for k, vv := range md {
661 endHeaders := false 704 if isReservedHeader(k) {
662 var err error 705 // Clients don't tolerate reading restricted headers after some non restricted ones were sent.
663 defer func() { 706 continue
664 if err == nil {
665 // Reset ping strikes when seding headers since that might cause the
666 // peer to send ping.
667 atomic.StoreUint32(&t.resetPingStrikes, 1)
668 }
669 }()
670 // Sends the headers in a single batch.
671 for !endHeaders {
672 size := t.hBuf.Len()
673 if size > http2MaxFrameLen {
674 size = http2MaxFrameLen
675 } else {
676 endHeaders = true
677 } 707 }
678 if first { 708 for _, v := range vv {
679 p := http2.HeadersFrameParam{ 709 headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
680 StreamID: s.id,
681 BlockFragment: b.Next(size),
682 EndStream: endStream,
683 EndHeaders: endHeaders,
684 }
685 err = t.framer.writeHeaders(endHeaders, p)
686 first = false
687 } else {
688 err = t.framer.writeContinuation(endHeaders, s.id, endHeaders, b.Next(size))
689 } 710 }
690 if err != nil { 711 }
691 t.Close() 712 return headerFields
692 return connectionErrorf(true, err, "transport: %v", err) 713}
714
715func (t *http2Server) checkForHeaderListSize(it interface{}) bool {
716 if t.maxSendHeaderListSize == nil {
717 return true
718 }
719 hdrFrame := it.(*headerFrame)
720 var sz int64
721 for _, f := range hdrFrame.hf {
722 if sz += int64(f.Size()); sz > int64(*t.maxSendHeaderListSize) {
723 errorf("header list size to send violates the maximum size (%d bytes) set by client", *t.maxSendHeaderListSize)
724 return false
693 } 725 }
694 } 726 }
695 return nil 727 return true
696} 728}
697 729
698// WriteHeader sends the header metedata md back to the client. 730// WriteHeader sends the header metedata md back to the client.
699func (t *http2Server) WriteHeader(s *Stream, md metadata.MD) error { 731func (t *http2Server) WriteHeader(s *Stream, md metadata.MD) error {
700 s.mu.Lock() 732 if s.updateHeaderSent() || s.getState() == streamDone {
701 if s.headerOk || s.state == streamDone {
702 s.mu.Unlock()
703 return ErrIllegalHeaderWrite 733 return ErrIllegalHeaderWrite
704 } 734 }
705 s.headerOk = true 735 s.hdrMu.Lock()
706 if md.Len() > 0 { 736 if md.Len() > 0 {
707 if s.header.Len() > 0 { 737 if s.header.Len() > 0 {
708 s.header = metadata.Join(s.header, md) 738 s.header = metadata.Join(s.header, md)
@@ -710,37 +740,45 @@ func (t *http2Server) WriteHeader(s *Stream, md metadata.MD) error {
710 s.header = md 740 s.header = md
711 } 741 }
712 } 742 }
713 md = s.header 743 if err := t.writeHeaderLocked(s); err != nil {
714 s.mu.Unlock() 744 s.hdrMu.Unlock()
715 if _, err := wait(s.ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil {
716 return err 745 return err
717 } 746 }
718 t.hBuf.Reset() 747 s.hdrMu.Unlock()
719 t.hEnc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) 748 return nil
720 t.hEnc.WriteField(hpack.HeaderField{Name: "content-type", Value: "application/grpc"}) 749}
750
751func (t *http2Server) writeHeaderLocked(s *Stream) error {
752 // TODO(mmukhi): Benchmark if the performance gets better if count the metadata and other header fields
753 // first and create a slice of that exact size.
754 headerFields := make([]hpack.HeaderField, 0, 2) // at least :status, content-type will be there if none else.
755 headerFields = append(headerFields, hpack.HeaderField{Name: ":status", Value: "200"})
756 headerFields = append(headerFields, hpack.HeaderField{Name: "content-type", Value: contentType(s.contentSubtype)})
721 if s.sendCompress != "" { 757 if s.sendCompress != "" {
722 t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-encoding", Value: s.sendCompress}) 758 headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-encoding", Value: s.sendCompress})
723 } 759 }
724 for k, vv := range md { 760 headerFields = appendHeaderFieldsFromMD(headerFields, s.header)
725 if isReservedHeader(k) { 761 success, err := t.controlBuf.executeAndPut(t.checkForHeaderListSize, &headerFrame{
726 // Clients don't tolerate reading restricted headers after some non restricted ones were sent. 762 streamID: s.id,
727 continue 763 hf: headerFields,
728 } 764 endStream: false,
729 for _, v := range vv { 765 onWrite: func() {
730 t.hEnc.WriteField(hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)}) 766 atomic.StoreUint32(&t.resetPingStrikes, 1)
767 },
768 })
769 if !success {
770 if err != nil {
771 return err
731 } 772 }
732 } 773 t.closeStream(s, true, http2.ErrCodeInternal, nil, false)
733 bufLen := t.hBuf.Len() 774 return ErrHeaderListSizeLimitViolation
734 if err := t.writeHeaders(s, t.hBuf, false); err != nil {
735 return err
736 } 775 }
737 if t.stats != nil { 776 if t.stats != nil {
738 outHeader := &stats.OutHeader{ 777 // Note: WireLength is not set in outHeader.
739 WireLength: bufLen, 778 // TODO(mmukhi): Revisit this later, if needed.
740 } 779 outHeader := &stats.OutHeader{}
741 t.stats.HandleRPC(s.Context(), outHeader) 780 t.stats.HandleRPC(s.Context(), outHeader)
742 } 781 }
743 t.writableChan <- 0
744 return nil 782 return nil
745} 783}
746 784
@@ -749,204 +787,108 @@ func (t *http2Server) WriteHeader(s *Stream, md metadata.MD) error {
749// TODO(zhaoq): Now it indicates the end of entire stream. Revisit if early 787// TODO(zhaoq): Now it indicates the end of entire stream. Revisit if early
750// OK is adopted. 788// OK is adopted.
751func (t *http2Server) WriteStatus(s *Stream, st *status.Status) error { 789func (t *http2Server) WriteStatus(s *Stream, st *status.Status) error {
752 var headersSent, hasHeader bool 790 if s.getState() == streamDone {
753 s.mu.Lock()
754 if s.state == streamDone {
755 s.mu.Unlock()
756 return nil 791 return nil
757 } 792 }
758 if s.headerOk { 793 s.hdrMu.Lock()
759 headersSent = true 794 // TODO(mmukhi): Benchmark if the performance gets better if count the metadata and other header fields
760 } 795 // first and create a slice of that exact size.
761 if s.header.Len() > 0 { 796 headerFields := make([]hpack.HeaderField, 0, 2) // grpc-status and grpc-message will be there if none else.
762 hasHeader = true 797 if !s.updateHeaderSent() { // No headers have been sent.
763 } 798 if len(s.header) > 0 { // Send a separate header frame.
764 s.mu.Unlock() 799 if err := t.writeHeaderLocked(s); err != nil {
765 800 s.hdrMu.Unlock()
766 if !headersSent && hasHeader { 801 return err
767 t.WriteHeader(s, nil) 802 }
768 headersSent = true 803 } else { // Send a trailer only response.
769 } 804 headerFields = append(headerFields, hpack.HeaderField{Name: ":status", Value: "200"})
770 805 headerFields = append(headerFields, hpack.HeaderField{Name: "content-type", Value: contentType(s.contentSubtype)})
771 if _, err := wait(s.ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil { 806 }
772 return err
773 }
774 t.hBuf.Reset()
775 if !headersSent {
776 t.hEnc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
777 t.hEnc.WriteField(hpack.HeaderField{Name: "content-type", Value: "application/grpc"})
778 } 807 }
779 t.hEnc.WriteField( 808 headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-status", Value: strconv.Itoa(int(st.Code()))})
780 hpack.HeaderField{ 809 headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-message", Value: encodeGrpcMessage(st.Message())})
781 Name: "grpc-status",
782 Value: strconv.Itoa(int(st.Code())),
783 })
784 t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-message", Value: encodeGrpcMessage(st.Message())})
785 810
786 if p := st.Proto(); p != nil && len(p.Details) > 0 { 811 if p := st.Proto(); p != nil && len(p.Details) > 0 {
787 stBytes, err := proto.Marshal(p) 812 stBytes, err := proto.Marshal(p)
788 if err != nil { 813 if err != nil {
789 // TODO: return error instead, when callers are able to handle it. 814 // TODO: return error instead, when callers are able to handle it.
790 panic(err) 815 grpclog.Errorf("transport: failed to marshal rpc status: %v, error: %v", p, err)
816 } else {
817 headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-status-details-bin", Value: encodeBinHeader(stBytes)})
791 } 818 }
792
793 t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-status-details-bin", Value: encodeBinHeader(stBytes)})
794 } 819 }
795 820
796 // Attach the trailer metadata. 821 // Attach the trailer metadata.
797 for k, vv := range s.trailer { 822 headerFields = appendHeaderFieldsFromMD(headerFields, s.trailer)
798 // Clients don't tolerate reading restricted headers after some non restricted ones were sent. 823 trailingHeader := &headerFrame{
799 if isReservedHeader(k) { 824 streamID: s.id,
800 continue 825 hf: headerFields,
801 } 826 endStream: true,
802 for _, v := range vv { 827 onWrite: func() {
803 t.hEnc.WriteField(hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)}) 828 atomic.StoreUint32(&t.resetPingStrikes, 1)
804 } 829 },
805 } 830 }
806 bufLen := t.hBuf.Len() 831 s.hdrMu.Unlock()
807 if err := t.writeHeaders(s, t.hBuf, true); err != nil { 832 success, err := t.controlBuf.execute(t.checkForHeaderListSize, trailingHeader)
808 t.Close() 833 if !success {
809 return err 834 if err != nil {
835 return err
836 }
837 t.closeStream(s, true, http2.ErrCodeInternal, nil, false)
838 return ErrHeaderListSizeLimitViolation
810 } 839 }
840 t.closeStream(s, false, 0, trailingHeader, true)
811 if t.stats != nil { 841 if t.stats != nil {
812 outTrailer := &stats.OutTrailer{ 842 t.stats.HandleRPC(s.Context(), &stats.OutTrailer{})
813 WireLength: bufLen,
814 }
815 t.stats.HandleRPC(s.Context(), outTrailer)
816 } 843 }
817 t.closeStream(s)
818 t.writableChan <- 0
819 return nil 844 return nil
820} 845}
821 846
822// Write converts the data into HTTP2 data frame and sends it out. Non-nil error 847// Write converts the data into HTTP2 data frame and sends it out. Non-nil error
823// is returns if it fails (e.g., framing error, transport error). 848// is returns if it fails (e.g., framing error, transport error).
824func (t *http2Server) Write(s *Stream, data []byte, opts *Options) (err error) { 849func (t *http2Server) Write(s *Stream, hdr []byte, data []byte, opts *Options) error {
825 // TODO(zhaoq): Support multi-writers for a single stream. 850 if !s.isHeaderSent() { // Headers haven't been written yet.
826 var writeHeaderFrame bool 851 if err := t.WriteHeader(s, nil); err != nil {
827 s.mu.Lock() 852 // TODO(mmukhi, dfawley): Make sure this is the right code to return.
828 if s.state == streamDone { 853 return status.Errorf(codes.Internal, "transport: %v", err)
829 s.mu.Unlock()
830 return streamErrorf(codes.Unknown, "the stream has been done")
831 }
832 if !s.headerOk {
833 writeHeaderFrame = true
834 }
835 s.mu.Unlock()
836 if writeHeaderFrame {
837 t.WriteHeader(s, nil)
838 }
839 r := bytes.NewBuffer(data)
840 var (
841 p []byte
842 oqv uint32
843 )
844 for {
845 if r.Len() == 0 && p == nil {
846 return nil
847 }
848 oqv = atomic.LoadUint32(&t.outQuotaVersion)
849 size := http2MaxFrameLen
850 // Wait until the stream has some quota to send the data.
851 sq, err := wait(s.ctx, nil, nil, t.shutdownChan, s.sendQuotaPool.acquire())
852 if err != nil {
853 return err
854 }
855 // Wait until the transport has some quota to send the data.
856 tq, err := wait(s.ctx, nil, nil, t.shutdownChan, t.sendQuotaPool.acquire())
857 if err != nil {
858 return err
859 }
860 if sq < size {
861 size = sq
862 }
863 if tq < size {
864 size = tq
865 } 854 }
866 if p == nil { 855 } else {
867 p = r.Next(size) 856 // Writing headers checks for this condition.
868 } 857 if s.getState() == streamDone {
869 ps := len(p) 858 // TODO(mmukhi, dfawley): Should the server write also return io.EOF?
870 if ps < sq { 859 s.cancel()
871 // Overbooked stream quota. Return it back. 860 select {
872 s.sendQuotaPool.add(sq - ps) 861 case <-t.ctx.Done():
873 } 862 return ErrConnClosing
874 if ps < tq { 863 default:
875 // Overbooked transport quota. Return it back.
876 t.sendQuotaPool.add(tq - ps)
877 }
878 t.framer.adjustNumWriters(1)
879 // Got some quota. Try to acquire writing privilege on the
880 // transport.
881 if _, err := wait(s.ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil {
882 if _, ok := err.(StreamError); ok {
883 // Return the connection quota back.
884 t.sendQuotaPool.add(ps)
885 }
886 if t.framer.adjustNumWriters(-1) == 0 {
887 // This writer is the last one in this batch and has the
888 // responsibility to flush the buffered frames. It queues
889 // a flush request to controlBuf instead of flushing directly
890 // in order to avoid the race with other writing or flushing.
891 t.controlBuf.put(&flushIO{})
892 }
893 return err
894 }
895 select {
896 case <-s.ctx.Done():
897 t.sendQuotaPool.add(ps)
898 if t.framer.adjustNumWriters(-1) == 0 {
899 t.controlBuf.put(&flushIO{})
900 } 864 }
901 t.writableChan <- 0
902 return ContextErr(s.ctx.Err()) 865 return ContextErr(s.ctx.Err())
903 default:
904 }
905 if oqv != atomic.LoadUint32(&t.outQuotaVersion) {
906 // InitialWindowSize settings frame must have been received after we
907 // acquired send quota but before we got the writable channel.
908 // We must forsake this write.
909 t.sendQuotaPool.add(ps)
910 s.sendQuotaPool.add(ps)
911 if t.framer.adjustNumWriters(-1) == 0 {
912 t.controlBuf.put(&flushIO{})
913 }
914 t.writableChan <- 0
915 continue
916 }
917 var forceFlush bool
918 if r.Len() == 0 && t.framer.adjustNumWriters(0) == 1 && !opts.Last {
919 forceFlush = true
920 }
921 // Reset ping strikes when sending data since this might cause
922 // the peer to send ping.
923 atomic.StoreUint32(&t.resetPingStrikes, 1)
924 if err := t.framer.writeData(forceFlush, s.id, false, p); err != nil {
925 t.Close()
926 return connectionErrorf(true, err, "transport: %v", err)
927 } 866 }
928 p = nil
929 if t.framer.adjustNumWriters(-1) == 0 {
930 t.framer.flushWrite()
931 }
932 t.writableChan <- 0
933 } 867 }
934 868 // Add some data to header frame so that we can equally distribute bytes across frames.
935} 869 emptyLen := http2MaxFrameLen - len(hdr)
936 870 if emptyLen > len(data) {
937func (t *http2Server) applySettings(ss []http2.Setting) { 871 emptyLen = len(data)
938 for _, s := range ss { 872 }
939 if s.ID == http2.SettingInitialWindowSize { 873 hdr = append(hdr, data[:emptyLen]...)
940 t.mu.Lock() 874 data = data[emptyLen:]
941 defer t.mu.Unlock() 875 df := &dataFrame{
942 for _, stream := range t.activeStreams { 876 streamID: s.id,
943 stream.sendQuotaPool.add(int(s.Val) - int(t.streamSendQuota)) 877 h: hdr,
944 } 878 d: data,
945 t.streamSendQuota = s.Val 879 onEachWrite: func() {
946 atomic.AddUint32(&t.outQuotaVersion, 1) 880 atomic.StoreUint32(&t.resetPingStrikes, 1)
881 },
882 }
883 if err := s.wq.get(int32(len(hdr) + len(data))); err != nil {
884 select {
885 case <-t.ctx.Done():
886 return ErrConnClosing
887 default:
947 } 888 }
948 889 return ContextErr(s.ctx.Err())
949 } 890 }
891 return t.controlBuf.put(df)
950} 892}
951 893
952// keepalive running in a separate goroutine does the following: 894// keepalive running in a separate goroutine does the following:
@@ -962,7 +904,7 @@ func (t *http2Server) keepalive() {
962 maxAge := time.NewTimer(t.kp.MaxConnectionAge) 904 maxAge := time.NewTimer(t.kp.MaxConnectionAge)
963 keepalive := time.NewTimer(t.kp.Time) 905 keepalive := time.NewTimer(t.kp.Time)
964 // NOTE: All exit paths of this function should reset their 906 // NOTE: All exit paths of this function should reset their
965 // respecitve timers. A failure to do so will cause the 907 // respective timers. A failure to do so will cause the
966 // following clean-up to deadlock and eventually leak. 908 // following clean-up to deadlock and eventually leak.
967 defer func() { 909 defer func() {
968 if !maxIdle.Stop() { 910 if !maxIdle.Stop() {
@@ -991,7 +933,7 @@ func (t *http2Server) keepalive() {
991 // The connection has been idle for a duration of keepalive.MaxConnectionIdle or more. 933 // The connection has been idle for a duration of keepalive.MaxConnectionIdle or more.
992 // Gracefully close the connection. 934 // Gracefully close the connection.
993 t.drain(http2.ErrCodeNo, []byte{}) 935 t.drain(http2.ErrCodeNo, []byte{})
994 // Reseting the timer so that the clean-up doesn't deadlock. 936 // Resetting the timer so that the clean-up doesn't deadlock.
995 maxIdle.Reset(infinity) 937 maxIdle.Reset(infinity)
996 return 938 return
997 } 939 }
@@ -1003,9 +945,9 @@ func (t *http2Server) keepalive() {
1003 case <-maxAge.C: 945 case <-maxAge.C:
1004 // Close the connection after grace period. 946 // Close the connection after grace period.
1005 t.Close() 947 t.Close()
1006 // Reseting the timer so that the clean-up doesn't deadlock. 948 // Resetting the timer so that the clean-up doesn't deadlock.
1007 maxAge.Reset(infinity) 949 maxAge.Reset(infinity)
1008 case <-t.shutdownChan: 950 case <-t.ctx.Done():
1009 } 951 }
1010 return 952 return
1011 case <-keepalive.C: 953 case <-keepalive.C:
@@ -1016,98 +958,17 @@ func (t *http2Server) keepalive() {
1016 } 958 }
1017 if pingSent { 959 if pingSent {
1018 t.Close() 960 t.Close()
1019 // Reseting the timer so that the clean-up doesn't deadlock. 961 // Resetting the timer so that the clean-up doesn't deadlock.
1020 keepalive.Reset(infinity) 962 keepalive.Reset(infinity)
1021 return 963 return
1022 } 964 }
1023 pingSent = true 965 pingSent = true
966 if channelz.IsOn() {
967 atomic.AddInt64(&t.czData.kpCount, 1)
968 }
1024 t.controlBuf.put(p) 969 t.controlBuf.put(p)
1025 keepalive.Reset(t.kp.Timeout) 970 keepalive.Reset(t.kp.Timeout)
1026 case <-t.shutdownChan: 971 case <-t.ctx.Done():
1027 return
1028 }
1029 }
1030}
1031
1032var goAwayPing = &ping{data: [8]byte{1, 6, 1, 8, 0, 3, 3, 9}}
1033
1034// controller running in a separate goroutine takes charge of sending control
1035// frames (e.g., window update, reset stream, setting, etc.) to the server.
1036func (t *http2Server) controller() {
1037 for {
1038 select {
1039 case i := <-t.controlBuf.get():
1040 t.controlBuf.load()
1041 select {
1042 case <-t.writableChan:
1043 switch i := i.(type) {
1044 case *windowUpdate:
1045 t.framer.writeWindowUpdate(i.flush, i.streamID, i.increment)
1046 case *settings:
1047 if i.ack {
1048 t.framer.writeSettingsAck(true)
1049 t.applySettings(i.ss)
1050 } else {
1051 t.framer.writeSettings(true, i.ss...)
1052 }
1053 case *resetStream:
1054 t.framer.writeRSTStream(true, i.streamID, i.code)
1055 case *goAway:
1056 t.mu.Lock()
1057 if t.state == closing {
1058 t.mu.Unlock()
1059 // The transport is closing.
1060 return
1061 }
1062 sid := t.maxStreamID
1063 if !i.headsUp {
1064 // Stop accepting more streams now.
1065 t.state = draining
1066 t.mu.Unlock()
1067 t.framer.writeGoAway(true, sid, i.code, i.debugData)
1068 if i.closeConn {
1069 // Abruptly close the connection following the GoAway.
1070 t.Close()
1071 }
1072 t.writableChan <- 0
1073 continue
1074 }
1075 t.mu.Unlock()
1076 // For a graceful close, send out a GoAway with stream ID of MaxUInt32,
1077 // Follow that with a ping and wait for the ack to come back or a timer
1078 // to expire. During this time accept new streams since they might have
1079 // originated before the GoAway reaches the client.
1080 // After getting the ack or timer expiration send out another GoAway this
1081 // time with an ID of the max stream server intends to process.
1082 t.framer.writeGoAway(true, math.MaxUint32, http2.ErrCodeNo, []byte{})
1083 t.framer.writePing(true, false, goAwayPing.data)
1084 go func() {
1085 timer := time.NewTimer(time.Minute)
1086 defer timer.Stop()
1087 select {
1088 case <-t.drainChan:
1089 case <-timer.C:
1090 case <-t.shutdownChan:
1091 return
1092 }
1093 t.controlBuf.put(&goAway{code: i.code, debugData: i.debugData})
1094 }()
1095 case *flushIO:
1096 t.framer.flushWrite()
1097 case *ping:
1098 if !i.ack {
1099 t.bdpEst.timesnap(i.data)
1100 }
1101 t.framer.writePing(true, i.ack, i.data)
1102 default:
1103 errorf("transport: http2Server.controller got unexpected item type %v\n", i)
1104 }
1105 t.writableChan <- 0
1106 continue
1107 case <-t.shutdownChan:
1108 return
1109 }
1110 case <-t.shutdownChan:
1111 return 972 return
1112 } 973 }
1113 } 974 }
@@ -1116,7 +977,7 @@ func (t *http2Server) controller() {
1116// Close starts shutting down the http2Server transport. 977// Close starts shutting down the http2Server transport.
1117// TODO(zhaoq): Now the destruction is not blocked on any pending streams. This 978// TODO(zhaoq): Now the destruction is not blocked on any pending streams. This
1118// could cause some resource issue. Revisit this later. 979// could cause some resource issue. Revisit this later.
1119func (t *http2Server) Close() (err error) { 980func (t *http2Server) Close() error {
1120 t.mu.Lock() 981 t.mu.Lock()
1121 if t.state == closing { 982 if t.state == closing {
1122 t.mu.Unlock() 983 t.mu.Unlock()
@@ -1126,8 +987,12 @@ func (t *http2Server) Close() (err error) {
1126 streams := t.activeStreams 987 streams := t.activeStreams
1127 t.activeStreams = nil 988 t.activeStreams = nil
1128 t.mu.Unlock() 989 t.mu.Unlock()
1129 close(t.shutdownChan) 990 t.controlBuf.finish()
1130 err = t.conn.Close() 991 t.cancel()
992 err := t.conn.Close()
993 if channelz.IsOn() {
994 channelz.RemoveEntry(t.channelzID)
995 }
1131 // Cancel all active streams. 996 // Cancel all active streams.
1132 for _, s := range streams { 997 for _, s := range streams {
1133 s.cancel() 998 s.cancel()
@@ -1136,32 +1001,48 @@ func (t *http2Server) Close() (err error) {
1136 connEnd := &stats.ConnEnd{} 1001 connEnd := &stats.ConnEnd{}
1137 t.stats.HandleConn(t.ctx, connEnd) 1002 t.stats.HandleConn(t.ctx, connEnd)
1138 } 1003 }
1139 return 1004 return err
1140} 1005}
1141 1006
1142// closeStream clears the footprint of a stream when the stream is not needed 1007// closeStream clears the footprint of a stream when the stream is not needed
1143// any more. 1008// any more.
1144func (t *http2Server) closeStream(s *Stream) { 1009func (t *http2Server) closeStream(s *Stream, rst bool, rstCode http2.ErrCode, hdr *headerFrame, eosReceived bool) {
1145 t.mu.Lock() 1010 if s.swapState(streamDone) == streamDone {
1146 delete(t.activeStreams, s.id) 1011 // If the stream was already done, return.
1147 if len(t.activeStreams) == 0 { 1012 return
1148 t.idle = time.Now()
1149 }
1150 if t.state == draining && len(t.activeStreams) == 0 {
1151 defer t.Close()
1152 } 1013 }
1153 t.mu.Unlock()
1154 // In case stream sending and receiving are invoked in separate 1014 // In case stream sending and receiving are invoked in separate
1155 // goroutines (e.g., bi-directional streaming), cancel needs to be 1015 // goroutines (e.g., bi-directional streaming), cancel needs to be
1156 // called to interrupt the potential blocking on other goroutines. 1016 // called to interrupt the potential blocking on other goroutines.
1157 s.cancel() 1017 s.cancel()
1158 s.mu.Lock() 1018 cleanup := &cleanupStream{
1159 if s.state == streamDone { 1019 streamID: s.id,
1160 s.mu.Unlock() 1020 rst: rst,
1161 return 1021 rstCode: rstCode,
1022 onWrite: func() {
1023 t.mu.Lock()
1024 if t.activeStreams != nil {
1025 delete(t.activeStreams, s.id)
1026 if len(t.activeStreams) == 0 {
1027 t.idle = time.Now()
1028 }
1029 }
1030 t.mu.Unlock()
1031 if channelz.IsOn() {
1032 if eosReceived {
1033 atomic.AddInt64(&t.czData.streamsSucceeded, 1)
1034 } else {
1035 atomic.AddInt64(&t.czData.streamsFailed, 1)
1036 }
1037 }
1038 },
1039 }
1040 if hdr != nil {
1041 hdr.cleanup = cleanup
1042 t.controlBuf.put(hdr)
1043 } else {
1044 t.controlBuf.put(cleanup)
1162 } 1045 }
1163 s.state = streamDone
1164 s.mu.Unlock()
1165} 1046}
1166 1047
1167func (t *http2Server) RemoteAddr() net.Addr { 1048func (t *http2Server) RemoteAddr() net.Addr {
@@ -1182,7 +1063,111 @@ func (t *http2Server) drain(code http2.ErrCode, debugData []byte) {
1182 t.controlBuf.put(&goAway{code: code, debugData: debugData, headsUp: true}) 1063 t.controlBuf.put(&goAway{code: code, debugData: debugData, headsUp: true})
1183} 1064}
1184 1065
1185var rgen = rand.New(rand.NewSource(time.Now().UnixNano())) 1066var goAwayPing = &ping{data: [8]byte{1, 6, 1, 8, 0, 3, 3, 9}}
1067
1068// Handles outgoing GoAway and returns true if loopy needs to put itself
1069// in draining mode.
1070func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) {
1071 t.mu.Lock()
1072 if t.state == closing { // TODO(mmukhi): This seems unnecessary.
1073 t.mu.Unlock()
1074 // The transport is closing.
1075 return false, ErrConnClosing
1076 }
1077 sid := t.maxStreamID
1078 if !g.headsUp {
1079 // Stop accepting more streams now.
1080 t.state = draining
1081 if len(t.activeStreams) == 0 {
1082 g.closeConn = true
1083 }
1084 t.mu.Unlock()
1085 if err := t.framer.fr.WriteGoAway(sid, g.code, g.debugData); err != nil {
1086 return false, err
1087 }
1088 if g.closeConn {
1089 // Abruptly close the connection following the GoAway (via
1090 // loopywriter). But flush out what's inside the buffer first.
1091 t.framer.writer.Flush()
1092 return false, fmt.Errorf("transport: Connection closing")
1093 }
1094 return true, nil
1095 }
1096 t.mu.Unlock()
1097 // For a graceful close, send out a GoAway with stream ID of MaxUInt32,
1098 // Follow that with a ping and wait for the ack to come back or a timer
1099 // to expire. During this time accept new streams since they might have
1100 // originated before the GoAway reaches the client.
1101 // After getting the ack or timer expiration send out another GoAway this
1102 // time with an ID of the max stream server intends to process.
1103 if err := t.framer.fr.WriteGoAway(math.MaxUint32, http2.ErrCodeNo, []byte{}); err != nil {
1104 return false, err
1105 }
1106 if err := t.framer.fr.WritePing(false, goAwayPing.data); err != nil {
1107 return false, err
1108 }
1109 go func() {
1110 timer := time.NewTimer(time.Minute)
1111 defer timer.Stop()
1112 select {
1113 case <-t.drainChan:
1114 case <-timer.C:
1115 case <-t.ctx.Done():
1116 return
1117 }
1118 t.controlBuf.put(&goAway{code: g.code, debugData: g.debugData})
1119 }()
1120 return false, nil
1121}
1122
1123func (t *http2Server) ChannelzMetric() *channelz.SocketInternalMetric {
1124 s := channelz.SocketInternalMetric{
1125 StreamsStarted: atomic.LoadInt64(&t.czData.streamsStarted),
1126 StreamsSucceeded: atomic.LoadInt64(&t.czData.streamsSucceeded),
1127 StreamsFailed: atomic.LoadInt64(&t.czData.streamsFailed),
1128 MessagesSent: atomic.LoadInt64(&t.czData.msgSent),
1129 MessagesReceived: atomic.LoadInt64(&t.czData.msgRecv),
1130 KeepAlivesSent: atomic.LoadInt64(&t.czData.kpCount),
1131 LastRemoteStreamCreatedTimestamp: time.Unix(0, atomic.LoadInt64(&t.czData.lastStreamCreatedTime)),
1132 LastMessageSentTimestamp: time.Unix(0, atomic.LoadInt64(&t.czData.lastMsgSentTime)),
1133 LastMessageReceivedTimestamp: time.Unix(0, atomic.LoadInt64(&t.czData.lastMsgRecvTime)),
1134 LocalFlowControlWindow: int64(t.fc.getSize()),
1135 SocketOptions: channelz.GetSocketOption(t.conn),
1136 LocalAddr: t.localAddr,
1137 RemoteAddr: t.remoteAddr,
1138 // RemoteName :
1139 }
1140 if au, ok := t.authInfo.(credentials.ChannelzSecurityInfo); ok {
1141 s.Security = au.GetSecurityValue()
1142 }
1143 s.RemoteFlowControlWindow = t.getOutFlowWindow()
1144 return &s
1145}
1146
1147func (t *http2Server) IncrMsgSent() {
1148 atomic.AddInt64(&t.czData.msgSent, 1)
1149 atomic.StoreInt64(&t.czData.lastMsgSentTime, time.Now().UnixNano())
1150}
1151
1152func (t *http2Server) IncrMsgRecv() {
1153 atomic.AddInt64(&t.czData.msgRecv, 1)
1154 atomic.StoreInt64(&t.czData.lastMsgRecvTime, time.Now().UnixNano())
1155}
1156
1157func (t *http2Server) getOutFlowWindow() int64 {
1158 resp := make(chan uint32)
1159 timer := time.NewTimer(time.Second)
1160 defer timer.Stop()
1161 t.controlBuf.put(&outFlowControlSizeRequest{resp})
1162 select {
1163 case sz := <-resp:
1164 return int64(sz)
1165 case <-t.ctxDone:
1166 return -1
1167 case <-timer.C:
1168 return -2
1169 }
1170}
1186 1171
1187func getJitter(v time.Duration) time.Duration { 1172func getJitter(v time.Duration) time.Duration {
1188 if v == infinity { 1173 if v == infinity {
@@ -1190,6 +1175,6 @@ func getJitter(v time.Duration) time.Duration {
1190 } 1175 }
1191 // Generate a jitter between +/- 10% of the value. 1176 // Generate a jitter between +/- 10% of the value.
1192 r := int64(v / 10) 1177 r := int64(v / 10)
1193 j := rgen.Int63n(2*r) - r 1178 j := grpcrand.Int63n(2*r) - r
1194 return time.Duration(j) 1179 return time.Duration(j)
1195} 1180}
diff --git a/vendor/google.golang.org/grpc/transport/http_util.go b/vendor/google.golang.org/grpc/internal/transport/http_util.go
index 685c6fb..77a2cfa 100644
--- a/vendor/google.golang.org/grpc/transport/http_util.go
+++ b/vendor/google.golang.org/grpc/internal/transport/http_util.go
@@ -24,12 +24,13 @@ import (
24 "encoding/base64" 24 "encoding/base64"
25 "fmt" 25 "fmt"
26 "io" 26 "io"
27 "math"
27 "net" 28 "net"
28 "net/http" 29 "net/http"
29 "strconv" 30 "strconv"
30 "strings" 31 "strings"
31 "sync/atomic"
32 "time" 32 "time"
33 "unicode/utf8"
33 34
34 "github.com/golang/protobuf/proto" 35 "github.com/golang/protobuf/proto"
35 "golang.org/x/net/http2" 36 "golang.org/x/net/http2"
@@ -44,8 +45,12 @@ const (
44 http2MaxFrameLen = 16384 // 16KB frame 45 http2MaxFrameLen = 16384 // 16KB frame
45 // http://http2.github.io/http2-spec/#SettingValues 46 // http://http2.github.io/http2-spec/#SettingValues
46 http2InitHeaderTableSize = 4096 47 http2InitHeaderTableSize = 4096
47 // http2IOBufSize specifies the buffer size for sending frames. 48 // baseContentType is the base content-type for gRPC. This is a valid
48 http2IOBufSize = 32 * 1024 49 // content-type on it's own, but can also include a content-subtype such as
50 // "proto" as a suffix after "+" or ";". See
51 // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests
52 // for more details.
53 baseContentType = "application/grpc"
49) 54)
50 55
51var ( 56var (
@@ -64,7 +69,7 @@ var (
64 http2.ErrCodeConnect: codes.Internal, 69 http2.ErrCodeConnect: codes.Internal,
65 http2.ErrCodeEnhanceYourCalm: codes.ResourceExhausted, 70 http2.ErrCodeEnhanceYourCalm: codes.ResourceExhausted,
66 http2.ErrCodeInadequateSecurity: codes.PermissionDenied, 71 http2.ErrCodeInadequateSecurity: codes.PermissionDenied,
67 http2.ErrCodeHTTP11Required: codes.FailedPrecondition, 72 http2.ErrCodeHTTP11Required: codes.Internal,
68 } 73 }
69 statusCodeConvTab = map[codes.Code]http2.ErrCode{ 74 statusCodeConvTab = map[codes.Code]http2.ErrCode{
70 codes.Internal: http2.ErrCodeInternal, 75 codes.Internal: http2.ErrCodeInternal,
@@ -111,7 +116,12 @@ type decodeState struct {
111 timeout time.Duration 116 timeout time.Duration
112 method string 117 method string
113 // key-value metadata map from the peer. 118 // key-value metadata map from the peer.
114 mdata map[string][]string 119 mdata map[string][]string
120 statsTags []byte
121 statsTrace []byte
122 contentSubtype string
123 // whether decoding on server side or not
124 serverSide bool
115} 125}
116 126
117// isReservedHeader checks whether hdr belongs to HTTP2 headers 127// isReservedHeader checks whether hdr belongs to HTTP2 headers
@@ -123,12 +133,16 @@ func isReservedHeader(hdr string) bool {
123 } 133 }
124 switch hdr { 134 switch hdr {
125 case "content-type", 135 case "content-type",
136 "user-agent",
126 "grpc-message-type", 137 "grpc-message-type",
127 "grpc-encoding", 138 "grpc-encoding",
128 "grpc-message", 139 "grpc-message",
129 "grpc-status", 140 "grpc-status",
130 "grpc-timeout", 141 "grpc-timeout",
131 "grpc-status-details-bin", 142 "grpc-status-details-bin",
143 // Intentionally exclude grpc-previous-rpc-attempts and
144 // grpc-retry-pushback-ms, which are "reserved", but their API
145 // intentionally works via metadata.
132 "te": 146 "te":
133 return true 147 return true
134 default: 148 default:
@@ -136,28 +150,55 @@ func isReservedHeader(hdr string) bool {
136 } 150 }
137} 151}
138 152
139// isWhitelistedPseudoHeader checks whether hdr belongs to HTTP2 pseudoheaders 153// isWhitelistedHeader checks whether hdr should be propagated into metadata
140// that should be propagated into metadata visible to users. 154// visible to users, even though it is classified as "reserved", above.
141func isWhitelistedPseudoHeader(hdr string) bool { 155func isWhitelistedHeader(hdr string) bool {
142 switch hdr { 156 switch hdr {
143 case ":authority": 157 case ":authority", "user-agent":
144 return true 158 return true
145 default: 159 default:
146 return false 160 return false
147 } 161 }
148} 162}
149 163
150func validContentType(t string) bool { 164// contentSubtype returns the content-subtype for the given content-type. The
151 e := "application/grpc" 165// given content-type must be a valid content-type that starts with
152 if !strings.HasPrefix(t, e) { 166// "application/grpc". A content-subtype will follow "application/grpc" after a
153 return false 167// "+" or ";". See
168// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
169// more details.
170//
171// If contentType is not a valid content-type for gRPC, the boolean
172// will be false, otherwise true. If content-type == "application/grpc",
173// "application/grpc+", or "application/grpc;", the boolean will be true,
174// but no content-subtype will be returned.
175//
176// contentType is assumed to be lowercase already.
177func contentSubtype(contentType string) (string, bool) {
178 if contentType == baseContentType {
179 return "", true
180 }
181 if !strings.HasPrefix(contentType, baseContentType) {
182 return "", false
183 }
184 // guaranteed since != baseContentType and has baseContentType prefix
185 switch contentType[len(baseContentType)] {
186 case '+', ';':
187 // this will return true for "application/grpc+" or "application/grpc;"
188 // which the previous validContentType function tested to be valid, so we
189 // just say that no content-subtype is specified in this case
190 return contentType[len(baseContentType)+1:], true
191 default:
192 return "", false
154 } 193 }
155 // Support variations on the content-type 194}
156 // (e.g. "application/grpc+blah", "application/grpc;blah"). 195
157 if len(t) > len(e) && t[len(e)] != '+' && t[len(e)] != ';' { 196// contentSubtype is assumed to be lowercase
158 return false 197func contentType(contentSubtype string) string {
198 if contentSubtype == "" {
199 return baseContentType
159 } 200 }
160 return true 201 return baseContentType + "+" + contentSubtype
161} 202}
162 203
163func (d *decodeState) status() *status.Status { 204func (d *decodeState) status() *status.Status {
@@ -197,13 +238,22 @@ func decodeMetadataHeader(k, v string) (string, error) {
197 return v, nil 238 return v, nil
198} 239}
199 240
200func (d *decodeState) decodeResponseHeader(frame *http2.MetaHeadersFrame) error { 241func (d *decodeState) decodeHeader(frame *http2.MetaHeadersFrame) error {
242 // frame.Truncated is set to true when framer detects that the current header
243 // list size hits MaxHeaderListSize limit.
244 if frame.Truncated {
245 return status.Error(codes.Internal, "peer header list size exceeded limit")
246 }
201 for _, hf := range frame.Fields { 247 for _, hf := range frame.Fields {
202 if err := d.processHeaderField(hf); err != nil { 248 if err := d.processHeaderField(hf); err != nil {
203 return err 249 return err
204 } 250 }
205 } 251 }
206 252
253 if d.serverSide {
254 return nil
255 }
256
207 // If grpc status exists, no need to check further. 257 // If grpc status exists, no need to check further.
208 if d.rawStatusCode != nil || d.statusGen != nil { 258 if d.rawStatusCode != nil || d.statusGen != nil {
209 return nil 259 return nil
@@ -212,7 +262,7 @@ func (d *decodeState) decodeResponseHeader(frame *http2.MetaHeadersFrame) error
212 // If grpc status doesn't exist and http status doesn't exist, 262 // If grpc status doesn't exist and http status doesn't exist,
213 // then it's a malformed header. 263 // then it's a malformed header.
214 if d.httpStatus == nil { 264 if d.httpStatus == nil {
215 return streamErrorf(codes.Internal, "malformed header: doesn't contain status(gRPC or HTTP)") 265 return status.Error(codes.Internal, "malformed header: doesn't contain status(gRPC or HTTP)")
216 } 266 }
217 267
218 if *(d.httpStatus) != http.StatusOK { 268 if *(d.httpStatus) != http.StatusOK {
@@ -220,33 +270,46 @@ func (d *decodeState) decodeResponseHeader(frame *http2.MetaHeadersFrame) error
220 if !ok { 270 if !ok {
221 code = codes.Unknown 271 code = codes.Unknown
222 } 272 }
223 return streamErrorf(code, http.StatusText(*(d.httpStatus))) 273 return status.Error(code, http.StatusText(*(d.httpStatus)))
224 } 274 }
225 275
226 // gRPC status doesn't exist and http status is OK. 276 // gRPC status doesn't exist and http status is OK.
227 // Set rawStatusCode to be unknown and return nil error. 277 // Set rawStatusCode to be unknown and return nil error.
228 // So that, if the stream has ended this Unknown status 278 // So that, if the stream has ended this Unknown status
229 // will be propogated to the user. 279 // will be propagated to the user.
230 // Otherwise, it will be ignored. In which case, status from 280 // Otherwise, it will be ignored. In which case, status from
231 // a later trailer, that has StreamEnded flag set, is propogated. 281 // a later trailer, that has StreamEnded flag set, is propagated.
232 code := int(codes.Unknown) 282 code := int(codes.Unknown)
233 d.rawStatusCode = &code 283 d.rawStatusCode = &code
234 return nil 284 return nil
285}
235 286
287func (d *decodeState) addMetadata(k, v string) {
288 if d.mdata == nil {
289 d.mdata = make(map[string][]string)
290 }
291 d.mdata[k] = append(d.mdata[k], v)
236} 292}
237 293
238func (d *decodeState) processHeaderField(f hpack.HeaderField) error { 294func (d *decodeState) processHeaderField(f hpack.HeaderField) error {
239 switch f.Name { 295 switch f.Name {
240 case "content-type": 296 case "content-type":
241 if !validContentType(f.Value) { 297 contentSubtype, validContentType := contentSubtype(f.Value)
242 return streamErrorf(codes.FailedPrecondition, "transport: received the unexpected content-type %q", f.Value) 298 if !validContentType {
299 return status.Errorf(codes.Internal, "transport: received the unexpected content-type %q", f.Value)
243 } 300 }
301 d.contentSubtype = contentSubtype
302 // TODO: do we want to propagate the whole content-type in the metadata,
303 // or come up with a way to just propagate the content-subtype if it was set?
304 // ie {"content-type": "application/grpc+proto"} or {"content-subtype": "proto"}
305 // in the metadata?
306 d.addMetadata(f.Name, f.Value)
244 case "grpc-encoding": 307 case "grpc-encoding":
245 d.encoding = f.Value 308 d.encoding = f.Value
246 case "grpc-status": 309 case "grpc-status":
247 code, err := strconv.Atoi(f.Value) 310 code, err := strconv.Atoi(f.Value)
248 if err != nil { 311 if err != nil {
249 return streamErrorf(codes.Internal, "transport: malformed grpc-status: %v", err) 312 return status.Errorf(codes.Internal, "transport: malformed grpc-status: %v", err)
250 } 313 }
251 d.rawStatusCode = &code 314 d.rawStatusCode = &code
252 case "grpc-message": 315 case "grpc-message":
@@ -254,39 +317,51 @@ func (d *decodeState) processHeaderField(f hpack.HeaderField) error {
254 case "grpc-status-details-bin": 317 case "grpc-status-details-bin":
255 v, err := decodeBinHeader(f.Value) 318 v, err := decodeBinHeader(f.Value)
256 if err != nil { 319 if err != nil {
257 return streamErrorf(codes.Internal, "transport: malformed grpc-status-details-bin: %v", err) 320 return status.Errorf(codes.Internal, "transport: malformed grpc-status-details-bin: %v", err)
258 } 321 }
259 s := &spb.Status{} 322 s := &spb.Status{}
260 if err := proto.Unmarshal(v, s); err != nil { 323 if err := proto.Unmarshal(v, s); err != nil {
261 return streamErrorf(codes.Internal, "transport: malformed grpc-status-details-bin: %v", err) 324 return status.Errorf(codes.Internal, "transport: malformed grpc-status-details-bin: %v", err)
262 } 325 }
263 d.statusGen = status.FromProto(s) 326 d.statusGen = status.FromProto(s)
264 case "grpc-timeout": 327 case "grpc-timeout":
265 d.timeoutSet = true 328 d.timeoutSet = true
266 var err error 329 var err error
267 if d.timeout, err = decodeTimeout(f.Value); err != nil { 330 if d.timeout, err = decodeTimeout(f.Value); err != nil {
268 return streamErrorf(codes.Internal, "transport: malformed time-out: %v", err) 331 return status.Errorf(codes.Internal, "transport: malformed time-out: %v", err)
269 } 332 }
270 case ":path": 333 case ":path":
271 d.method = f.Value 334 d.method = f.Value
272 case ":status": 335 case ":status":
273 code, err := strconv.Atoi(f.Value) 336 code, err := strconv.Atoi(f.Value)
274 if err != nil { 337 if err != nil {
275 return streamErrorf(codes.Internal, "transport: malformed http-status: %v", err) 338 return status.Errorf(codes.Internal, "transport: malformed http-status: %v", err)
276 } 339 }
277 d.httpStatus = &code 340 d.httpStatus = &code
341 case "grpc-tags-bin":
342 v, err := decodeBinHeader(f.Value)
343 if err != nil {
344 return status.Errorf(codes.Internal, "transport: malformed grpc-tags-bin: %v", err)
345 }
346 d.statsTags = v
347 d.addMetadata(f.Name, string(v))
348 case "grpc-trace-bin":
349 v, err := decodeBinHeader(f.Value)
350 if err != nil {
351 return status.Errorf(codes.Internal, "transport: malformed grpc-trace-bin: %v", err)
352 }
353 d.statsTrace = v
354 d.addMetadata(f.Name, string(v))
278 default: 355 default:
279 if !isReservedHeader(f.Name) || isWhitelistedPseudoHeader(f.Name) { 356 if isReservedHeader(f.Name) && !isWhitelistedHeader(f.Name) {
280 if d.mdata == nil { 357 break
281 d.mdata = make(map[string][]string) 358 }
282 } 359 v, err := decodeMetadataHeader(f.Name, f.Value)
283 v, err := decodeMetadataHeader(f.Name, f.Value) 360 if err != nil {
284 if err != nil { 361 errorf("Failed to decode metadata header (%q, %q): %v", f.Name, f.Value, err)
285 errorf("Failed to decode metadata header (%q, %q): %v", f.Name, f.Value, err) 362 return nil
286 return nil
287 }
288 d.mdata[f.Name] = append(d.mdata[f.Name], v)
289 } 363 }
364 d.addMetadata(f.Name, v)
290 } 365 }
291 return nil 366 return nil
292} 367}
@@ -361,6 +436,10 @@ func decodeTimeout(s string) (time.Duration, error) {
361 if size < 2 { 436 if size < 2 {
362 return 0, fmt.Errorf("transport: timeout string is too short: %q", s) 437 return 0, fmt.Errorf("transport: timeout string is too short: %q", s)
363 } 438 }
439 if size > 9 {
440 // Spec allows for 8 digits plus the unit.
441 return 0, fmt.Errorf("transport: timeout string is too long: %q", s)
442 }
364 unit := timeoutUnit(s[size-1]) 443 unit := timeoutUnit(s[size-1])
365 d, ok := timeoutUnitToDuration(unit) 444 d, ok := timeoutUnitToDuration(unit)
366 if !ok { 445 if !ok {
@@ -370,21 +449,27 @@ func decodeTimeout(s string) (time.Duration, error) {
370 if err != nil { 449 if err != nil {
371 return 0, err 450 return 0, err
372 } 451 }
452 const maxHours = math.MaxInt64 / int64(time.Hour)
453 if d == time.Hour && t > maxHours {
454 // This timeout would overflow math.MaxInt64; clamp it.
455 return time.Duration(math.MaxInt64), nil
456 }
373 return d * time.Duration(t), nil 457 return d * time.Duration(t), nil
374} 458}
375 459
376const ( 460const (
377 spaceByte = ' ' 461 spaceByte = ' '
378 tildaByte = '~' 462 tildeByte = '~'
379 percentByte = '%' 463 percentByte = '%'
380) 464)
381 465
382// encodeGrpcMessage is used to encode status code in header field 466// encodeGrpcMessage is used to encode status code in header field
383// "grpc-message". 467// "grpc-message". It does percent encoding and also replaces invalid utf-8
384// It checks to see if each individual byte in msg is an 468// characters with Unicode replacement character.
385// allowable byte, and then either percent encoding or passing it through. 469//
386// When percent encoding, the byte is converted into hexadecimal notation 470// It checks to see if each individual byte in msg is an allowable byte, and
387// with a '%' prepended. 471// then either percent encoding or passing it through. When percent encoding,
472// the byte is converted into hexadecimal notation with a '%' prepended.
388func encodeGrpcMessage(msg string) string { 473func encodeGrpcMessage(msg string) string {
389 if msg == "" { 474 if msg == "" {
390 return "" 475 return ""
@@ -392,7 +477,7 @@ func encodeGrpcMessage(msg string) string {
392 lenMsg := len(msg) 477 lenMsg := len(msg)
393 for i := 0; i < lenMsg; i++ { 478 for i := 0; i < lenMsg; i++ {
394 c := msg[i] 479 c := msg[i]
395 if !(c >= spaceByte && c < tildaByte && c != percentByte) { 480 if !(c >= spaceByte && c <= tildeByte && c != percentByte) {
396 return encodeGrpcMessageUnchecked(msg) 481 return encodeGrpcMessageUnchecked(msg)
397 } 482 }
398 } 483 }
@@ -401,14 +486,26 @@ func encodeGrpcMessage(msg string) string {
401 486
402func encodeGrpcMessageUnchecked(msg string) string { 487func encodeGrpcMessageUnchecked(msg string) string {
403 var buf bytes.Buffer 488 var buf bytes.Buffer
404 lenMsg := len(msg) 489 for len(msg) > 0 {
405 for i := 0; i < lenMsg; i++ { 490 r, size := utf8.DecodeRuneInString(msg)
406 c := msg[i] 491 for _, b := range []byte(string(r)) {
407 if c >= spaceByte && c < tildaByte && c != percentByte { 492 if size > 1 {
408 buf.WriteByte(c) 493 // If size > 1, r is not ascii. Always do percent encoding.
409 } else { 494 buf.WriteString(fmt.Sprintf("%%%02X", b))
410 buf.WriteString(fmt.Sprintf("%%%02X", c)) 495 continue
496 }
497
498 // The for loop is necessary even if size == 1. r could be
499 // utf8.RuneError.
500 //
501 // fmt.Sprintf("%%%02X", utf8.RuneError) gives "%FFFD".
502 if b >= spaceByte && b <= tildeByte && b != percentByte {
503 buf.WriteByte(b)
504 } else {
505 buf.WriteString(fmt.Sprintf("%%%02X", b))
506 }
411 } 507 }
508 msg = msg[size:]
412 } 509 }
413 return buf.String() 510 return buf.String()
414} 511}
@@ -447,151 +544,80 @@ func decodeGrpcMessageUnchecked(msg string) string {
447 return buf.String() 544 return buf.String()
448} 545}
449 546
450type framer struct { 547type bufWriter struct {
451 numWriters int32 548 buf []byte
452 reader io.Reader 549 offset int
453 writer *bufio.Writer 550 batchSize int
454 fr *http2.Framer 551 conn net.Conn
455} 552 err error
456
457func newFramer(conn net.Conn) *framer {
458 f := &framer{
459 reader: bufio.NewReaderSize(conn, http2IOBufSize),
460 writer: bufio.NewWriterSize(conn, http2IOBufSize),
461 }
462 f.fr = http2.NewFramer(f.writer, f.reader)
463 // Opt-in to Frame reuse API on framer to reduce garbage.
464 // Frames aren't safe to read from after a subsequent call to ReadFrame.
465 f.fr.SetReuseFrames()
466 f.fr.ReadMetaHeaders = hpack.NewDecoder(http2InitHeaderTableSize, nil)
467 return f
468}
469 553
470func (f *framer) adjustNumWriters(i int32) int32 { 554 onFlush func()
471 return atomic.AddInt32(&f.numWriters, i)
472} 555}
473 556
474// The following writeXXX functions can only be called when the caller gets 557func newBufWriter(conn net.Conn, batchSize int) *bufWriter {
475// unblocked from writableChan channel (i.e., owns the privilege to write). 558 return &bufWriter{
476 559 buf: make([]byte, batchSize*2),
477func (f *framer) writeContinuation(forceFlush bool, streamID uint32, endHeaders bool, headerBlockFragment []byte) error { 560 batchSize: batchSize,
478 if err := f.fr.WriteContinuation(streamID, endHeaders, headerBlockFragment); err != nil { 561 conn: conn,
479 return err
480 } 562 }
481 if forceFlush {
482 return f.writer.Flush()
483 }
484 return nil
485} 563}
486 564
487func (f *framer) writeData(forceFlush bool, streamID uint32, endStream bool, data []byte) error { 565func (w *bufWriter) Write(b []byte) (n int, err error) {
488 if err := f.fr.WriteData(streamID, endStream, data); err != nil { 566 if w.err != nil {
489 return err 567 return 0, w.err
490 } 568 }
491 if forceFlush { 569 if w.batchSize == 0 { // Buffer has been disabled.
492 return f.writer.Flush() 570 return w.conn.Write(b)
493 } 571 }
494 return nil 572 for len(b) > 0 {
495} 573 nn := copy(w.buf[w.offset:], b)
496 574 b = b[nn:]
497func (f *framer) writeGoAway(forceFlush bool, maxStreamID uint32, code http2.ErrCode, debugData []byte) error { 575 w.offset += nn
498 if err := f.fr.WriteGoAway(maxStreamID, code, debugData); err != nil { 576 n += nn
499 return err 577 if w.offset >= w.batchSize {
500 } 578 err = w.Flush()
501 if forceFlush { 579 }
502 return f.writer.Flush()
503 }
504 return nil
505}
506
507func (f *framer) writeHeaders(forceFlush bool, p http2.HeadersFrameParam) error {
508 if err := f.fr.WriteHeaders(p); err != nil {
509 return err
510 }
511 if forceFlush {
512 return f.writer.Flush()
513 }
514 return nil
515}
516
517func (f *framer) writePing(forceFlush, ack bool, data [8]byte) error {
518 if err := f.fr.WritePing(ack, data); err != nil {
519 return err
520 }
521 if forceFlush {
522 return f.writer.Flush()
523 }
524 return nil
525}
526
527func (f *framer) writePriority(forceFlush bool, streamID uint32, p http2.PriorityParam) error {
528 if err := f.fr.WritePriority(streamID, p); err != nil {
529 return err
530 }
531 if forceFlush {
532 return f.writer.Flush()
533 } 580 }
534 return nil 581 return n, err
535} 582}
536 583
537func (f *framer) writePushPromise(forceFlush bool, p http2.PushPromiseParam) error { 584func (w *bufWriter) Flush() error {
538 if err := f.fr.WritePushPromise(p); err != nil { 585 if w.err != nil {
539 return err 586 return w.err
540 }
541 if forceFlush {
542 return f.writer.Flush()
543 } 587 }
544 return nil 588 if w.offset == 0 {
545} 589 return nil
546
547func (f *framer) writeRSTStream(forceFlush bool, streamID uint32, code http2.ErrCode) error {
548 if err := f.fr.WriteRSTStream(streamID, code); err != nil {
549 return err
550 } 590 }
551 if forceFlush { 591 if w.onFlush != nil {
552 return f.writer.Flush() 592 w.onFlush()
553 } 593 }
554 return nil 594 _, w.err = w.conn.Write(w.buf[:w.offset])
595 w.offset = 0
596 return w.err
555} 597}
556 598
557func (f *framer) writeSettings(forceFlush bool, settings ...http2.Setting) error { 599type framer struct {
558 if err := f.fr.WriteSettings(settings...); err != nil { 600 writer *bufWriter
559 return err 601 fr *http2.Framer
560 }
561 if forceFlush {
562 return f.writer.Flush()
563 }
564 return nil
565} 602}
566 603
567func (f *framer) writeSettingsAck(forceFlush bool) error { 604func newFramer(conn net.Conn, writeBufferSize, readBufferSize int, maxHeaderListSize uint32) *framer {
568 if err := f.fr.WriteSettingsAck(); err != nil { 605 if writeBufferSize < 0 {
569 return err 606 writeBufferSize = 0
570 } 607 }
571 if forceFlush { 608 var r io.Reader = conn
572 return f.writer.Flush() 609 if readBufferSize > 0 {
610 r = bufio.NewReaderSize(r, readBufferSize)
573 } 611 }
574 return nil 612 w := newBufWriter(conn, writeBufferSize)
575} 613 f := &framer{
576 614 writer: w,
577func (f *framer) writeWindowUpdate(forceFlush bool, streamID, incr uint32) error { 615 fr: http2.NewFramer(w, r),
578 if err := f.fr.WriteWindowUpdate(streamID, incr); err != nil {
579 return err
580 }
581 if forceFlush {
582 return f.writer.Flush()
583 } 616 }
584 return nil 617 // Opt-in to Frame reuse API on framer to reduce garbage.
585} 618 // Frames aren't safe to read from after a subsequent call to ReadFrame.
586 619 f.fr.SetReuseFrames()
587func (f *framer) flushWrite() error { 620 f.fr.MaxHeaderListSize = maxHeaderListSize
588 return f.writer.Flush() 621 f.fr.ReadMetaHeaders = hpack.NewDecoder(http2InitHeaderTableSize, nil)
589} 622 return f
590
591func (f *framer) readFrame() (http2.Frame, error) {
592 return f.fr.ReadFrame()
593}
594
595func (f *framer) errorDetail() error {
596 return f.fr.ErrorDetail()
597} 623}
diff --git a/vendor/google.golang.org/grpc/transport/log.go b/vendor/google.golang.org/grpc/internal/transport/log.go
index ac8e358..879df80 100644
--- a/vendor/google.golang.org/grpc/transport/log.go
+++ b/vendor/google.golang.org/grpc/internal/transport/log.go
@@ -42,9 +42,3 @@ func errorf(format string, args ...interface{}) {
42 grpclog.Errorf(format, args...) 42 grpclog.Errorf(format, args...)
43 } 43 }
44} 44}
45
46func fatalf(format string, args ...interface{}) {
47 if grpclog.V(logLevel) {
48 grpclog.Fatalf(format, args...)
49 }
50}
diff --git a/vendor/google.golang.org/grpc/transport/transport.go b/vendor/google.golang.org/grpc/internal/transport/transport.go
index ec0fe67..2580aa7 100644
--- a/vendor/google.golang.org/grpc/transport/transport.go
+++ b/vendor/google.golang.org/grpc/internal/transport/transport.go
@@ -17,17 +17,19 @@
17 */ 17 */
18 18
19// Package transport defines and implements message oriented communication 19// Package transport defines and implements message oriented communication
20// channel to complete various transactions (e.g., an RPC). 20// channel to complete various transactions (e.g., an RPC). It is meant for
21package transport // import "google.golang.org/grpc/transport" 21// grpc-internal usage and is not intended to be imported directly by users.
22package transport
22 23
23import ( 24import (
25 "context"
26 "errors"
24 "fmt" 27 "fmt"
25 "io" 28 "io"
26 "net" 29 "net"
27 "sync" 30 "sync"
31 "sync/atomic"
28 32
29 "golang.org/x/net/context"
30 "golang.org/x/net/http2"
31 "google.golang.org/grpc/codes" 33 "google.golang.org/grpc/codes"
32 "google.golang.org/grpc/credentials" 34 "google.golang.org/grpc/credentials"
33 "google.golang.org/grpc/keepalive" 35 "google.golang.org/grpc/keepalive"
@@ -56,6 +58,7 @@ type recvBuffer struct {
56 c chan recvMsg 58 c chan recvMsg
57 mu sync.Mutex 59 mu sync.Mutex
58 backlog []recvMsg 60 backlog []recvMsg
61 err error
59} 62}
60 63
61func newRecvBuffer() *recvBuffer { 64func newRecvBuffer() *recvBuffer {
@@ -67,20 +70,27 @@ func newRecvBuffer() *recvBuffer {
67 70
68func (b *recvBuffer) put(r recvMsg) { 71func (b *recvBuffer) put(r recvMsg) {
69 b.mu.Lock() 72 b.mu.Lock()
70 defer b.mu.Unlock() 73 if b.err != nil {
74 b.mu.Unlock()
75 // An error had occurred earlier, don't accept more
76 // data or errors.
77 return
78 }
79 b.err = r.err
71 if len(b.backlog) == 0 { 80 if len(b.backlog) == 0 {
72 select { 81 select {
73 case b.c <- r: 82 case b.c <- r:
83 b.mu.Unlock()
74 return 84 return
75 default: 85 default:
76 } 86 }
77 } 87 }
78 b.backlog = append(b.backlog, r) 88 b.backlog = append(b.backlog, r)
89 b.mu.Unlock()
79} 90}
80 91
81func (b *recvBuffer) load() { 92func (b *recvBuffer) load() {
82 b.mu.Lock() 93 b.mu.Lock()
83 defer b.mu.Unlock()
84 if len(b.backlog) > 0 { 94 if len(b.backlog) > 0 {
85 select { 95 select {
86 case b.c <- b.backlog[0]: 96 case b.c <- b.backlog[0]:
@@ -89,6 +99,7 @@ func (b *recvBuffer) load() {
89 default: 99 default:
90 } 100 }
91 } 101 }
102 b.mu.Unlock()
92} 103}
93 104
94// get returns the channel that receives a recvMsg in the buffer. 105// get returns the channel that receives a recvMsg in the buffer.
@@ -102,11 +113,12 @@ func (b *recvBuffer) get() <-chan recvMsg {
102// recvBufferReader implements io.Reader interface to read the data from 113// recvBufferReader implements io.Reader interface to read the data from
103// recvBuffer. 114// recvBuffer.
104type recvBufferReader struct { 115type recvBufferReader struct {
105 ctx context.Context 116 closeStream func(error) // Closes the client transport stream with the given error and nil trailer metadata.
106 goAway chan struct{} 117 ctx context.Context
107 recv *recvBuffer 118 ctxDone <-chan struct{} // cache of ctx.Done() (for performance).
108 last []byte // Stores the remaining data in the previous calls. 119 recv *recvBuffer
109 err error 120 last []byte // Stores the remaining data in the previous calls.
121 err error
110} 122}
111 123
112// Read reads the next len(p) bytes from last. If last is drained, it tries to 124// Read reads the next len(p) bytes from last. If last is drained, it tries to
@@ -116,87 +128,54 @@ func (r *recvBufferReader) Read(p []byte) (n int, err error) {
116 if r.err != nil { 128 if r.err != nil {
117 return 0, r.err 129 return 0, r.err
118 } 130 }
119 n, r.err = r.read(p)
120 return n, r.err
121}
122
123func (r *recvBufferReader) read(p []byte) (n int, err error) {
124 if r.last != nil && len(r.last) > 0 { 131 if r.last != nil && len(r.last) > 0 {
125 // Read remaining data left in last call. 132 // Read remaining data left in last call.
126 copied := copy(p, r.last) 133 copied := copy(p, r.last)
127 r.last = r.last[copied:] 134 r.last = r.last[copied:]
128 return copied, nil 135 return copied, nil
129 } 136 }
137 if r.closeStream != nil {
138 n, r.err = r.readClient(p)
139 } else {
140 n, r.err = r.read(p)
141 }
142 return n, r.err
143}
144
145func (r *recvBufferReader) read(p []byte) (n int, err error) {
130 select { 146 select {
131 case <-r.ctx.Done(): 147 case <-r.ctxDone:
132 return 0, ContextErr(r.ctx.Err()) 148 return 0, ContextErr(r.ctx.Err())
133 case <-r.goAway:
134 return 0, ErrStreamDrain
135 case m := <-r.recv.get(): 149 case m := <-r.recv.get():
136 r.recv.load() 150 return r.readAdditional(m, p)
137 if m.err != nil {
138 return 0, m.err
139 }
140 copied := copy(p, m.data)
141 r.last = m.data[copied:]
142 return copied, nil
143 } 151 }
144} 152}
145 153
146// All items in an out of a controlBuffer should be the same type. 154func (r *recvBufferReader) readClient(p []byte) (n int, err error) {
147type item interface { 155 // If the context is canceled, then closes the stream with nil metadata.
148 item() 156 // closeStream writes its error parameter to r.recv as a recvMsg.
149} 157 // r.readAdditional acts on that message and returns the necessary error.
150 158 select {
151// controlBuffer is an unbounded channel of item. 159 case <-r.ctxDone:
152type controlBuffer struct { 160 r.closeStream(ContextErr(r.ctx.Err()))
153 c chan item 161 m := <-r.recv.get()
154 mu sync.Mutex 162 return r.readAdditional(m, p)
155 backlog []item 163 case m := <-r.recv.get():
156} 164 return r.readAdditional(m, p)
157
158func newControlBuffer() *controlBuffer {
159 b := &controlBuffer{
160 c: make(chan item, 1),
161 } 165 }
162 return b
163} 166}
164 167
165func (b *controlBuffer) put(r item) { 168func (r *recvBufferReader) readAdditional(m recvMsg, p []byte) (n int, err error) {
166 b.mu.Lock() 169 r.recv.load()
167 defer b.mu.Unlock() 170 if m.err != nil {
168 if len(b.backlog) == 0 { 171 return 0, m.err
169 select {
170 case b.c <- r:
171 return
172 default:
173 }
174 } 172 }
175 b.backlog = append(b.backlog, r) 173 copied := copy(p, m.data)
174 r.last = m.data[copied:]
175 return copied, nil
176} 176}
177 177
178func (b *controlBuffer) load() { 178type streamState uint32
179 b.mu.Lock()
180 defer b.mu.Unlock()
181 if len(b.backlog) > 0 {
182 select {
183 case b.c <- b.backlog[0]:
184 b.backlog[0] = nil
185 b.backlog = b.backlog[1:]
186 default:
187 }
188 }
189}
190
191// get returns the channel that receives an item in the buffer.
192//
193// Upon receipt of an item, the caller should call load to send another
194// item onto the channel if there is any.
195func (b *controlBuffer) get() <-chan item {
196 return b.c
197}
198
199type streamState uint8
200 179
201const ( 180const (
202 streamActive streamState = iota 181 streamActive streamState = iota
@@ -207,65 +186,98 @@ const (
207 186
208// Stream represents an RPC in the transport layer. 187// Stream represents an RPC in the transport layer.
209type Stream struct { 188type Stream struct {
210 id uint32 189 id uint32
211 // nil for client side Stream. 190 st ServerTransport // nil for client side Stream
212 st ServerTransport 191 ctx context.Context // the associated context of the stream
213 // ctx is the associated context of the stream. 192 cancel context.CancelFunc // always nil for client side Stream
214 ctx context.Context 193 done chan struct{} // closed at the end of stream to unblock writers. On the client side.
215 // cancel is always nil for client side Stream. 194 ctxDone <-chan struct{} // same as done chan but for server side. Cache of ctx.Done() (for performance)
216 cancel context.CancelFunc 195 method string // the associated RPC method of the stream
217 // done is closed when the final status arrives.
218 done chan struct{}
219 // goAway is closed when the server sent GoAways signal before this stream was initiated.
220 goAway chan struct{}
221 // method records the associated RPC method of the stream.
222 method string
223 recvCompress string 196 recvCompress string
224 sendCompress string 197 sendCompress string
225 buf *recvBuffer 198 buf *recvBuffer
226 trReader io.Reader 199 trReader io.Reader
227 fc *inFlow 200 fc *inFlow
228 recvQuota uint32 201 wq *writeQuota
229
230 // TODO: Remote this unused variable.
231 // The accumulated inbound quota pending for window update.
232 updateQuota uint32
233 202
234 // Callback to state application's intentions to read data. This 203 // Callback to state application's intentions to read data. This
235 // is used to adjust flow control, if need be. 204 // is used to adjust flow control, if needed.
236 requestRead func(int) 205 requestRead func(int)
237 206
238 sendQuotaPool *quotaPool 207 headerChan chan struct{} // closed to indicate the end of header metadata.
239 // Close headerChan to indicate the end of reception of header metadata. 208 headerDone uint32 // set when headerChan is closed. Used to avoid closing headerChan multiple times.
240 headerChan chan struct{} 209
241 // header caches the received header metadata. 210 // hdrMu protects header and trailer metadata on the server-side.
242 header metadata.MD 211 hdrMu sync.Mutex
243 // The key-value map of trailer metadata. 212 // On client side, header keeps the received header metadata.
244 trailer metadata.MD 213 //
245 214 // On server side, header keeps the header set by SetHeader(). The complete
246 mu sync.RWMutex // guard the following 215 // header will merged into this after t.WriteHeader() is called.
247 // headerOK becomes true from the first header is about to send. 216 header metadata.MD
248 headerOk bool 217 trailer metadata.MD // the key-value map of trailer metadata.
249 state streamState 218
250 // true iff headerChan is closed. Used to avoid closing headerChan 219 noHeaders bool // set if the client never received headers (set only after the stream is done).
251 // multiple times. 220
252 headerDone bool 221 // On the server-side, headerSent is atomically set to 1 when the headers are sent out.
253 // the status error received from the server. 222 headerSent uint32
223
224 state streamState
225
226 // On client-side it is the status error received from the server.
227 // On server-side it is unused.
254 status *status.Status 228 status *status.Status
255 // rstStream indicates whether a RST_STREAM frame needs to be sent 229
256 // to the server to signify that this stream is closing. 230 bytesReceived uint32 // indicates whether any bytes have been received on this stream
257 rstStream bool 231 unprocessed uint32 // set if the server sends a refused stream or GOAWAY including this stream
258 // rstError is the error that needs to be sent along with the RST_STREAM frame. 232
259 rstError http2.ErrCode 233 // contentSubtype is the content-subtype for requests.
260 // bytesSent and bytesReceived indicates whether any bytes have been sent or 234 // this must be lowercase or the behavior is undefined.
261 // received on this stream. 235 contentSubtype string
262 bytesSent bool 236}
263 bytesReceived bool 237
238// isHeaderSent is only valid on the server-side.
239func (s *Stream) isHeaderSent() bool {
240 return atomic.LoadUint32(&s.headerSent) == 1
241}
242
243// updateHeaderSent updates headerSent and returns true
244// if it was alreay set. It is valid only on server-side.
245func (s *Stream) updateHeaderSent() bool {
246 return atomic.SwapUint32(&s.headerSent, 1) == 1
247}
248
249func (s *Stream) swapState(st streamState) streamState {
250 return streamState(atomic.SwapUint32((*uint32)(&s.state), uint32(st)))
251}
252
253func (s *Stream) compareAndSwapState(oldState, newState streamState) bool {
254 return atomic.CompareAndSwapUint32((*uint32)(&s.state), uint32(oldState), uint32(newState))
255}
256
257func (s *Stream) getState() streamState {
258 return streamState(atomic.LoadUint32((*uint32)(&s.state)))
259}
260
261func (s *Stream) waitOnHeader() error {
262 if s.headerChan == nil {
263 // On the server headerChan is always nil since a stream originates
264 // only after having received headers.
265 return nil
266 }
267 select {
268 case <-s.ctx.Done():
269 return ContextErr(s.ctx.Err())
270 case <-s.headerChan:
271 return nil
272 }
264} 273}
265 274
266// RecvCompress returns the compression algorithm applied to the inbound 275// RecvCompress returns the compression algorithm applied to the inbound
267// message. It is empty string if there is no compression applied. 276// message. It is empty string if there is no compression applied.
268func (s *Stream) RecvCompress() string { 277func (s *Stream) RecvCompress() string {
278 if err := s.waitOnHeader(); err != nil {
279 return ""
280 }
269 return s.recvCompress 281 return s.recvCompress
270} 282}
271 283
@@ -274,53 +286,68 @@ func (s *Stream) SetSendCompress(str string) {
274 s.sendCompress = str 286 s.sendCompress = str
275} 287}
276 288
277// Done returns a chanel which is closed when it receives the final status 289// Done returns a channel which is closed when it receives the final status
278// from the server. 290// from the server.
279func (s *Stream) Done() <-chan struct{} { 291func (s *Stream) Done() <-chan struct{} {
280 return s.done 292 return s.done
281} 293}
282 294
283// GoAway returns a channel which is closed when the server sent GoAways signal 295// Header returns the header metadata of the stream.
284// before this stream was initiated. 296//
285func (s *Stream) GoAway() <-chan struct{} { 297// On client side, it acquires the key-value pairs of header metadata once it is
286 return s.goAway 298// available. It blocks until i) the metadata is ready or ii) there is no header
287} 299// metadata or iii) the stream is canceled/expired.
288 300//
289// Header acquires the key-value pairs of header metadata once it 301// On server side, it returns the out header after t.WriteHeader is called.
290// is available. It blocks until i) the metadata is ready or ii) there is no
291// header metadata or iii) the stream is canceled/expired.
292func (s *Stream) Header() (metadata.MD, error) { 302func (s *Stream) Header() (metadata.MD, error) {
293 var err error 303 if s.headerChan == nil && s.header != nil {
294 select { 304 // On server side, return the header in stream. It will be the out
295 case <-s.ctx.Done(): 305 // header after t.WriteHeader is called.
296 err = ContextErr(s.ctx.Err())
297 case <-s.goAway:
298 err = ErrStreamDrain
299 case <-s.headerChan:
300 return s.header.Copy(), nil 306 return s.header.Copy(), nil
301 } 307 }
308 err := s.waitOnHeader()
302 // Even if the stream is closed, header is returned if available. 309 // Even if the stream is closed, header is returned if available.
303 select { 310 select {
304 case <-s.headerChan: 311 case <-s.headerChan:
312 if s.header == nil {
313 return nil, nil
314 }
305 return s.header.Copy(), nil 315 return s.header.Copy(), nil
306 default: 316 default:
307 } 317 }
308 return nil, err 318 return nil, err
309} 319}
310 320
321// TrailersOnly blocks until a header or trailers-only frame is received and
322// then returns true if the stream was trailers-only. If the stream ends
323// before headers are received, returns true, nil. If a context error happens
324// first, returns it as a status error. Client-side only.
325func (s *Stream) TrailersOnly() (bool, error) {
326 err := s.waitOnHeader()
327 if err != nil {
328 return false, err
329 }
330 // if !headerDone, some other connection error occurred.
331 return s.noHeaders && atomic.LoadUint32(&s.headerDone) == 1, nil
332}
333
311// Trailer returns the cached trailer metedata. Note that if it is not called 334// Trailer returns the cached trailer metedata. Note that if it is not called
312// after the entire stream is done, it could return an empty MD. Client 335// after the entire stream is done, it could return an empty MD. Client
313// side only. 336// side only.
337// It can be safely read only after stream has ended that is either read
338// or write have returned io.EOF.
314func (s *Stream) Trailer() metadata.MD { 339func (s *Stream) Trailer() metadata.MD {
315 s.mu.RLock() 340 c := s.trailer.Copy()
316 defer s.mu.RUnlock() 341 return c
317 return s.trailer.Copy()
318} 342}
319 343
320// ServerTransport returns the underlying ServerTransport for the stream. 344// ContentSubtype returns the content-subtype for a request. For example, a
321// The client side stream always returns nil. 345// content-subtype of "proto" will result in a content-type of
322func (s *Stream) ServerTransport() ServerTransport { 346// "application/grpc+proto". This will always be lowercase. See
323 return s.st 347// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
348// more details.
349func (s *Stream) ContentSubtype() string {
350 return s.contentSubtype
324} 351}
325 352
326// Context returns the context of the stream. 353// Context returns the context of the stream.
@@ -334,34 +361,48 @@ func (s *Stream) Method() string {
334} 361}
335 362
336// Status returns the status received from the server. 363// Status returns the status received from the server.
364// Status can be read safely only after the stream has ended,
365// that is, after Done() is closed.
337func (s *Stream) Status() *status.Status { 366func (s *Stream) Status() *status.Status {
338 return s.status 367 return s.status
339} 368}
340 369
341// SetHeader sets the header metadata. This can be called multiple times. 370// SetHeader sets the header metadata. This can be called multiple times.
342// Server side only. 371// Server side only.
372// This should not be called in parallel to other data writes.
343func (s *Stream) SetHeader(md metadata.MD) error { 373func (s *Stream) SetHeader(md metadata.MD) error {
344 s.mu.Lock()
345 defer s.mu.Unlock()
346 if s.headerOk || s.state == streamDone {
347 return ErrIllegalHeaderWrite
348 }
349 if md.Len() == 0 { 374 if md.Len() == 0 {
350 return nil 375 return nil
351 } 376 }
377 if s.isHeaderSent() || s.getState() == streamDone {
378 return ErrIllegalHeaderWrite
379 }
380 s.hdrMu.Lock()
352 s.header = metadata.Join(s.header, md) 381 s.header = metadata.Join(s.header, md)
382 s.hdrMu.Unlock()
353 return nil 383 return nil
354} 384}
355 385
386// SendHeader sends the given header metadata. The given metadata is
387// combined with any metadata set by previous calls to SetHeader and
388// then written to the transport stream.
389func (s *Stream) SendHeader(md metadata.MD) error {
390 return s.st.WriteHeader(s, md)
391}
392
356// SetTrailer sets the trailer metadata which will be sent with the RPC status 393// SetTrailer sets the trailer metadata which will be sent with the RPC status
357// by the server. This can be called multiple times. Server side only. 394// by the server. This can be called multiple times. Server side only.
395// This should not be called parallel to other data writes.
358func (s *Stream) SetTrailer(md metadata.MD) error { 396func (s *Stream) SetTrailer(md metadata.MD) error {
359 if md.Len() == 0 { 397 if md.Len() == 0 {
360 return nil 398 return nil
361 } 399 }
362 s.mu.Lock() 400 if s.getState() == streamDone {
363 defer s.mu.Unlock() 401 return ErrIllegalHeaderWrite
402 }
403 s.hdrMu.Lock()
364 s.trailer = metadata.Join(s.trailer, md) 404 s.trailer = metadata.Join(s.trailer, md)
405 s.hdrMu.Unlock()
365 return nil 406 return nil
366} 407}
367 408
@@ -401,26 +442,15 @@ func (t *transportReader) Read(p []byte) (n int, err error) {
401 return 442 return
402} 443}
403 444
404// finish sets the stream's state and status, and closes the done channel.
405// s.mu must be held by the caller. st must always be non-nil.
406func (s *Stream) finish(st *status.Status) {
407 s.status = st
408 s.state = streamDone
409 close(s.done)
410}
411
412// BytesSent indicates whether any bytes have been sent on this stream.
413func (s *Stream) BytesSent() bool {
414 s.mu.Lock()
415 defer s.mu.Unlock()
416 return s.bytesSent
417}
418
419// BytesReceived indicates whether any bytes have been received on this stream. 445// BytesReceived indicates whether any bytes have been received on this stream.
420func (s *Stream) BytesReceived() bool { 446func (s *Stream) BytesReceived() bool {
421 s.mu.Lock() 447 return atomic.LoadUint32(&s.bytesReceived) == 1
422 defer s.mu.Unlock() 448}
423 return s.bytesReceived 449
450// Unprocessed indicates whether the server did not process this stream --
451// i.e. it sent a refused stream or GOAWAY including this stream ID.
452func (s *Stream) Unprocessed() bool {
453 return atomic.LoadUint32(&s.unprocessed) == 1
424} 454}
425 455
426// GoString is implemented by Stream so context.String() won't 456// GoString is implemented by Stream so context.String() won't
@@ -429,27 +459,11 @@ func (s *Stream) GoString() string {
429 return fmt.Sprintf("<stream: %p, %v>", s, s.method) 459 return fmt.Sprintf("<stream: %p, %v>", s, s.method)
430} 460}
431 461
432// The key to save transport.Stream in the context.
433type streamKey struct{}
434
435// newContextWithStream creates a new context from ctx and attaches stream
436// to it.
437func newContextWithStream(ctx context.Context, stream *Stream) context.Context {
438 return context.WithValue(ctx, streamKey{}, stream)
439}
440
441// StreamFromContext returns the stream saved in ctx.
442func StreamFromContext(ctx context.Context) (s *Stream, ok bool) {
443 s, ok = ctx.Value(streamKey{}).(*Stream)
444 return
445}
446
447// state of transport 462// state of transport
448type transportState int 463type transportState int
449 464
450const ( 465const (
451 reachable transportState = iota 466 reachable transportState = iota
452 unreachable
453 closing 467 closing
454 draining 468 draining
455) 469)
@@ -464,6 +478,10 @@ type ServerConfig struct {
464 KeepalivePolicy keepalive.EnforcementPolicy 478 KeepalivePolicy keepalive.EnforcementPolicy
465 InitialWindowSize int32 479 InitialWindowSize int32
466 InitialConnWindowSize int32 480 InitialConnWindowSize int32
481 WriteBufferSize int
482 ReadBufferSize int
483 ChannelzParentID int64
484 MaxHeaderListSize *uint32
467} 485}
468 486
469// NewServerTransport creates a ServerTransport with conn or non-nil error 487// NewServerTransport creates a ServerTransport with conn or non-nil error
@@ -476,37 +494,47 @@ func NewServerTransport(protocol string, conn net.Conn, config *ServerConfig) (S
476type ConnectOptions struct { 494type ConnectOptions struct {
477 // UserAgent is the application user agent. 495 // UserAgent is the application user agent.
478 UserAgent string 496 UserAgent string
479 // Authority is the :authority pseudo-header to use. This field has no effect if
480 // TransportCredentials is set.
481 Authority string
482 // Dialer specifies how to dial a network address. 497 // Dialer specifies how to dial a network address.
483 Dialer func(context.Context, string) (net.Conn, error) 498 Dialer func(context.Context, string) (net.Conn, error)
484 // FailOnNonTempDialError specifies if gRPC fails on non-temporary dial errors. 499 // FailOnNonTempDialError specifies if gRPC fails on non-temporary dial errors.
485 FailOnNonTempDialError bool 500 FailOnNonTempDialError bool
486 // PerRPCCredentials stores the PerRPCCredentials required to issue RPCs. 501 // PerRPCCredentials stores the PerRPCCredentials required to issue RPCs.
487 PerRPCCredentials []credentials.PerRPCCredentials 502 PerRPCCredentials []credentials.PerRPCCredentials
488 // TransportCredentials stores the Authenticator required to setup a client connection. 503 // TransportCredentials stores the Authenticator required to setup a client
504 // connection. Only one of TransportCredentials and CredsBundle is non-nil.
489 TransportCredentials credentials.TransportCredentials 505 TransportCredentials credentials.TransportCredentials
506 // CredsBundle is the credentials bundle to be used. Only one of
507 // TransportCredentials and CredsBundle is non-nil.
508 CredsBundle credentials.Bundle
490 // KeepaliveParams stores the keepalive parameters. 509 // KeepaliveParams stores the keepalive parameters.
491 KeepaliveParams keepalive.ClientParameters 510 KeepaliveParams keepalive.ClientParameters
492 // StatsHandler stores the handler for stats. 511 // StatsHandler stores the handler for stats.
493 StatsHandler stats.Handler 512 StatsHandler stats.Handler
494 // InitialWindowSize sets the intial window size for a stream. 513 // InitialWindowSize sets the initial window size for a stream.
495 InitialWindowSize int32 514 InitialWindowSize int32
496 // InitialConnWindowSize sets the intial window size for a connection. 515 // InitialConnWindowSize sets the initial window size for a connection.
497 InitialConnWindowSize int32 516 InitialConnWindowSize int32
517 // WriteBufferSize sets the size of write buffer which in turn determines how much data can be batched before it's written on the wire.
518 WriteBufferSize int
519 // ReadBufferSize sets the size of read buffer, which in turn determines how much data can be read at most for one read syscall.
520 ReadBufferSize int
521 // ChannelzParentID sets the addrConn id which initiate the creation of this client transport.
522 ChannelzParentID int64
523 // MaxHeaderListSize sets the max (uncompressed) size of header list that is prepared to be received.
524 MaxHeaderListSize *uint32
498} 525}
499 526
500// TargetInfo contains the information of the target such as network address and metadata. 527// TargetInfo contains the information of the target such as network address and metadata.
501type TargetInfo struct { 528type TargetInfo struct {
502 Addr string 529 Addr string
503 Metadata interface{} 530 Metadata interface{}
531 Authority string
504} 532}
505 533
506// NewClientTransport establishes the transport with the required ConnectOptions 534// NewClientTransport establishes the transport with the required ConnectOptions
507// and returns it to the caller. 535// and returns it to the caller.
508func NewClientTransport(ctx context.Context, target TargetInfo, opts ConnectOptions) (ClientTransport, error) { 536func NewClientTransport(connectCtx, ctx context.Context, target TargetInfo, opts ConnectOptions, onPrefaceReceipt func(), onGoAway func(GoAwayReason), onClose func()) (ClientTransport, error) {
509 return newHTTP2Client(ctx, target, opts) 537 return newHTTP2Client(connectCtx, ctx, target, opts, onPrefaceReceipt, onGoAway, onClose)
510} 538}
511 539
512// Options provides additional hints and information for message 540// Options provides additional hints and information for message
@@ -515,11 +543,6 @@ type Options struct {
515 // Last indicates whether this write is the last piece for 543 // Last indicates whether this write is the last piece for
516 // this stream. 544 // this stream.
517 Last bool 545 Last bool
518
519 // Delay is a hint to the transport implementation for whether
520 // the data could be buffered for a batching write. The
521 // Transport implementation may ignore the hint.
522 Delay bool
523} 546}
524 547
525// CallHdr carries the information of a particular RPC. 548// CallHdr carries the information of a particular RPC.
@@ -530,10 +553,6 @@ type CallHdr struct {
530 // Method specifies the operation to perform. 553 // Method specifies the operation to perform.
531 Method string 554 Method string
532 555
533 // RecvCompress specifies the compression algorithm applied on
534 // inbound messages.
535 RecvCompress string
536
537 // SendCompress specifies the compression algorithm applied on 556 // SendCompress specifies the compression algorithm applied on
538 // outbound message. 557 // outbound message.
539 SendCompress string 558 SendCompress string
@@ -541,13 +560,15 @@ type CallHdr struct {
541 // Creds specifies credentials.PerRPCCredentials for a call. 560 // Creds specifies credentials.PerRPCCredentials for a call.
542 Creds credentials.PerRPCCredentials 561 Creds credentials.PerRPCCredentials
543 562
544 // Flush indicates whether a new stream command should be sent 563 // ContentSubtype specifies the content-subtype for a request. For example, a
545 // to the peer without waiting for the first data. This is 564 // content-subtype of "proto" will result in a content-type of
546 // only a hint. 565 // "application/grpc+proto". The value of ContentSubtype must be all
547 // If it's true, the transport may modify the flush decision 566 // lowercase, otherwise the behavior is undefined. See
548 // for performance purposes. 567 // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests
549 // If it's false, new stream will never be flushed. 568 // for more details.
550 Flush bool 569 ContentSubtype string
570
571 PreviousAttempts int // value of grpc-previous-rpc-attempts header to set
551} 572}
552 573
553// ClientTransport is the common interface for all gRPC client-side transport 574// ClientTransport is the common interface for all gRPC client-side transport
@@ -564,7 +585,7 @@ type ClientTransport interface {
564 585
565 // Write sends the data for the given stream. A nil stream indicates 586 // Write sends the data for the given stream. A nil stream indicates
566 // the write is to be performed on the transport as a whole. 587 // the write is to be performed on the transport as a whole.
567 Write(s *Stream, data []byte, opts *Options) error 588 Write(s *Stream, hdr []byte, data []byte, opts *Options) error
568 589
569 // NewStream creates a Stream for an RPC. 590 // NewStream creates a Stream for an RPC.
570 NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, error) 591 NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, error)
@@ -589,6 +610,12 @@ type ClientTransport interface {
589 610
590 // GetGoAwayReason returns the reason why GoAway frame was received. 611 // GetGoAwayReason returns the reason why GoAway frame was received.
591 GetGoAwayReason() GoAwayReason 612 GetGoAwayReason() GoAwayReason
613
614 // IncrMsgSent increments the number of message sent through this transport.
615 IncrMsgSent()
616
617 // IncrMsgRecv increments the number of message received through this transport.
618 IncrMsgRecv()
592} 619}
593 620
594// ServerTransport is the common interface for all gRPC server-side transport 621// ServerTransport is the common interface for all gRPC server-side transport
@@ -606,7 +633,7 @@ type ServerTransport interface {
606 633
607 // Write sends the data for the given stream. 634 // Write sends the data for the given stream.
608 // Write may not be called on all streams. 635 // Write may not be called on all streams.
609 Write(s *Stream, data []byte, opts *Options) error 636 Write(s *Stream, hdr []byte, data []byte, opts *Options) error
610 637
611 // WriteStatus sends the status of a stream to the client. WriteStatus is 638 // WriteStatus sends the status of a stream to the client. WriteStatus is
612 // the final call made on a stream and always occurs. 639 // the final call made on a stream and always occurs.
@@ -622,14 +649,12 @@ type ServerTransport interface {
622 649
623 // Drain notifies the client this ServerTransport stops accepting new RPCs. 650 // Drain notifies the client this ServerTransport stops accepting new RPCs.
624 Drain() 651 Drain()
625}
626 652
627// streamErrorf creates an StreamError with the specified error code and description. 653 // IncrMsgSent increments the number of message sent through this transport.
628func streamErrorf(c codes.Code, format string, a ...interface{}) StreamError { 654 IncrMsgSent()
629 return StreamError{ 655
630 Code: c, 656 // IncrMsgRecv increments the number of message received through this transport.
631 Desc: fmt.Sprintf(format, a...), 657 IncrMsgRecv()
632 }
633} 658}
634 659
635// connectionErrorf creates an ConnectionError with the specified error description. 660// connectionErrorf creates an ConnectionError with the specified error description.
@@ -671,60 +696,63 @@ func (e ConnectionError) Origin() error {
671var ( 696var (
672 // ErrConnClosing indicates that the transport is closing. 697 // ErrConnClosing indicates that the transport is closing.
673 ErrConnClosing = connectionErrorf(true, nil, "transport is closing") 698 ErrConnClosing = connectionErrorf(true, nil, "transport is closing")
674 // ErrStreamDrain indicates that the stream is rejected by the server because 699 // errStreamDrain indicates that the stream is rejected because the
675 // the server stops accepting new RPCs. 700 // connection is draining. This could be caused by goaway or balancer
676 ErrStreamDrain = streamErrorf(codes.Unavailable, "the server stops accepting new RPCs") 701 // removing the address.
702 errStreamDrain = status.Error(codes.Unavailable, "the connection is draining")
703 // errStreamDone is returned from write at the client side to indiacte application
704 // layer of an error.
705 errStreamDone = errors.New("the stream is done")
706 // StatusGoAway indicates that the server sent a GOAWAY that included this
707 // stream's ID in unprocessed RPCs.
708 statusGoAway = status.New(codes.Unavailable, "the stream is rejected because server is draining the connection")
677) 709)
678 710
679// TODO: See if we can replace StreamError with status package errors.
680
681// StreamError is an error that only affects one stream within a connection.
682type StreamError struct {
683 Code codes.Code
684 Desc string
685}
686
687func (e StreamError) Error() string {
688 return fmt.Sprintf("stream error: code = %s desc = %q", e.Code, e.Desc)
689}
690
691// wait blocks until it can receive from ctx.Done, closing, or proceed.
692// If it receives from ctx.Done, it returns 0, the StreamError for ctx.Err.
693// If it receives from done, it returns 0, io.EOF if ctx is not done; otherwise
694// it return the StreamError for ctx.Err.
695// If it receives from goAway, it returns 0, ErrStreamDrain.
696// If it receives from closing, it returns 0, ErrConnClosing.
697// If it receives from proceed, it returns the received integer, nil.
698func wait(ctx context.Context, done, goAway, closing <-chan struct{}, proceed <-chan int) (int, error) {
699 select {
700 case <-ctx.Done():
701 return 0, ContextErr(ctx.Err())
702 case <-done:
703 // User cancellation has precedence.
704 select {
705 case <-ctx.Done():
706 return 0, ContextErr(ctx.Err())
707 default:
708 }
709 return 0, io.EOF
710 case <-goAway:
711 return 0, ErrStreamDrain
712 case <-closing:
713 return 0, ErrConnClosing
714 case i := <-proceed:
715 return i, nil
716 }
717}
718
719// GoAwayReason contains the reason for the GoAway frame received. 711// GoAwayReason contains the reason for the GoAway frame received.
720type GoAwayReason uint8 712type GoAwayReason uint8
721 713
722const ( 714const (
723 // Invalid indicates that no GoAway frame is received. 715 // GoAwayInvalid indicates that no GoAway frame is received.
724 Invalid GoAwayReason = 0 716 GoAwayInvalid GoAwayReason = 0
725 // NoReason is the default value when GoAway frame is received. 717 // GoAwayNoReason is the default value when GoAway frame is received.
726 NoReason GoAwayReason = 1 718 GoAwayNoReason GoAwayReason = 1
727 // TooManyPings indicates that a GoAway frame with ErrCodeEnhanceYourCalm 719 // GoAwayTooManyPings indicates that a GoAway frame with
728 // was recieved and that the debug data said "too_many_pings". 720 // ErrCodeEnhanceYourCalm was received and that the debug data said
729 TooManyPings GoAwayReason = 2 721 // "too_many_pings".
722 GoAwayTooManyPings GoAwayReason = 2
730) 723)
724
725// channelzData is used to store channelz related data for http2Client and http2Server.
726// These fields cannot be embedded in the original structs (e.g. http2Client), since to do atomic
727// operation on int64 variable on 32-bit machine, user is responsible to enforce memory alignment.
728// Here, by grouping those int64 fields inside a struct, we are enforcing the alignment.
729type channelzData struct {
730 kpCount int64
731 // The number of streams that have started, including already finished ones.
732 streamsStarted int64
733 // Client side: The number of streams that have ended successfully by receiving
734 // EoS bit set frame from server.
735 // Server side: The number of streams that have ended successfully by sending
736 // frame with EoS bit set.
737 streamsSucceeded int64
738 streamsFailed int64
739 // lastStreamCreatedTime stores the timestamp that the last stream gets created. It is of int64 type
740 // instead of time.Time since it's more costly to atomically update time.Time variable than int64
741 // variable. The same goes for lastMsgSentTime and lastMsgRecvTime.
742 lastStreamCreatedTime int64
743 msgSent int64
744 msgRecv int64
745 lastMsgSentTime int64
746 lastMsgRecvTime int64
747}
748
749// ContextErr converts the error from context package into a status error.
750func ContextErr(err error) error {
751 switch err {
752 case context.DeadlineExceeded:
753 return status.Error(codes.DeadlineExceeded, err.Error())
754 case context.Canceled:
755 return status.Error(codes.Canceled, err.Error())
756 }
757 return status.Errorf(codes.Internal, "Unexpected error from context packet: %v", err)
758}
diff --git a/vendor/google.golang.org/grpc/keepalive/keepalive.go b/vendor/google.golang.org/grpc/keepalive/keepalive.go
index f8adc7e..899e72d 100644
--- a/vendor/google.golang.org/grpc/keepalive/keepalive.go
+++ b/vendor/google.golang.org/grpc/keepalive/keepalive.go
@@ -16,7 +16,8 @@
16 * 16 *
17 */ 17 */
18 18
19// Package keepalive defines configurable parameters for point-to-point healthcheck. 19// Package keepalive defines configurable parameters for point-to-point
20// healthcheck.
20package keepalive 21package keepalive
21 22
22import ( 23import (
@@ -24,42 +25,59 @@ import (
24) 25)
25 26
26// ClientParameters is used to set keepalive parameters on the client-side. 27// ClientParameters is used to set keepalive parameters on the client-side.
27// These configure how the client will actively probe to notice when a connection is broken 28// These configure how the client will actively probe to notice when a
28// and send pings so intermediaries will be aware of the liveness of the connection. 29// connection is broken and send pings so intermediaries will be aware of the
29// Make sure these parameters are set in coordination with the keepalive policy on the server, 30// liveness of the connection. Make sure these parameters are set in
30// as incompatible settings can result in closing of connection. 31// coordination with the keepalive policy on the server, as incompatible
32// settings can result in closing of connection.
31type ClientParameters struct { 33type ClientParameters struct {
32 // After a duration of this time if the client doesn't see any activity it pings the server to see if the transport is still alive. 34 // After a duration of this time if the client doesn't see any activity it
35 // pings the server to see if the transport is still alive.
33 Time time.Duration // The current default value is infinity. 36 Time time.Duration // The current default value is infinity.
34 // After having pinged for keepalive check, the client waits for a duration of Timeout and if no activity is seen even after that 37 // After having pinged for keepalive check, the client waits for a duration
35 // the connection is closed. 38 // of Timeout and if no activity is seen even after that the connection is
39 // closed.
36 Timeout time.Duration // The current default value is 20 seconds. 40 Timeout time.Duration // The current default value is 20 seconds.
37 // If true, client runs keepalive checks even with no active RPCs. 41 // If true, client sends keepalive pings even with no active RPCs. If false,
42 // when there are no active RPCs, Time and Timeout will be ignored and no
43 // keepalive pings will be sent.
38 PermitWithoutStream bool // false by default. 44 PermitWithoutStream bool // false by default.
39} 45}
40 46
41// ServerParameters is used to set keepalive and max-age parameters on the server-side. 47// ServerParameters is used to set keepalive and max-age parameters on the
48// server-side.
42type ServerParameters struct { 49type ServerParameters struct {
43 // MaxConnectionIdle is a duration for the amount of time after which an idle connection would be closed by sending a GoAway. 50 // MaxConnectionIdle is a duration for the amount of time after which an
44 // Idleness duration is defined since the most recent time the number of outstanding RPCs became zero or the connection establishment. 51 // idle connection would be closed by sending a GoAway. Idleness duration is
52 // defined since the most recent time the number of outstanding RPCs became
53 // zero or the connection establishment.
45 MaxConnectionIdle time.Duration // The current default value is infinity. 54 MaxConnectionIdle time.Duration // The current default value is infinity.
46 // MaxConnectionAge is a duration for the maximum amount of time a connection may exist before it will be closed by sending a GoAway. 55 // MaxConnectionAge is a duration for the maximum amount of time a
47 // A random jitter of +/-10% will be added to MaxConnectionAge to spread out connection storms. 56 // connection may exist before it will be closed by sending a GoAway. A
57 // random jitter of +/-10% will be added to MaxConnectionAge to spread out
58 // connection storms.
48 MaxConnectionAge time.Duration // The current default value is infinity. 59 MaxConnectionAge time.Duration // The current default value is infinity.
49 // MaxConnectinoAgeGrace is an additive period after MaxConnectionAge after which the connection will be forcibly closed. 60 // MaxConnectionAgeGrace is an additive period after MaxConnectionAge after
61 // which the connection will be forcibly closed.
50 MaxConnectionAgeGrace time.Duration // The current default value is infinity. 62 MaxConnectionAgeGrace time.Duration // The current default value is infinity.
51 // After a duration of this time if the server doesn't see any activity it pings the client to see if the transport is still alive. 63 // After a duration of this time if the server doesn't see any activity it
64 // pings the client to see if the transport is still alive.
52 Time time.Duration // The current default value is 2 hours. 65 Time time.Duration // The current default value is 2 hours.
53 // After having pinged for keepalive check, the server waits for a duration of Timeout and if no activity is seen even after that 66 // After having pinged for keepalive check, the server waits for a duration
54 // the connection is closed. 67 // of Timeout and if no activity is seen even after that the connection is
68 // closed.
55 Timeout time.Duration // The current default value is 20 seconds. 69 Timeout time.Duration // The current default value is 20 seconds.
56} 70}
57 71
58// EnforcementPolicy is used to set keepalive enforcement policy on the server-side. 72// EnforcementPolicy is used to set keepalive enforcement policy on the
59// Server will close connection with a client that violates this policy. 73// server-side. Server will close connection with a client that violates this
74// policy.
60type EnforcementPolicy struct { 75type EnforcementPolicy struct {
61 // MinTime is the minimum amount of time a client should wait before sending a keepalive ping. 76 // MinTime is the minimum amount of time a client should wait before sending
77 // a keepalive ping.
62 MinTime time.Duration // The current default value is 5 minutes. 78 MinTime time.Duration // The current default value is 5 minutes.
63 // If true, server expects keepalive pings even when there are no active streams(RPCs). 79 // If true, server allows keepalive pings even when there are no active
80 // streams(RPCs). If false, and client sends ping when there are no active
81 // streams, server will send GOAWAY and close the connection.
64 PermitWithoutStream bool // false by default. 82 PermitWithoutStream bool // false by default.
65} 83}
diff --git a/vendor/google.golang.org/grpc/metadata/metadata.go b/vendor/google.golang.org/grpc/metadata/metadata.go
index be4f9e7..cf6d1b9 100644
--- a/vendor/google.golang.org/grpc/metadata/metadata.go
+++ b/vendor/google.golang.org/grpc/metadata/metadata.go
@@ -17,17 +17,19 @@
17 */ 17 */
18 18
19// Package metadata define the structure of the metadata supported by gRPC library. 19// Package metadata define the structure of the metadata supported by gRPC library.
20// Please refer to https://grpc.io/docs/guides/wire.html for more information about custom-metadata. 20// Please refer to https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md
21// for more information about custom-metadata.
21package metadata // import "google.golang.org/grpc/metadata" 22package metadata // import "google.golang.org/grpc/metadata"
22 23
23import ( 24import (
25 "context"
24 "fmt" 26 "fmt"
25 "strings" 27 "strings"
26
27 "golang.org/x/net/context"
28) 28)
29 29
30// DecodeKeyValue returns k, v, nil. It is deprecated and should not be used. 30// DecodeKeyValue returns k, v, nil.
31//
32// Deprecated: use k and v directly instead.
31func DecodeKeyValue(k, v string) (string, string, error) { 33func DecodeKeyValue(k, v string) (string, string, error) {
32 return k, v, nil 34 return k, v, nil
33} 35}
@@ -44,6 +46,9 @@ type MD map[string][]string
44// - lowercase letters: a-z 46// - lowercase letters: a-z
45// - special characters: -_. 47// - special characters: -_.
46// Uppercase letters are automatically converted to lowercase. 48// Uppercase letters are automatically converted to lowercase.
49//
50// Keys beginning with "grpc-" are reserved for grpc-internal use only and may
51// result in errors if set in metadata.
47func New(m map[string]string) MD { 52func New(m map[string]string) MD {
48 md := MD{} 53 md := MD{}
49 for k, val := range m { 54 for k, val := range m {
@@ -62,6 +67,9 @@ func New(m map[string]string) MD {
62// - lowercase letters: a-z 67// - lowercase letters: a-z
63// - special characters: -_. 68// - special characters: -_.
64// Uppercase letters are automatically converted to lowercase. 69// Uppercase letters are automatically converted to lowercase.
70//
71// Keys beginning with "grpc-" are reserved for grpc-internal use only and may
72// result in errors if set in metadata.
65func Pairs(kv ...string) MD { 73func Pairs(kv ...string) MD {
66 if len(kv)%2 == 1 { 74 if len(kv)%2 == 1 {
67 panic(fmt.Sprintf("metadata: Pairs got the odd number of input pairs for metadata: %d", len(kv))) 75 panic(fmt.Sprintf("metadata: Pairs got the odd number of input pairs for metadata: %d", len(kv)))
@@ -88,6 +96,30 @@ func (md MD) Copy() MD {
88 return Join(md) 96 return Join(md)
89} 97}
90 98
99// Get obtains the values for a given key.
100func (md MD) Get(k string) []string {
101 k = strings.ToLower(k)
102 return md[k]
103}
104
105// Set sets the value of a given key with a slice of values.
106func (md MD) Set(k string, vals ...string) {
107 if len(vals) == 0 {
108 return
109 }
110 k = strings.ToLower(k)
111 md[k] = vals
112}
113
114// Append adds the values to key k, not overwriting what was already stored at that key.
115func (md MD) Append(k string, vals ...string) {
116 if len(vals) == 0 {
117 return
118 }
119 k = strings.ToLower(k)
120 md[k] = append(md[k], vals...)
121}
122
91// Join joins any number of mds into a single MD. 123// Join joins any number of mds into a single MD.
92// The order of values for each key is determined by the order in which 124// The order of values for each key is determined by the order in which
93// the mds containing those values are presented to Join. 125// the mds containing those values are presented to Join.
@@ -104,24 +136,31 @@ func Join(mds ...MD) MD {
104type mdIncomingKey struct{} 136type mdIncomingKey struct{}
105type mdOutgoingKey struct{} 137type mdOutgoingKey struct{}
106 138
107// NewContext is a wrapper for NewOutgoingContext(ctx, md). Deprecated.
108func NewContext(ctx context.Context, md MD) context.Context {
109 return NewOutgoingContext(ctx, md)
110}
111
112// NewIncomingContext creates a new context with incoming md attached. 139// NewIncomingContext creates a new context with incoming md attached.
113func NewIncomingContext(ctx context.Context, md MD) context.Context { 140func NewIncomingContext(ctx context.Context, md MD) context.Context {
114 return context.WithValue(ctx, mdIncomingKey{}, md) 141 return context.WithValue(ctx, mdIncomingKey{}, md)
115} 142}
116 143
117// NewOutgoingContext creates a new context with outgoing md attached. 144// NewOutgoingContext creates a new context with outgoing md attached. If used
145// in conjunction with AppendToOutgoingContext, NewOutgoingContext will
146// overwrite any previously-appended metadata.
118func NewOutgoingContext(ctx context.Context, md MD) context.Context { 147func NewOutgoingContext(ctx context.Context, md MD) context.Context {
119 return context.WithValue(ctx, mdOutgoingKey{}, md) 148 return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md})
120} 149}
121 150
122// FromContext is a wrapper for FromIncomingContext(ctx). Deprecated. 151// AppendToOutgoingContext returns a new context with the provided kv merged
123func FromContext(ctx context.Context) (md MD, ok bool) { 152// with any existing metadata in the context. Please refer to the
124 return FromIncomingContext(ctx) 153// documentation of Pairs for a description of kv.
154func AppendToOutgoingContext(ctx context.Context, kv ...string) context.Context {
155 if len(kv)%2 == 1 {
156 panic(fmt.Sprintf("metadata: AppendToOutgoingContext got an odd number of input pairs for metadata: %d", len(kv)))
157 }
158 md, _ := ctx.Value(mdOutgoingKey{}).(rawMD)
159 added := make([][]string, len(md.added)+1)
160 copy(added, md.added)
161 added[len(added)-1] = make([]string, len(kv))
162 copy(added[len(added)-1], kv)
163 return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md.md, added: added})
125} 164}
126 165
127// FromIncomingContext returns the incoming metadata in ctx if it exists. The 166// FromIncomingContext returns the incoming metadata in ctx if it exists. The
@@ -132,10 +171,39 @@ func FromIncomingContext(ctx context.Context) (md MD, ok bool) {
132 return 171 return
133} 172}
134 173
174// FromOutgoingContextRaw returns the un-merged, intermediary contents
175// of rawMD. Remember to perform strings.ToLower on the keys. The returned
176// MD should not be modified. Writing to it may cause races. Modification
177// should be made to copies of the returned MD.
178//
179// This is intended for gRPC-internal use ONLY.
180func FromOutgoingContextRaw(ctx context.Context) (MD, [][]string, bool) {
181 raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD)
182 if !ok {
183 return nil, nil, false
184 }
185
186 return raw.md, raw.added, true
187}
188
135// FromOutgoingContext returns the outgoing metadata in ctx if it exists. The 189// FromOutgoingContext returns the outgoing metadata in ctx if it exists. The
136// returned MD should not be modified. Writing to it may cause races. 190// returned MD should not be modified. Writing to it may cause races.
137// Modification should be made to the copies of the returned MD. 191// Modification should be made to copies of the returned MD.
138func FromOutgoingContext(ctx context.Context) (md MD, ok bool) { 192func FromOutgoingContext(ctx context.Context) (MD, bool) {
139 md, ok = ctx.Value(mdOutgoingKey{}).(MD) 193 raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD)
140 return 194 if !ok {
195 return nil, false
196 }
197
198 mds := make([]MD, 0, len(raw.added)+1)
199 mds = append(mds, raw.md)
200 for _, vv := range raw.added {
201 mds = append(mds, Pairs(vv...))
202 }
203 return Join(mds...), ok
204}
205
206type rawMD struct {
207 md MD
208 added [][]string
141} 209}
diff --git a/vendor/google.golang.org/grpc/naming/dns_resolver.go b/vendor/google.golang.org/grpc/naming/dns_resolver.go
index efd37e3..fd8cd3b 100644
--- a/vendor/google.golang.org/grpc/naming/dns_resolver.go
+++ b/vendor/google.golang.org/grpc/naming/dns_resolver.go
@@ -19,13 +19,13 @@
19package naming 19package naming
20 20
21import ( 21import (
22 "context"
22 "errors" 23 "errors"
23 "fmt" 24 "fmt"
24 "net" 25 "net"
25 "strconv" 26 "strconv"
26 "time" 27 "time"
27 28
28 "golang.org/x/net/context"
29 "google.golang.org/grpc/grpclog" 29 "google.golang.org/grpc/grpclog"
30) 30)
31 31
@@ -37,6 +37,9 @@ const (
37var ( 37var (
38 errMissingAddr = errors.New("missing address") 38 errMissingAddr = errors.New("missing address")
39 errWatcherClose = errors.New("watcher has been closed") 39 errWatcherClose = errors.New("watcher has been closed")
40
41 lookupHost = net.DefaultResolver.LookupHost
42 lookupSRV = net.DefaultResolver.LookupSRV
40) 43)
41 44
42// NewDNSResolverWithFreq creates a DNS Resolver that can resolve DNS names, and 45// NewDNSResolverWithFreq creates a DNS Resolver that can resolve DNS names, and
@@ -141,8 +144,8 @@ type dnsWatcher struct {
141 r *dnsResolver 144 r *dnsResolver
142 host string 145 host string
143 port string 146 port string
144 // The latest resolved address list 147 // The latest resolved address set
145 curAddrs []*Update 148 curAddrs map[string]*Update
146 ctx context.Context 149 ctx context.Context
147 cancel context.CancelFunc 150 cancel context.CancelFunc
148 t *time.Timer 151 t *time.Timer
@@ -153,10 +156,10 @@ type ipWatcher struct {
153 updateChan chan *Update 156 updateChan chan *Update
154} 157}
155 158
156// Next returns the adrress resolution Update for the target. For IP address, 159// Next returns the address resolution Update for the target. For IP address,
157// the resolution is itself, thus polling name server is unncessary. Therefore, 160// the resolution is itself, thus polling name server is unnecessary. Therefore,
158// Next() will return an Update the first time it is called, and will be blocked 161// Next() will return an Update the first time it is called, and will be blocked
159// for all following calls as no Update exisits until watcher is closed. 162// for all following calls as no Update exists until watcher is closed.
160func (i *ipWatcher) Next() ([]*Update, error) { 163func (i *ipWatcher) Next() ([]*Update, error) {
161 u, ok := <-i.updateChan 164 u, ok := <-i.updateChan
162 if !ok { 165 if !ok {
@@ -192,28 +195,24 @@ type AddrMetadataGRPCLB struct {
192 195
193// compileUpdate compares the old resolved addresses and newly resolved addresses, 196// compileUpdate compares the old resolved addresses and newly resolved addresses,
194// and generates an update list 197// and generates an update list
195func (w *dnsWatcher) compileUpdate(newAddrs []*Update) []*Update { 198func (w *dnsWatcher) compileUpdate(newAddrs map[string]*Update) []*Update {
196 update := make(map[Update]bool) 199 var res []*Update
197 for _, u := range newAddrs { 200 for a, u := range w.curAddrs {
198 update[*u] = true 201 if _, ok := newAddrs[a]; !ok {
199 } 202 u.Op = Delete
200 for _, u := range w.curAddrs { 203 res = append(res, u)
201 if _, ok := update[*u]; ok {
202 delete(update, *u)
203 continue
204 } 204 }
205 update[Update{Addr: u.Addr, Op: Delete, Metadata: u.Metadata}] = true
206 } 205 }
207 res := make([]*Update, 0, len(update)) 206 for a, u := range newAddrs {
208 for k := range update { 207 if _, ok := w.curAddrs[a]; !ok {
209 tmp := k 208 res = append(res, u)
210 res = append(res, &tmp) 209 }
211 } 210 }
212 return res 211 return res
213} 212}
214 213
215func (w *dnsWatcher) lookupSRV() []*Update { 214func (w *dnsWatcher) lookupSRV() map[string]*Update {
216 var newAddrs []*Update 215 newAddrs := make(map[string]*Update)
217 _, srvs, err := lookupSRV(w.ctx, "grpclb", "tcp", w.host) 216 _, srvs, err := lookupSRV(w.ctx, "grpclb", "tcp", w.host)
218 if err != nil { 217 if err != nil {
219 grpclog.Infof("grpc: failed dns SRV record lookup due to %v.\n", err) 218 grpclog.Infof("grpc: failed dns SRV record lookup due to %v.\n", err)
@@ -231,15 +230,16 @@ func (w *dnsWatcher) lookupSRV() []*Update {
231 grpclog.Errorf("grpc: failed IP parsing due to %v.\n", err) 230 grpclog.Errorf("grpc: failed IP parsing due to %v.\n", err)
232 continue 231 continue
233 } 232 }
234 newAddrs = append(newAddrs, &Update{Addr: a + ":" + strconv.Itoa(int(s.Port)), 233 addr := a + ":" + strconv.Itoa(int(s.Port))
235 Metadata: AddrMetadataGRPCLB{AddrType: GRPCLB, ServerName: s.Target}}) 234 newAddrs[addr] = &Update{Addr: addr,
235 Metadata: AddrMetadataGRPCLB{AddrType: GRPCLB, ServerName: s.Target}}
236 } 236 }
237 } 237 }
238 return newAddrs 238 return newAddrs
239} 239}
240 240
241func (w *dnsWatcher) lookupHost() []*Update { 241func (w *dnsWatcher) lookupHost() map[string]*Update {
242 var newAddrs []*Update 242 newAddrs := make(map[string]*Update)
243 addrs, err := lookupHost(w.ctx, w.host) 243 addrs, err := lookupHost(w.ctx, w.host)
244 if err != nil { 244 if err != nil {
245 grpclog.Warningf("grpc: failed dns A record lookup due to %v.\n", err) 245 grpclog.Warningf("grpc: failed dns A record lookup due to %v.\n", err)
@@ -251,7 +251,8 @@ func (w *dnsWatcher) lookupHost() []*Update {
251 grpclog.Errorf("grpc: failed IP parsing due to %v.\n", err) 251 grpclog.Errorf("grpc: failed IP parsing due to %v.\n", err)
252 continue 252 continue
253 } 253 }
254 newAddrs = append(newAddrs, &Update{Addr: a + ":" + w.port}) 254 addr := a + ":" + w.port
255 newAddrs[addr] = &Update{Addr: addr}
255 } 256 }
256 return newAddrs 257 return newAddrs
257} 258}
diff --git a/vendor/google.golang.org/grpc/naming/naming.go b/vendor/google.golang.org/grpc/naming/naming.go
index 1af7e32..8cc39e9 100644
--- a/vendor/google.golang.org/grpc/naming/naming.go
+++ b/vendor/google.golang.org/grpc/naming/naming.go
@@ -18,20 +18,26 @@
18 18
19// Package naming defines the naming API and related data structures for gRPC. 19// Package naming defines the naming API and related data structures for gRPC.
20// The interface is EXPERIMENTAL and may be suject to change. 20// The interface is EXPERIMENTAL and may be suject to change.
21//
22// Deprecated: please use package resolver.
21package naming 23package naming
22 24
23// Operation defines the corresponding operations for a name resolution change. 25// Operation defines the corresponding operations for a name resolution change.
26//
27// Deprecated: please use package resolver.
24type Operation uint8 28type Operation uint8
25 29
26const ( 30const (
27 // Add indicates a new address is added. 31 // Add indicates a new address is added.
28 Add Operation = iota 32 Add Operation = iota
29 // Delete indicates an exisiting address is deleted. 33 // Delete indicates an existing address is deleted.
30 Delete 34 Delete
31) 35)
32 36
33// Update defines a name resolution update. Notice that it is not valid having both 37// Update defines a name resolution update. Notice that it is not valid having both
34// empty string Addr and nil Metadata in an Update. 38// empty string Addr and nil Metadata in an Update.
39//
40// Deprecated: please use package resolver.
35type Update struct { 41type Update struct {
36 // Op indicates the operation of the update. 42 // Op indicates the operation of the update.
37 Op Operation 43 Op Operation
@@ -43,12 +49,16 @@ type Update struct {
43} 49}
44 50
45// Resolver creates a Watcher for a target to track its resolution changes. 51// Resolver creates a Watcher for a target to track its resolution changes.
52//
53// Deprecated: please use package resolver.
46type Resolver interface { 54type Resolver interface {
47 // Resolve creates a Watcher for target. 55 // Resolve creates a Watcher for target.
48 Resolve(target string) (Watcher, error) 56 Resolve(target string) (Watcher, error)
49} 57}
50 58
51// Watcher watches for the updates on the specified target. 59// Watcher watches for the updates on the specified target.
60//
61// Deprecated: please use package resolver.
52type Watcher interface { 62type Watcher interface {
53 // Next blocks until an update or error happens. It may return one or more 63 // Next blocks until an update or error happens. It may return one or more
54 // updates. The first call should get the full set of the results. It should 64 // updates. The first call should get the full set of the results. It should
diff --git a/vendor/google.golang.org/grpc/peer/peer.go b/vendor/google.golang.org/grpc/peer/peer.go
index 317b8b9..e01d219 100644
--- a/vendor/google.golang.org/grpc/peer/peer.go
+++ b/vendor/google.golang.org/grpc/peer/peer.go
@@ -21,9 +21,9 @@
21package peer 21package peer
22 22
23import ( 23import (
24 "context"
24 "net" 25 "net"
25 26
26 "golang.org/x/net/context"
27 "google.golang.org/grpc/credentials" 27 "google.golang.org/grpc/credentials"
28) 28)
29 29
diff --git a/vendor/google.golang.org/grpc/picker_wrapper.go b/vendor/google.golang.org/grpc/picker_wrapper.go
new file mode 100644
index 0000000..14f915d
--- /dev/null
+++ b/vendor/google.golang.org/grpc/picker_wrapper.go
@@ -0,0 +1,180 @@
1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package grpc
20
21import (
22 "context"
23 "io"
24 "sync"
25
26 "google.golang.org/grpc/balancer"
27 "google.golang.org/grpc/codes"
28 "google.golang.org/grpc/grpclog"
29 "google.golang.org/grpc/internal/channelz"
30 "google.golang.org/grpc/internal/transport"
31 "google.golang.org/grpc/status"
32)
33
34// pickerWrapper is a wrapper of balancer.Picker. It blocks on certain pick
35// actions and unblock when there's a picker update.
36type pickerWrapper struct {
37 mu sync.Mutex
38 done bool
39 blockingCh chan struct{}
40 picker balancer.Picker
41
42 // The latest connection happened.
43 connErrMu sync.Mutex
44 connErr error
45}
46
47func newPickerWrapper() *pickerWrapper {
48 bp := &pickerWrapper{blockingCh: make(chan struct{})}
49 return bp
50}
51
52func (bp *pickerWrapper) updateConnectionError(err error) {
53 bp.connErrMu.Lock()
54 bp.connErr = err
55 bp.connErrMu.Unlock()
56}
57
58func (bp *pickerWrapper) connectionError() error {
59 bp.connErrMu.Lock()
60 err := bp.connErr
61 bp.connErrMu.Unlock()
62 return err
63}
64
65// updatePicker is called by UpdateBalancerState. It unblocks all blocked pick.
66func (bp *pickerWrapper) updatePicker(p balancer.Picker) {
67 bp.mu.Lock()
68 if bp.done {
69 bp.mu.Unlock()
70 return
71 }
72 bp.picker = p
73 // bp.blockingCh should never be nil.
74 close(bp.blockingCh)
75 bp.blockingCh = make(chan struct{})
76 bp.mu.Unlock()
77}
78
79func doneChannelzWrapper(acw *acBalancerWrapper, done func(balancer.DoneInfo)) func(balancer.DoneInfo) {
80 acw.mu.Lock()
81 ac := acw.ac
82 acw.mu.Unlock()
83 ac.incrCallsStarted()
84 return func(b balancer.DoneInfo) {
85 if b.Err != nil && b.Err != io.EOF {
86 ac.incrCallsFailed()
87 } else {
88 ac.incrCallsSucceeded()
89 }
90 if done != nil {
91 done(b)
92 }
93 }
94}
95
96// pick returns the transport that will be used for the RPC.
97// It may block in the following cases:
98// - there's no picker
99// - the current picker returns ErrNoSubConnAvailable
100// - the current picker returns other errors and failfast is false.
101// - the subConn returned by the current picker is not READY
102// When one of these situations happens, pick blocks until the picker gets updated.
103func (bp *pickerWrapper) pick(ctx context.Context, failfast bool, opts balancer.PickOptions) (transport.ClientTransport, func(balancer.DoneInfo), error) {
104 var (
105 p balancer.Picker
106 ch chan struct{}
107 )
108
109 for {
110 bp.mu.Lock()
111 if bp.done {
112 bp.mu.Unlock()
113 return nil, nil, ErrClientConnClosing
114 }
115
116 if bp.picker == nil {
117 ch = bp.blockingCh
118 }
119 if ch == bp.blockingCh {
120 // This could happen when either:
121 // - bp.picker is nil (the previous if condition), or
122 // - has called pick on the current picker.
123 bp.mu.Unlock()
124 select {
125 case <-ctx.Done():
126 return nil, nil, ctx.Err()
127 case <-ch:
128 }
129 continue
130 }
131
132 ch = bp.blockingCh
133 p = bp.picker
134 bp.mu.Unlock()
135
136 subConn, done, err := p.Pick(ctx, opts)
137
138 if err != nil {
139 switch err {
140 case balancer.ErrNoSubConnAvailable:
141 continue
142 case balancer.ErrTransientFailure:
143 if !failfast {
144 continue
145 }
146 return nil, nil, status.Errorf(codes.Unavailable, "%v, latest connection error: %v", err, bp.connectionError())
147 default:
148 // err is some other error.
149 return nil, nil, toRPCErr(err)
150 }
151 }
152
153 acw, ok := subConn.(*acBalancerWrapper)
154 if !ok {
155 grpclog.Infof("subconn returned from pick is not *acBalancerWrapper")
156 continue
157 }
158 if t, ok := acw.getAddrConn().getReadyTransport(); ok {
159 if channelz.IsOn() {
160 return t, doneChannelzWrapper(acw, done), nil
161 }
162 return t, done, nil
163 }
164 grpclog.Infof("blockingPicker: the picked transport is not ready, loop back to repick")
165 // If ok == false, ac.state is not READY.
166 // A valid picker always returns READY subConn. This means the state of ac
167 // just changed, and picker will be updated shortly.
168 // continue back to the beginning of the for loop to repick.
169 }
170}
171
172func (bp *pickerWrapper) close() {
173 bp.mu.Lock()
174 defer bp.mu.Unlock()
175 if bp.done {
176 return
177 }
178 bp.done = true
179 close(bp.blockingCh)
180}
diff --git a/vendor/google.golang.org/grpc/pickfirst.go b/vendor/google.golang.org/grpc/pickfirst.go
new file mode 100644
index 0000000..d1e38aa
--- /dev/null
+++ b/vendor/google.golang.org/grpc/pickfirst.go
@@ -0,0 +1,110 @@
1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package grpc
20
21import (
22 "context"
23
24 "google.golang.org/grpc/balancer"
25 "google.golang.org/grpc/connectivity"
26 "google.golang.org/grpc/grpclog"
27 "google.golang.org/grpc/resolver"
28)
29
30// PickFirstBalancerName is the name of the pick_first balancer.
31const PickFirstBalancerName = "pick_first"
32
33func newPickfirstBuilder() balancer.Builder {
34 return &pickfirstBuilder{}
35}
36
37type pickfirstBuilder struct{}
38
39func (*pickfirstBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer {
40 return &pickfirstBalancer{cc: cc}
41}
42
43func (*pickfirstBuilder) Name() string {
44 return PickFirstBalancerName
45}
46
47type pickfirstBalancer struct {
48 cc balancer.ClientConn
49 sc balancer.SubConn
50}
51
52func (b *pickfirstBalancer) HandleResolvedAddrs(addrs []resolver.Address, err error) {
53 if err != nil {
54 grpclog.Infof("pickfirstBalancer: HandleResolvedAddrs called with error %v", err)
55 return
56 }
57 if b.sc == nil {
58 b.sc, err = b.cc.NewSubConn(addrs, balancer.NewSubConnOptions{})
59 if err != nil {
60 //TODO(yuxuanli): why not change the cc state to Idle?
61 grpclog.Errorf("pickfirstBalancer: failed to NewSubConn: %v", err)
62 return
63 }
64 b.cc.UpdateBalancerState(connectivity.Idle, &picker{sc: b.sc})
65 b.sc.Connect()
66 } else {
67 b.sc.UpdateAddresses(addrs)
68 b.sc.Connect()
69 }
70}
71
72func (b *pickfirstBalancer) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
73 grpclog.Infof("pickfirstBalancer: HandleSubConnStateChange: %p, %v", sc, s)
74 if b.sc != sc {
75 grpclog.Infof("pickfirstBalancer: ignored state change because sc is not recognized")
76 return
77 }
78 if s == connectivity.Shutdown {
79 b.sc = nil
80 return
81 }
82
83 switch s {
84 case connectivity.Ready, connectivity.Idle:
85 b.cc.UpdateBalancerState(s, &picker{sc: sc})
86 case connectivity.Connecting:
87 b.cc.UpdateBalancerState(s, &picker{err: balancer.ErrNoSubConnAvailable})
88 case connectivity.TransientFailure:
89 b.cc.UpdateBalancerState(s, &picker{err: balancer.ErrTransientFailure})
90 }
91}
92
93func (b *pickfirstBalancer) Close() {
94}
95
96type picker struct {
97 err error
98 sc balancer.SubConn
99}
100
101func (p *picker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
102 if p.err != nil {
103 return nil, nil, p.err
104 }
105 return p.sc, nil, nil
106}
107
108func init() {
109 balancer.Register(newPickfirstBuilder())
110}
diff --git a/vendor/google.golang.org/grpc/proxy.go b/vendor/google.golang.org/grpc/proxy.go
index 2d40236..f8f69bf 100644
--- a/vendor/google.golang.org/grpc/proxy.go
+++ b/vendor/google.golang.org/grpc/proxy.go
@@ -20,6 +20,8 @@ package grpc
20 20
21import ( 21import (
22 "bufio" 22 "bufio"
23 "context"
24 "encoding/base64"
23 "errors" 25 "errors"
24 "fmt" 26 "fmt"
25 "io" 27 "io"
@@ -27,10 +29,10 @@ import (
27 "net/http" 29 "net/http"
28 "net/http/httputil" 30 "net/http/httputil"
29 "net/url" 31 "net/url"
30
31 "golang.org/x/net/context"
32) 32)
33 33
34const proxyAuthHeaderKey = "Proxy-Authorization"
35
34var ( 36var (
35 // errDisabled indicates that proxy is disabled for the address. 37 // errDisabled indicates that proxy is disabled for the address.
36 errDisabled = errors.New("proxy is disabled for the address") 38 errDisabled = errors.New("proxy is disabled for the address")
@@ -38,7 +40,7 @@ var (
38 httpProxyFromEnvironment = http.ProxyFromEnvironment 40 httpProxyFromEnvironment = http.ProxyFromEnvironment
39) 41)
40 42
41func mapAddress(ctx context.Context, address string) (string, error) { 43func mapAddress(ctx context.Context, address string) (*url.URL, error) {
42 req := &http.Request{ 44 req := &http.Request{
43 URL: &url.URL{ 45 URL: &url.URL{
44 Scheme: "https", 46 Scheme: "https",
@@ -47,12 +49,12 @@ func mapAddress(ctx context.Context, address string) (string, error) {
47 } 49 }
48 url, err := httpProxyFromEnvironment(req) 50 url, err := httpProxyFromEnvironment(req)
49 if err != nil { 51 if err != nil {
50 return "", err 52 return nil, err
51 } 53 }
52 if url == nil { 54 if url == nil {
53 return "", errDisabled 55 return nil, errDisabled
54 } 56 }
55 return url.Host, nil 57 return url, nil
56} 58}
57 59
58// To read a response from a net.Conn, http.ReadResponse() takes a bufio.Reader. 60// To read a response from a net.Conn, http.ReadResponse() takes a bufio.Reader.
@@ -69,18 +71,28 @@ func (c *bufConn) Read(b []byte) (int, error) {
69 return c.r.Read(b) 71 return c.r.Read(b)
70} 72}
71 73
72func doHTTPConnectHandshake(ctx context.Context, conn net.Conn, addr string) (_ net.Conn, err error) { 74func basicAuth(username, password string) string {
75 auth := username + ":" + password
76 return base64.StdEncoding.EncodeToString([]byte(auth))
77}
78
79func doHTTPConnectHandshake(ctx context.Context, conn net.Conn, backendAddr string, proxyURL *url.URL) (_ net.Conn, err error) {
73 defer func() { 80 defer func() {
74 if err != nil { 81 if err != nil {
75 conn.Close() 82 conn.Close()
76 } 83 }
77 }() 84 }()
78 85
79 req := (&http.Request{ 86 req := &http.Request{
80 Method: http.MethodConnect, 87 Method: http.MethodConnect,
81 URL: &url.URL{Host: addr}, 88 URL: &url.URL{Host: backendAddr},
82 Header: map[string][]string{"User-Agent": {grpcUA}}, 89 Header: map[string][]string{"User-Agent": {grpcUA}},
83 }) 90 }
91 if t := proxyURL.User; t != nil {
92 u := t.Username()
93 p, _ := t.Password()
94 req.Header.Add(proxyAuthHeaderKey, "Basic "+basicAuth(u, p))
95 }
84 96
85 if err := sendHTTPRequest(ctx, req, conn); err != nil { 97 if err := sendHTTPRequest(ctx, req, conn); err != nil {
86 return nil, fmt.Errorf("failed to write the HTTP request: %v", err) 98 return nil, fmt.Errorf("failed to write the HTTP request: %v", err)
@@ -108,23 +120,33 @@ func doHTTPConnectHandshake(ctx context.Context, conn net.Conn, addr string) (_
108// provided dialer, does HTTP CONNECT handshake and returns the connection. 120// provided dialer, does HTTP CONNECT handshake and returns the connection.
109func newProxyDialer(dialer func(context.Context, string) (net.Conn, error)) func(context.Context, string) (net.Conn, error) { 121func newProxyDialer(dialer func(context.Context, string) (net.Conn, error)) func(context.Context, string) (net.Conn, error) {
110 return func(ctx context.Context, addr string) (conn net.Conn, err error) { 122 return func(ctx context.Context, addr string) (conn net.Conn, err error) {
111 var skipHandshake bool 123 var newAddr string
112 newAddr, err := mapAddress(ctx, addr) 124 proxyURL, err := mapAddress(ctx, addr)
113 if err != nil { 125 if err != nil {
114 if err != errDisabled { 126 if err != errDisabled {
115 return nil, err 127 return nil, err
116 } 128 }
117 skipHandshake = true
118 newAddr = addr 129 newAddr = addr
130 } else {
131 newAddr = proxyURL.Host
119 } 132 }
120 133
121 conn, err = dialer(ctx, newAddr) 134 conn, err = dialer(ctx, newAddr)
122 if err != nil { 135 if err != nil {
123 return 136 return
124 } 137 }
125 if !skipHandshake { 138 if proxyURL != nil {
126 conn, err = doHTTPConnectHandshake(ctx, conn, addr) 139 // proxy is disabled if proxyURL is nil.
140 conn, err = doHTTPConnectHandshake(ctx, conn, addr, proxyURL)
127 } 141 }
128 return 142 return
129 } 143 }
130} 144}
145
146func sendHTTPRequest(ctx context.Context, req *http.Request, conn net.Conn) error {
147 req = req.WithContext(ctx)
148 if err := req.Write(conn); err != nil {
149 return fmt.Errorf("failed to write the HTTP request: %v", err)
150 }
151 return nil
152}
diff --git a/vendor/google.golang.org/grpc/resolver/dns/dns_resolver.go b/vendor/google.golang.org/grpc/resolver/dns/dns_resolver.go
new file mode 100644
index 0000000..f33189f
--- /dev/null
+++ b/vendor/google.golang.org/grpc/resolver/dns/dns_resolver.go
@@ -0,0 +1,436 @@
1/*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// Package dns implements a dns resolver to be installed as the default resolver
20// in grpc.
21package dns
22
23import (
24 "context"
25 "encoding/json"
26 "errors"
27 "fmt"
28 "net"
29 "os"
30 "strconv"
31 "strings"
32 "sync"
33 "time"
34
35 "google.golang.org/grpc/grpclog"
36 "google.golang.org/grpc/internal/backoff"
37 "google.golang.org/grpc/internal/grpcrand"
38 "google.golang.org/grpc/resolver"
39)
40
41func init() {
42 resolver.Register(NewBuilder())
43}
44
45const (
46 defaultPort = "443"
47 defaultFreq = time.Minute * 30
48 defaultDNSSvrPort = "53"
49 golang = "GO"
50 // In DNS, service config is encoded in a TXT record via the mechanism
51 // described in RFC-1464 using the attribute name grpc_config.
52 txtAttribute = "grpc_config="
53)
54
55var (
56 errMissingAddr = errors.New("dns resolver: missing address")
57
58 // Addresses ending with a colon that is supposed to be the separator
59 // between host and port is not allowed. E.g. "::" is a valid address as
60 // it is an IPv6 address (host only) and "[::]:" is invalid as it ends with
61 // a colon as the host and port separator
62 errEndsWithColon = errors.New("dns resolver: missing port after port-separator colon")
63)
64
65var (
66 defaultResolver netResolver = net.DefaultResolver
67)
68
69var customAuthorityDialler = func(authority string) func(ctx context.Context, network, address string) (net.Conn, error) {
70 return func(ctx context.Context, network, address string) (net.Conn, error) {
71 var dialer net.Dialer
72 return dialer.DialContext(ctx, network, authority)
73 }
74}
75
76var customAuthorityResolver = func(authority string) (netResolver, error) {
77 host, port, err := parseTarget(authority, defaultDNSSvrPort)
78 if err != nil {
79 return nil, err
80 }
81
82 authorityWithPort := net.JoinHostPort(host, port)
83
84 return &net.Resolver{
85 PreferGo: true,
86 Dial: customAuthorityDialler(authorityWithPort),
87 }, nil
88}
89
90// NewBuilder creates a dnsBuilder which is used to factory DNS resolvers.
91func NewBuilder() resolver.Builder {
92 return &dnsBuilder{minFreq: defaultFreq}
93}
94
95type dnsBuilder struct {
96 // minimum frequency of polling the DNS server.
97 minFreq time.Duration
98}
99
100// Build creates and starts a DNS resolver that watches the name resolution of the target.
101func (b *dnsBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOption) (resolver.Resolver, error) {
102 host, port, err := parseTarget(target.Endpoint, defaultPort)
103 if err != nil {
104 return nil, err
105 }
106
107 // IP address.
108 if net.ParseIP(host) != nil {
109 host, _ = formatIP(host)
110 addr := []resolver.Address{{Addr: host + ":" + port}}
111 i := &ipResolver{
112 cc: cc,
113 ip: addr,
114 rn: make(chan struct{}, 1),
115 q: make(chan struct{}),
116 }
117 cc.NewAddress(addr)
118 go i.watcher()
119 return i, nil
120 }
121
122 // DNS address (non-IP).
123 ctx, cancel := context.WithCancel(context.Background())
124 d := &dnsResolver{
125 freq: b.minFreq,
126 backoff: backoff.Exponential{MaxDelay: b.minFreq},
127 host: host,
128 port: port,
129 ctx: ctx,
130 cancel: cancel,
131 cc: cc,
132 t: time.NewTimer(0),
133 rn: make(chan struct{}, 1),
134 disableServiceConfig: opts.DisableServiceConfig,
135 }
136
137 if target.Authority == "" {
138 d.resolver = defaultResolver
139 } else {
140 d.resolver, err = customAuthorityResolver(target.Authority)
141 if err != nil {
142 return nil, err
143 }
144 }
145
146 d.wg.Add(1)
147 go d.watcher()
148 return d, nil
149}
150
151// Scheme returns the naming scheme of this resolver builder, which is "dns".
152func (b *dnsBuilder) Scheme() string {
153 return "dns"
154}
155
156type netResolver interface {
157 LookupHost(ctx context.Context, host string) (addrs []string, err error)
158 LookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*net.SRV, err error)
159 LookupTXT(ctx context.Context, name string) (txts []string, err error)
160}
161
162// ipResolver watches for the name resolution update for an IP address.
163type ipResolver struct {
164 cc resolver.ClientConn
165 ip []resolver.Address
166 // rn channel is used by ResolveNow() to force an immediate resolution of the target.
167 rn chan struct{}
168 q chan struct{}
169}
170
171// ResolveNow resend the address it stores, no resolution is needed.
172func (i *ipResolver) ResolveNow(opt resolver.ResolveNowOption) {
173 select {
174 case i.rn <- struct{}{}:
175 default:
176 }
177}
178
179// Close closes the ipResolver.
180func (i *ipResolver) Close() {
181 close(i.q)
182}
183
184func (i *ipResolver) watcher() {
185 for {
186 select {
187 case <-i.rn:
188 i.cc.NewAddress(i.ip)
189 case <-i.q:
190 return
191 }
192 }
193}
194
195// dnsResolver watches for the name resolution update for a non-IP target.
196type dnsResolver struct {
197 freq time.Duration
198 backoff backoff.Exponential
199 retryCount int
200 host string
201 port string
202 resolver netResolver
203 ctx context.Context
204 cancel context.CancelFunc
205 cc resolver.ClientConn
206 // rn channel is used by ResolveNow() to force an immediate resolution of the target.
207 rn chan struct{}
208 t *time.Timer
209 // wg is used to enforce Close() to return after the watcher() goroutine has finished.
210 // Otherwise, data race will be possible. [Race Example] in dns_resolver_test we
211 // replace the real lookup functions with mocked ones to facilitate testing.
212 // If Close() doesn't wait for watcher() goroutine finishes, race detector sometimes
213 // will warns lookup (READ the lookup function pointers) inside watcher() goroutine
214 // has data race with replaceNetFunc (WRITE the lookup function pointers).
215 wg sync.WaitGroup
216 disableServiceConfig bool
217}
218
219// ResolveNow invoke an immediate resolution of the target that this dnsResolver watches.
220func (d *dnsResolver) ResolveNow(opt resolver.ResolveNowOption) {
221 select {
222 case d.rn <- struct{}{}:
223 default:
224 }
225}
226
227// Close closes the dnsResolver.
228func (d *dnsResolver) Close() {
229 d.cancel()
230 d.wg.Wait()
231 d.t.Stop()
232}
233
234func (d *dnsResolver) watcher() {
235 defer d.wg.Done()
236 for {
237 select {
238 case <-d.ctx.Done():
239 return
240 case <-d.t.C:
241 case <-d.rn:
242 }
243 result, sc := d.lookup()
244 // Next lookup should happen within an interval defined by d.freq. It may be
245 // more often due to exponential retry on empty address list.
246 if len(result) == 0 {
247 d.retryCount++
248 d.t.Reset(d.backoff.Backoff(d.retryCount))
249 } else {
250 d.retryCount = 0
251 d.t.Reset(d.freq)
252 }
253 d.cc.NewServiceConfig(sc)
254 d.cc.NewAddress(result)
255 }
256}
257
258func (d *dnsResolver) lookupSRV() []resolver.Address {
259 var newAddrs []resolver.Address
260 _, srvs, err := d.resolver.LookupSRV(d.ctx, "grpclb", "tcp", d.host)
261 if err != nil {
262 grpclog.Infof("grpc: failed dns SRV record lookup due to %v.\n", err)
263 return nil
264 }
265 for _, s := range srvs {
266 lbAddrs, err := d.resolver.LookupHost(d.ctx, s.Target)
267 if err != nil {
268 grpclog.Infof("grpc: failed load balancer address dns lookup due to %v.\n", err)
269 continue
270 }
271 for _, a := range lbAddrs {
272 a, ok := formatIP(a)
273 if !ok {
274 grpclog.Errorf("grpc: failed IP parsing due to %v.\n", err)
275 continue
276 }
277 addr := a + ":" + strconv.Itoa(int(s.Port))
278 newAddrs = append(newAddrs, resolver.Address{Addr: addr, Type: resolver.GRPCLB, ServerName: s.Target})
279 }
280 }
281 return newAddrs
282}
283
284func (d *dnsResolver) lookupTXT() string {
285 ss, err := d.resolver.LookupTXT(d.ctx, d.host)
286 if err != nil {
287 grpclog.Infof("grpc: failed dns TXT record lookup due to %v.\n", err)
288 return ""
289 }
290 var res string
291 for _, s := range ss {
292 res += s
293 }
294
295 // TXT record must have "grpc_config=" attribute in order to be used as service config.
296 if !strings.HasPrefix(res, txtAttribute) {
297 grpclog.Warningf("grpc: TXT record %v missing %v attribute", res, txtAttribute)
298 return ""
299 }
300 return strings.TrimPrefix(res, txtAttribute)
301}
302
303func (d *dnsResolver) lookupHost() []resolver.Address {
304 var newAddrs []resolver.Address
305 addrs, err := d.resolver.LookupHost(d.ctx, d.host)
306 if err != nil {
307 grpclog.Warningf("grpc: failed dns A record lookup due to %v.\n", err)
308 return nil
309 }
310 for _, a := range addrs {
311 a, ok := formatIP(a)
312 if !ok {
313 grpclog.Errorf("grpc: failed IP parsing due to %v.\n", err)
314 continue
315 }
316 addr := a + ":" + d.port
317 newAddrs = append(newAddrs, resolver.Address{Addr: addr})
318 }
319 return newAddrs
320}
321
322func (d *dnsResolver) lookup() ([]resolver.Address, string) {
323 newAddrs := d.lookupSRV()
324 // Support fallback to non-balancer address.
325 newAddrs = append(newAddrs, d.lookupHost()...)
326 if d.disableServiceConfig {
327 return newAddrs, ""
328 }
329 sc := d.lookupTXT()
330 return newAddrs, canaryingSC(sc)
331}
332
333// formatIP returns ok = false if addr is not a valid textual representation of an IP address.
334// If addr is an IPv4 address, return the addr and ok = true.
335// If addr is an IPv6 address, return the addr enclosed in square brackets and ok = true.
336func formatIP(addr string) (addrIP string, ok bool) {
337 ip := net.ParseIP(addr)
338 if ip == nil {
339 return "", false
340 }
341 if ip.To4() != nil {
342 return addr, true
343 }
344 return "[" + addr + "]", true
345}
346
347// parseTarget takes the user input target string and default port, returns formatted host and port info.
348// If target doesn't specify a port, set the port to be the defaultPort.
349// If target is in IPv6 format and host-name is enclosed in sqarue brackets, brackets
350// are strippd when setting the host.
351// examples:
352// target: "www.google.com" defaultPort: "443" returns host: "www.google.com", port: "443"
353// target: "ipv4-host:80" defaultPort: "443" returns host: "ipv4-host", port: "80"
354// target: "[ipv6-host]" defaultPort: "443" returns host: "ipv6-host", port: "443"
355// target: ":80" defaultPort: "443" returns host: "localhost", port: "80"
356func parseTarget(target, defaultPort string) (host, port string, err error) {
357 if target == "" {
358 return "", "", errMissingAddr
359 }
360 if ip := net.ParseIP(target); ip != nil {
361 // target is an IPv4 or IPv6(without brackets) address
362 return target, defaultPort, nil
363 }
364 if host, port, err = net.SplitHostPort(target); err == nil {
365 if port == "" {
366 // If the port field is empty (target ends with colon), e.g. "[::1]:", this is an error.
367 return "", "", errEndsWithColon
368 }
369 // target has port, i.e ipv4-host:port, [ipv6-host]:port, host-name:port
370 if host == "" {
371 // Keep consistent with net.Dial(): If the host is empty, as in ":80", the local system is assumed.
372 host = "localhost"
373 }
374 return host, port, nil
375 }
376 if host, port, err = net.SplitHostPort(target + ":" + defaultPort); err == nil {
377 // target doesn't have port
378 return host, port, nil
379 }
380 return "", "", fmt.Errorf("invalid target address %v, error info: %v", target, err)
381}
382
383type rawChoice struct {
384 ClientLanguage *[]string `json:"clientLanguage,omitempty"`
385 Percentage *int `json:"percentage,omitempty"`
386 ClientHostName *[]string `json:"clientHostName,omitempty"`
387 ServiceConfig *json.RawMessage `json:"serviceConfig,omitempty"`
388}
389
390func containsString(a *[]string, b string) bool {
391 if a == nil {
392 return true
393 }
394 for _, c := range *a {
395 if c == b {
396 return true
397 }
398 }
399 return false
400}
401
402func chosenByPercentage(a *int) bool {
403 if a == nil {
404 return true
405 }
406 return grpcrand.Intn(100)+1 <= *a
407}
408
409func canaryingSC(js string) string {
410 if js == "" {
411 return ""
412 }
413 var rcs []rawChoice
414 err := json.Unmarshal([]byte(js), &rcs)
415 if err != nil {
416 grpclog.Warningf("grpc: failed to parse service config json string due to %v.\n", err)
417 return ""
418 }
419 cliHostname, err := os.Hostname()
420 if err != nil {
421 grpclog.Warningf("grpc: failed to get client hostname due to %v.\n", err)
422 return ""
423 }
424 var sc string
425 for _, c := range rcs {
426 if !containsString(c.ClientLanguage, golang) ||
427 !chosenByPercentage(c.Percentage) ||
428 !containsString(c.ClientHostName, cliHostname) ||
429 c.ServiceConfig == nil {
430 continue
431 }
432 sc = string(*c.ServiceConfig)
433 break
434 }
435 return sc
436}
diff --git a/vendor/google.golang.org/grpc/resolver/passthrough/passthrough.go b/vendor/google.golang.org/grpc/resolver/passthrough/passthrough.go
new file mode 100644
index 0000000..b76010d
--- /dev/null
+++ b/vendor/google.golang.org/grpc/resolver/passthrough/passthrough.go
@@ -0,0 +1,57 @@
1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// Package passthrough implements a pass-through resolver. It sends the target
20// name without scheme back to gRPC as resolved address.
21package passthrough
22
23import "google.golang.org/grpc/resolver"
24
25const scheme = "passthrough"
26
27type passthroughBuilder struct{}
28
29func (*passthroughBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOption) (resolver.Resolver, error) {
30 r := &passthroughResolver{
31 target: target,
32 cc: cc,
33 }
34 r.start()
35 return r, nil
36}
37
38func (*passthroughBuilder) Scheme() string {
39 return scheme
40}
41
42type passthroughResolver struct {
43 target resolver.Target
44 cc resolver.ClientConn
45}
46
47func (r *passthroughResolver) start() {
48 r.cc.NewAddress([]resolver.Address{{Addr: r.target.Endpoint}})
49}
50
51func (*passthroughResolver) ResolveNow(o resolver.ResolveNowOption) {}
52
53func (*passthroughResolver) Close() {}
54
55func init() {
56 resolver.Register(&passthroughBuilder{})
57}
diff --git a/vendor/google.golang.org/grpc/resolver/resolver.go b/vendor/google.golang.org/grpc/resolver/resolver.go
new file mode 100644
index 0000000..145cf47
--- /dev/null
+++ b/vendor/google.golang.org/grpc/resolver/resolver.go
@@ -0,0 +1,158 @@
1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// Package resolver defines APIs for name resolution in gRPC.
20// All APIs in this package are experimental.
21package resolver
22
23var (
24 // m is a map from scheme to resolver builder.
25 m = make(map[string]Builder)
26 // defaultScheme is the default scheme to use.
27 defaultScheme = "passthrough"
28)
29
30// TODO(bar) install dns resolver in init(){}.
31
32// Register registers the resolver builder to the resolver map. b.Scheme will be
33// used as the scheme registered with this builder.
34//
35// NOTE: this function must only be called during initialization time (i.e. in
36// an init() function), and is not thread-safe. If multiple Resolvers are
37// registered with the same name, the one registered last will take effect.
38func Register(b Builder) {
39 m[b.Scheme()] = b
40}
41
42// Get returns the resolver builder registered with the given scheme.
43//
44// If no builder is register with the scheme, nil will be returned.
45func Get(scheme string) Builder {
46 if b, ok := m[scheme]; ok {
47 return b
48 }
49 return nil
50}
51
52// SetDefaultScheme sets the default scheme that will be used. The default
53// default scheme is "passthrough".
54//
55// NOTE: this function must only be called during initialization time (i.e. in
56// an init() function), and is not thread-safe. The scheme set last overrides
57// previously set values.
58func SetDefaultScheme(scheme string) {
59 defaultScheme = scheme
60}
61
62// GetDefaultScheme gets the default scheme that will be used.
63func GetDefaultScheme() string {
64 return defaultScheme
65}
66
67// AddressType indicates the address type returned by name resolution.
68type AddressType uint8
69
70const (
71 // Backend indicates the address is for a backend server.
72 Backend AddressType = iota
73 // GRPCLB indicates the address is for a grpclb load balancer.
74 GRPCLB
75)
76
77// Address represents a server the client connects to.
78// This is the EXPERIMENTAL API and may be changed or extended in the future.
79type Address struct {
80 // Addr is the server address on which a connection will be established.
81 Addr string
82 // Type is the type of this address.
83 Type AddressType
84 // ServerName is the name of this address.
85 //
86 // e.g. if Type is GRPCLB, ServerName should be the name of the remote load
87 // balancer, not the name of the backend.
88 ServerName string
89 // Metadata is the information associated with Addr, which may be used
90 // to make load balancing decision.
91 Metadata interface{}
92}
93
94// BuildOption includes additional information for the builder to create
95// the resolver.
96type BuildOption struct {
97 // DisableServiceConfig indicates whether resolver should fetch service config data.
98 DisableServiceConfig bool
99}
100
101// ClientConn contains the callbacks for resolver to notify any updates
102// to the gRPC ClientConn.
103//
104// This interface is to be implemented by gRPC. Users should not need a
105// brand new implementation of this interface. For the situations like
106// testing, the new implementation should embed this interface. This allows
107// gRPC to add new methods to this interface.
108type ClientConn interface {
109 // NewAddress is called by resolver to notify ClientConn a new list
110 // of resolved addresses.
111 // The address list should be the complete list of resolved addresses.
112 NewAddress(addresses []Address)
113 // NewServiceConfig is called by resolver to notify ClientConn a new
114 // service config. The service config should be provided as a json string.
115 NewServiceConfig(serviceConfig string)
116}
117
118// Target represents a target for gRPC, as specified in:
119// https://github.com/grpc/grpc/blob/master/doc/naming.md.
120type Target struct {
121 Scheme string
122 Authority string
123 Endpoint string
124}
125
126// Builder creates a resolver that will be used to watch name resolution updates.
127type Builder interface {
128 // Build creates a new resolver for the given target.
129 //
130 // gRPC dial calls Build synchronously, and fails if the returned error is
131 // not nil.
132 Build(target Target, cc ClientConn, opts BuildOption) (Resolver, error)
133 // Scheme returns the scheme supported by this resolver.
134 // Scheme is defined at https://github.com/grpc/grpc/blob/master/doc/naming.md.
135 Scheme() string
136}
137
138// ResolveNowOption includes additional information for ResolveNow.
139type ResolveNowOption struct{}
140
141// Resolver watches for the updates on the specified target.
142// Updates include address updates and service config updates.
143type Resolver interface {
144 // ResolveNow will be called by gRPC to try to resolve the target name
145 // again. It's just a hint, resolver can ignore this if it's not necessary.
146 //
147 // It could be called multiple times concurrently.
148 ResolveNow(ResolveNowOption)
149 // Close closes the resolver.
150 Close()
151}
152
153// UnregisterForTesting removes the resolver builder with the given scheme from the
154// resolver map.
155// This function is for testing only.
156func UnregisterForTesting(scheme string) {
157 delete(m, scheme)
158}
diff --git a/vendor/google.golang.org/grpc/resolver_conn_wrapper.go b/vendor/google.golang.org/grpc/resolver_conn_wrapper.go
new file mode 100644
index 0000000..50991ea
--- /dev/null
+++ b/vendor/google.golang.org/grpc/resolver_conn_wrapper.go
@@ -0,0 +1,155 @@
1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package grpc
20
21import (
22 "fmt"
23 "strings"
24
25 "google.golang.org/grpc/grpclog"
26 "google.golang.org/grpc/internal/channelz"
27 "google.golang.org/grpc/resolver"
28)
29
30// ccResolverWrapper is a wrapper on top of cc for resolvers.
31// It implements resolver.ClientConnection interface.
32type ccResolverWrapper struct {
33 cc *ClientConn
34 resolver resolver.Resolver
35 addrCh chan []resolver.Address
36 scCh chan string
37 done chan struct{}
38 lastAddressesCount int
39}
40
41// split2 returns the values from strings.SplitN(s, sep, 2).
42// If sep is not found, it returns ("", "", false) instead.
43func split2(s, sep string) (string, string, bool) {
44 spl := strings.SplitN(s, sep, 2)
45 if len(spl) < 2 {
46 return "", "", false
47 }
48 return spl[0], spl[1], true
49}
50
51// parseTarget splits target into a struct containing scheme, authority and
52// endpoint.
53//
54// If target is not a valid scheme://authority/endpoint, it returns {Endpoint:
55// target}.
56func parseTarget(target string) (ret resolver.Target) {
57 var ok bool
58 ret.Scheme, ret.Endpoint, ok = split2(target, "://")
59 if !ok {
60 return resolver.Target{Endpoint: target}
61 }
62 ret.Authority, ret.Endpoint, ok = split2(ret.Endpoint, "/")
63 if !ok {
64 return resolver.Target{Endpoint: target}
65 }
66 return ret
67}
68
69// newCCResolverWrapper parses cc.target for scheme and gets the resolver
70// builder for this scheme and builds the resolver. The monitoring goroutine
71// for it is not started yet and can be created by calling start().
72//
73// If withResolverBuilder dial option is set, the specified resolver will be
74// used instead.
75func newCCResolverWrapper(cc *ClientConn) (*ccResolverWrapper, error) {
76 rb := cc.dopts.resolverBuilder
77 if rb == nil {
78 return nil, fmt.Errorf("could not get resolver for scheme: %q", cc.parsedTarget.Scheme)
79 }
80
81 ccr := &ccResolverWrapper{
82 cc: cc,
83 addrCh: make(chan []resolver.Address, 1),
84 scCh: make(chan string, 1),
85 done: make(chan struct{}),
86 }
87
88 var err error
89 ccr.resolver, err = rb.Build(cc.parsedTarget, ccr, resolver.BuildOption{DisableServiceConfig: cc.dopts.disableServiceConfig})
90 if err != nil {
91 return nil, err
92 }
93 return ccr, nil
94}
95
96func (ccr *ccResolverWrapper) resolveNow(o resolver.ResolveNowOption) {
97 ccr.resolver.ResolveNow(o)
98}
99
100func (ccr *ccResolverWrapper) close() {
101 ccr.resolver.Close()
102 close(ccr.done)
103}
104
105// NewAddress is called by the resolver implemenetion to send addresses to gRPC.
106func (ccr *ccResolverWrapper) NewAddress(addrs []resolver.Address) {
107 select {
108 case <-ccr.done:
109 return
110 default:
111 }
112 grpclog.Infof("ccResolverWrapper: sending new addresses to cc: %v", addrs)
113 if channelz.IsOn() {
114 ccr.addChannelzTraceEvent(addrs)
115 }
116 ccr.cc.handleResolvedAddrs(addrs, nil)
117}
118
119// NewServiceConfig is called by the resolver implemenetion to send service
120// configs to gRPC.
121func (ccr *ccResolverWrapper) NewServiceConfig(sc string) {
122 select {
123 case <-ccr.done:
124 return
125 default:
126 }
127 grpclog.Infof("ccResolverWrapper: got new service config: %v", sc)
128 ccr.cc.handleServiceConfig(sc)
129}
130
131func (ccr *ccResolverWrapper) addChannelzTraceEvent(addrs []resolver.Address) {
132 if len(addrs) == 0 && ccr.lastAddressesCount != 0 {
133 channelz.AddTraceEvent(ccr.cc.channelzID, &channelz.TraceEventDesc{
134 Desc: "Resolver returns an empty address list",
135 Severity: channelz.CtWarning,
136 })
137 } else if len(addrs) != 0 && ccr.lastAddressesCount == 0 {
138 var s string
139 for i, a := range addrs {
140 if a.ServerName != "" {
141 s += a.Addr + "(" + a.ServerName + ")"
142 } else {
143 s += a.Addr
144 }
145 if i != len(addrs)-1 {
146 s += " "
147 }
148 }
149 channelz.AddTraceEvent(ccr.cc.channelzID, &channelz.TraceEventDesc{
150 Desc: fmt.Sprintf("Resolver returns a non-empty address list (previous one was empty) %q", s),
151 Severity: channelz.CtINFO,
152 })
153 }
154 ccr.lastAddressesCount = len(addrs)
155}
diff --git a/vendor/google.golang.org/grpc/rpc_util.go b/vendor/google.golang.org/grpc/rpc_util.go
index 9b9d388..8d0d3dc 100644
--- a/vendor/google.golang.org/grpc/rpc_util.go
+++ b/vendor/google.golang.org/grpc/rpc_util.go
@@ -21,24 +21,31 @@ package grpc
21import ( 21import (
22 "bytes" 22 "bytes"
23 "compress/gzip" 23 "compress/gzip"
24 "context"
24 "encoding/binary" 25 "encoding/binary"
26 "fmt"
25 "io" 27 "io"
26 "io/ioutil" 28 "io/ioutil"
27 "math" 29 "math"
30 "net/url"
31 "strings"
28 "sync" 32 "sync"
29 "time" 33 "time"
30 34
31 "golang.org/x/net/context"
32 "google.golang.org/grpc/codes" 35 "google.golang.org/grpc/codes"
33 "google.golang.org/grpc/credentials" 36 "google.golang.org/grpc/credentials"
37 "google.golang.org/grpc/encoding"
38 "google.golang.org/grpc/encoding/proto"
39 "google.golang.org/grpc/internal/transport"
34 "google.golang.org/grpc/metadata" 40 "google.golang.org/grpc/metadata"
35 "google.golang.org/grpc/peer" 41 "google.golang.org/grpc/peer"
36 "google.golang.org/grpc/stats" 42 "google.golang.org/grpc/stats"
37 "google.golang.org/grpc/status" 43 "google.golang.org/grpc/status"
38 "google.golang.org/grpc/transport"
39) 44)
40 45
41// Compressor defines the interface gRPC uses to compress a message. 46// Compressor defines the interface gRPC uses to compress a message.
47//
48// Deprecated: use package encoding.
42type Compressor interface { 49type Compressor interface {
43 // Do compresses p into w. 50 // Do compresses p into w.
44 Do(w io.Writer, p []byte) error 51 Do(w io.Writer, p []byte) error
@@ -51,18 +58,39 @@ type gzipCompressor struct {
51} 58}
52 59
53// NewGZIPCompressor creates a Compressor based on GZIP. 60// NewGZIPCompressor creates a Compressor based on GZIP.
61//
62// Deprecated: use package encoding/gzip.
54func NewGZIPCompressor() Compressor { 63func NewGZIPCompressor() Compressor {
64 c, _ := NewGZIPCompressorWithLevel(gzip.DefaultCompression)
65 return c
66}
67
68// NewGZIPCompressorWithLevel is like NewGZIPCompressor but specifies the gzip compression level instead
69// of assuming DefaultCompression.
70//
71// The error returned will be nil if the level is valid.
72//
73// Deprecated: use package encoding/gzip.
74func NewGZIPCompressorWithLevel(level int) (Compressor, error) {
75 if level < gzip.DefaultCompression || level > gzip.BestCompression {
76 return nil, fmt.Errorf("grpc: invalid compression level: %d", level)
77 }
55 return &gzipCompressor{ 78 return &gzipCompressor{
56 pool: sync.Pool{ 79 pool: sync.Pool{
57 New: func() interface{} { 80 New: func() interface{} {
58 return gzip.NewWriter(ioutil.Discard) 81 w, err := gzip.NewWriterLevel(ioutil.Discard, level)
82 if err != nil {
83 panic(err)
84 }
85 return w
59 }, 86 },
60 }, 87 },
61 } 88 }, nil
62} 89}
63 90
64func (c *gzipCompressor) Do(w io.Writer, p []byte) error { 91func (c *gzipCompressor) Do(w io.Writer, p []byte) error {
65 z := c.pool.Get().(*gzip.Writer) 92 z := c.pool.Get().(*gzip.Writer)
93 defer c.pool.Put(z)
66 z.Reset(w) 94 z.Reset(w)
67 if _, err := z.Write(p); err != nil { 95 if _, err := z.Write(p); err != nil {
68 return err 96 return err
@@ -75,6 +103,8 @@ func (c *gzipCompressor) Type() string {
75} 103}
76 104
77// Decompressor defines the interface gRPC uses to decompress a message. 105// Decompressor defines the interface gRPC uses to decompress a message.
106//
107// Deprecated: use package encoding.
78type Decompressor interface { 108type Decompressor interface {
79 // Do reads the data from r and uncompress them. 109 // Do reads the data from r and uncompress them.
80 Do(r io.Reader) ([]byte, error) 110 Do(r io.Reader) ([]byte, error)
@@ -87,6 +117,8 @@ type gzipDecompressor struct {
87} 117}
88 118
89// NewGZIPDecompressor creates a Decompressor based on GZIP. 119// NewGZIPDecompressor creates a Decompressor based on GZIP.
120//
121// Deprecated: use package encoding/gzip.
90func NewGZIPDecompressor() Decompressor { 122func NewGZIPDecompressor() Decompressor {
91 return &gzipDecompressor{} 123 return &gzipDecompressor{}
92} 124}
@@ -121,17 +153,23 @@ func (d *gzipDecompressor) Type() string {
121 153
122// callInfo contains all related configuration and information about an RPC. 154// callInfo contains all related configuration and information about an RPC.
123type callInfo struct { 155type callInfo struct {
156 compressorType string
124 failFast bool 157 failFast bool
125 headerMD metadata.MD 158 stream ClientStream
126 trailerMD metadata.MD
127 peer *peer.Peer
128 traceInfo traceInfo // in trace.go
129 maxReceiveMessageSize *int 159 maxReceiveMessageSize *int
130 maxSendMessageSize *int 160 maxSendMessageSize *int
131 creds credentials.PerRPCCredentials 161 creds credentials.PerRPCCredentials
162 contentSubtype string
163 codec baseCodec
164 maxRetryRPCBufferSize int
132} 165}
133 166
134var defaultCallInfo = callInfo{failFast: true} 167func defaultCallInfo() *callInfo {
168 return &callInfo{
169 failFast: true,
170 maxRetryRPCBufferSize: 256 * 1024, // 256KB
171 }
172}
135 173
136// CallOption configures a Call before it starts or extracts information from 174// CallOption configures a Call before it starts or extracts information from
137// a Call after it completes. 175// a Call after it completes.
@@ -153,87 +191,267 @@ type EmptyCallOption struct{}
153func (EmptyCallOption) before(*callInfo) error { return nil } 191func (EmptyCallOption) before(*callInfo) error { return nil }
154func (EmptyCallOption) after(*callInfo) {} 192func (EmptyCallOption) after(*callInfo) {}
155 193
156type beforeCall func(c *callInfo) error
157
158func (o beforeCall) before(c *callInfo) error { return o(c) }
159func (o beforeCall) after(c *callInfo) {}
160
161type afterCall func(c *callInfo)
162
163func (o afterCall) before(c *callInfo) error { return nil }
164func (o afterCall) after(c *callInfo) { o(c) }
165
166// Header returns a CallOptions that retrieves the header metadata 194// Header returns a CallOptions that retrieves the header metadata
167// for a unary RPC. 195// for a unary RPC.
168func Header(md *metadata.MD) CallOption { 196func Header(md *metadata.MD) CallOption {
169 return afterCall(func(c *callInfo) { 197 return HeaderCallOption{HeaderAddr: md}
170 *md = c.headerMD 198}
171 }) 199
200// HeaderCallOption is a CallOption for collecting response header metadata.
201// The metadata field will be populated *after* the RPC completes.
202// This is an EXPERIMENTAL API.
203type HeaderCallOption struct {
204 HeaderAddr *metadata.MD
205}
206
207func (o HeaderCallOption) before(c *callInfo) error { return nil }
208func (o HeaderCallOption) after(c *callInfo) {
209 if c.stream != nil {
210 *o.HeaderAddr, _ = c.stream.Header()
211 }
172} 212}
173 213
174// Trailer returns a CallOptions that retrieves the trailer metadata 214// Trailer returns a CallOptions that retrieves the trailer metadata
175// for a unary RPC. 215// for a unary RPC.
176func Trailer(md *metadata.MD) CallOption { 216func Trailer(md *metadata.MD) CallOption {
177 return afterCall(func(c *callInfo) { 217 return TrailerCallOption{TrailerAddr: md}
178 *md = c.trailerMD 218}
179 }) 219
220// TrailerCallOption is a CallOption for collecting response trailer metadata.
221// The metadata field will be populated *after* the RPC completes.
222// This is an EXPERIMENTAL API.
223type TrailerCallOption struct {
224 TrailerAddr *metadata.MD
225}
226
227func (o TrailerCallOption) before(c *callInfo) error { return nil }
228func (o TrailerCallOption) after(c *callInfo) {
229 if c.stream != nil {
230 *o.TrailerAddr = c.stream.Trailer()
231 }
232}
233
234// Peer returns a CallOption that retrieves peer information for a unary RPC.
235// The peer field will be populated *after* the RPC completes.
236func Peer(p *peer.Peer) CallOption {
237 return PeerCallOption{PeerAddr: p}
180} 238}
181 239
182// Peer returns a CallOption that retrieves peer information for a 240// PeerCallOption is a CallOption for collecting the identity of the remote
183// unary RPC. 241// peer. The peer field will be populated *after* the RPC completes.
184func Peer(peer *peer.Peer) CallOption { 242// This is an EXPERIMENTAL API.
185 return afterCall(func(c *callInfo) { 243type PeerCallOption struct {
186 if c.peer != nil { 244 PeerAddr *peer.Peer
187 *peer = *c.peer 245}
246
247func (o PeerCallOption) before(c *callInfo) error { return nil }
248func (o PeerCallOption) after(c *callInfo) {
249 if c.stream != nil {
250 if x, ok := peer.FromContext(c.stream.Context()); ok {
251 *o.PeerAddr = *x
188 } 252 }
189 }) 253 }
190} 254}
191 255
192// FailFast configures the action to take when an RPC is attempted on broken 256// WaitForReady configures the action to take when an RPC is attempted on broken
193// connections or unreachable servers. If failfast is true, the RPC will fail 257// connections or unreachable servers. If waitForReady is false, the RPC will fail
194// immediately. Otherwise, the RPC client will block the call until a 258// immediately. Otherwise, the RPC client will block the call until a
195// connection is available (or the call is canceled or times out) and will retry 259// connection is available (or the call is canceled or times out) and will
196// the call if it fails due to a transient error. Please refer to 260// retry the call if it fails due to a transient error. gRPC will not retry if
261// data was written to the wire unless the server indicates it did not process
262// the data. Please refer to
197// https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md. 263// https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md.
198// Note: failFast is default to true. 264//
265// By default, RPCs don't "wait for ready".
266func WaitForReady(waitForReady bool) CallOption {
267 return FailFastCallOption{FailFast: !waitForReady}
268}
269
270// FailFast is the opposite of WaitForReady.
271//
272// Deprecated: use WaitForReady.
199func FailFast(failFast bool) CallOption { 273func FailFast(failFast bool) CallOption {
200 return beforeCall(func(c *callInfo) error { 274 return FailFastCallOption{FailFast: failFast}
201 c.failFast = failFast
202 return nil
203 })
204} 275}
205 276
277// FailFastCallOption is a CallOption for indicating whether an RPC should fail
278// fast or not.
279// This is an EXPERIMENTAL API.
280type FailFastCallOption struct {
281 FailFast bool
282}
283
284func (o FailFastCallOption) before(c *callInfo) error {
285 c.failFast = o.FailFast
286 return nil
287}
288func (o FailFastCallOption) after(c *callInfo) {}
289
206// MaxCallRecvMsgSize returns a CallOption which sets the maximum message size the client can receive. 290// MaxCallRecvMsgSize returns a CallOption which sets the maximum message size the client can receive.
207func MaxCallRecvMsgSize(s int) CallOption { 291func MaxCallRecvMsgSize(s int) CallOption {
208 return beforeCall(func(o *callInfo) error { 292 return MaxRecvMsgSizeCallOption{MaxRecvMsgSize: s}
209 o.maxReceiveMessageSize = &s 293}
210 return nil 294
211 }) 295// MaxRecvMsgSizeCallOption is a CallOption that indicates the maximum message
296// size the client can receive.
297// This is an EXPERIMENTAL API.
298type MaxRecvMsgSizeCallOption struct {
299 MaxRecvMsgSize int
212} 300}
213 301
302func (o MaxRecvMsgSizeCallOption) before(c *callInfo) error {
303 c.maxReceiveMessageSize = &o.MaxRecvMsgSize
304 return nil
305}
306func (o MaxRecvMsgSizeCallOption) after(c *callInfo) {}
307
214// MaxCallSendMsgSize returns a CallOption which sets the maximum message size the client can send. 308// MaxCallSendMsgSize returns a CallOption which sets the maximum message size the client can send.
215func MaxCallSendMsgSize(s int) CallOption { 309func MaxCallSendMsgSize(s int) CallOption {
216 return beforeCall(func(o *callInfo) error { 310 return MaxSendMsgSizeCallOption{MaxSendMsgSize: s}
217 o.maxSendMessageSize = &s 311}
218 return nil 312
219 }) 313// MaxSendMsgSizeCallOption is a CallOption that indicates the maximum message
314// size the client can send.
315// This is an EXPERIMENTAL API.
316type MaxSendMsgSizeCallOption struct {
317 MaxSendMsgSize int
220} 318}
221 319
320func (o MaxSendMsgSizeCallOption) before(c *callInfo) error {
321 c.maxSendMessageSize = &o.MaxSendMsgSize
322 return nil
323}
324func (o MaxSendMsgSizeCallOption) after(c *callInfo) {}
325
222// PerRPCCredentials returns a CallOption that sets credentials.PerRPCCredentials 326// PerRPCCredentials returns a CallOption that sets credentials.PerRPCCredentials
223// for a call. 327// for a call.
224func PerRPCCredentials(creds credentials.PerRPCCredentials) CallOption { 328func PerRPCCredentials(creds credentials.PerRPCCredentials) CallOption {
225 return beforeCall(func(c *callInfo) error { 329 return PerRPCCredsCallOption{Creds: creds}
226 c.creds = creds 330}
227 return nil 331
228 }) 332// PerRPCCredsCallOption is a CallOption that indicates the per-RPC
333// credentials to use for the call.
334// This is an EXPERIMENTAL API.
335type PerRPCCredsCallOption struct {
336 Creds credentials.PerRPCCredentials
337}
338
339func (o PerRPCCredsCallOption) before(c *callInfo) error {
340 c.creds = o.Creds
341 return nil
342}
343func (o PerRPCCredsCallOption) after(c *callInfo) {}
344
345// UseCompressor returns a CallOption which sets the compressor used when
346// sending the request. If WithCompressor is also set, UseCompressor has
347// higher priority.
348//
349// This API is EXPERIMENTAL.
350func UseCompressor(name string) CallOption {
351 return CompressorCallOption{CompressorType: name}
352}
353
354// CompressorCallOption is a CallOption that indicates the compressor to use.
355// This is an EXPERIMENTAL API.
356type CompressorCallOption struct {
357 CompressorType string
358}
359
360func (o CompressorCallOption) before(c *callInfo) error {
361 c.compressorType = o.CompressorType
362 return nil
363}
364func (o CompressorCallOption) after(c *callInfo) {}
365
366// CallContentSubtype returns a CallOption that will set the content-subtype
367// for a call. For example, if content-subtype is "json", the Content-Type over
368// the wire will be "application/grpc+json". The content-subtype is converted
369// to lowercase before being included in Content-Type. See Content-Type on
370// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
371// more details.
372//
373// If CallCustomCodec is not also used, the content-subtype will be used to
374// look up the Codec to use in the registry controlled by RegisterCodec. See
375// the documentation on RegisterCodec for details on registration. The lookup
376// of content-subtype is case-insensitive. If no such Codec is found, the call
377// will result in an error with code codes.Internal.
378//
379// If CallCustomCodec is also used, that Codec will be used for all request and
380// response messages, with the content-subtype set to the given contentSubtype
381// here for requests.
382func CallContentSubtype(contentSubtype string) CallOption {
383 return ContentSubtypeCallOption{ContentSubtype: strings.ToLower(contentSubtype)}
384}
385
386// ContentSubtypeCallOption is a CallOption that indicates the content-subtype
387// used for marshaling messages.
388// This is an EXPERIMENTAL API.
389type ContentSubtypeCallOption struct {
390 ContentSubtype string
391}
392
393func (o ContentSubtypeCallOption) before(c *callInfo) error {
394 c.contentSubtype = o.ContentSubtype
395 return nil
396}
397func (o ContentSubtypeCallOption) after(c *callInfo) {}
398
399// CallCustomCodec returns a CallOption that will set the given Codec to be
400// used for all request and response messages for a call. The result of calling
401// String() will be used as the content-subtype in a case-insensitive manner.
402//
403// See Content-Type on
404// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
405// more details. Also see the documentation on RegisterCodec and
406// CallContentSubtype for more details on the interaction between Codec and
407// content-subtype.
408//
409// This function is provided for advanced users; prefer to use only
410// CallContentSubtype to select a registered codec instead.
411func CallCustomCodec(codec Codec) CallOption {
412 return CustomCodecCallOption{Codec: codec}
413}
414
415// CustomCodecCallOption is a CallOption that indicates the codec used for
416// marshaling messages.
417// This is an EXPERIMENTAL API.
418type CustomCodecCallOption struct {
419 Codec Codec
420}
421
422func (o CustomCodecCallOption) before(c *callInfo) error {
423 c.codec = o.Codec
424 return nil
425}
426func (o CustomCodecCallOption) after(c *callInfo) {}
427
428// MaxRetryRPCBufferSize returns a CallOption that limits the amount of memory
429// used for buffering this RPC's requests for retry purposes.
430//
431// This API is EXPERIMENTAL.
432func MaxRetryRPCBufferSize(bytes int) CallOption {
433 return MaxRetryRPCBufferSizeCallOption{bytes}
434}
435
436// MaxRetryRPCBufferSizeCallOption is a CallOption indicating the amount of
437// memory to be used for caching this RPC for retry purposes.
438// This is an EXPERIMENTAL API.
439type MaxRetryRPCBufferSizeCallOption struct {
440 MaxRetryRPCBufferSize int
441}
442
443func (o MaxRetryRPCBufferSizeCallOption) before(c *callInfo) error {
444 c.maxRetryRPCBufferSize = o.MaxRetryRPCBufferSize
445 return nil
229} 446}
447func (o MaxRetryRPCBufferSizeCallOption) after(c *callInfo) {}
230 448
231// The format of the payload: compressed or not? 449// The format of the payload: compressed or not?
232type payloadFormat uint8 450type payloadFormat uint8
233 451
234const ( 452const (
235 compressionNone payloadFormat = iota // no compression 453 compressionNone payloadFormat = 0 // no compression
236 compressionMade 454 compressionMade payloadFormat = 1 // compressed
237) 455)
238 456
239// parser reads complete gRPC messages from the underlying reader. 457// parser reads complete gRPC messages from the underlying reader.
@@ -243,8 +461,8 @@ type parser struct {
243 // error types. 461 // error types.
244 r io.Reader 462 r io.Reader
245 463
246 // The header of a gRPC message. Find more detail 464 // The header of a gRPC message. Find more detail at
247 // at https://grpc.io/docs/guides/wire.html. 465 // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md
248 header [5]byte 466 header [5]byte
249} 467}
250 468
@@ -257,7 +475,7 @@ type parser struct {
257// * io.EOF, when no messages remain 475// * io.EOF, when no messages remain
258// * io.ErrUnexpectedEOF 476// * io.ErrUnexpectedEOF
259// * of type transport.ConnectionError 477// * of type transport.ConnectionError
260// * of type transport.StreamError 478// * an error from the status package
261// No other error values or types must be returned, which also means 479// No other error values or types must be returned, which also means
262// that the underlying io.Reader must not return an incompatible 480// that the underlying io.Reader must not return an incompatible
263// error. 481// error.
@@ -272,8 +490,11 @@ func (p *parser) recvMsg(maxReceiveMessageSize int) (pf payloadFormat, msg []byt
272 if length == 0 { 490 if length == 0 {
273 return pf, nil, nil 491 return pf, nil, nil
274 } 492 }
275 if length > uint32(maxReceiveMessageSize) { 493 if int64(length) > int64(maxInt) {
276 return 0, nil, Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", length, maxReceiveMessageSize) 494 return 0, nil, status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max length allowed on current machine (%d vs. %d)", length, maxInt)
495 }
496 if int(length) > maxReceiveMessageSize {
497 return 0, nil, status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", length, maxReceiveMessageSize)
277 } 498 }
278 // TODO(bradfitz,zhaoq): garbage. reuse buffer after proto decoding instead 499 // TODO(bradfitz,zhaoq): garbage. reuse buffer after proto decoding instead
279 // of making it for each message: 500 // of making it for each message:
@@ -287,120 +508,173 @@ func (p *parser) recvMsg(maxReceiveMessageSize int) (pf payloadFormat, msg []byt
287 return pf, msg, nil 508 return pf, msg, nil
288} 509}
289 510
290// encode serializes msg and prepends the message header. If msg is nil, it 511// encode serializes msg and returns a buffer containing the message, or an
291// generates the message header of 0 message length. 512// error if it is too large to be transmitted by grpc. If msg is nil, it
292func encode(c Codec, msg interface{}, cp Compressor, cbuf *bytes.Buffer, outPayload *stats.OutPayload) ([]byte, error) { 513// generates an empty message.
293 var ( 514func encode(c baseCodec, msg interface{}) ([]byte, error) {
294 b []byte 515 if msg == nil { // NOTE: typed nils will not be caught by this check
295 length uint 516 return nil, nil
296 ) 517 }
297 if msg != nil { 518 b, err := c.Marshal(msg)
298 var err error 519 if err != nil {
299 // TODO(zhaoq): optimize to reduce memory alloc and copying. 520 return nil, status.Errorf(codes.Internal, "grpc: error while marshaling: %v", err.Error())
300 b, err = c.Marshal(msg) 521 }
522 if uint(len(b)) > math.MaxUint32 {
523 return nil, status.Errorf(codes.ResourceExhausted, "grpc: message too large (%d bytes)", len(b))
524 }
525 return b, nil
526}
527
528// compress returns the input bytes compressed by compressor or cp. If both
529// compressors are nil, returns nil.
530//
531// TODO(dfawley): eliminate cp parameter by wrapping Compressor in an encoding.Compressor.
532func compress(in []byte, cp Compressor, compressor encoding.Compressor) ([]byte, error) {
533 if compressor == nil && cp == nil {
534 return nil, nil
535 }
536 wrapErr := func(err error) error {
537 return status.Errorf(codes.Internal, "grpc: error while compressing: %v", err.Error())
538 }
539 cbuf := &bytes.Buffer{}
540 if compressor != nil {
541 z, err := compressor.Compress(cbuf)
301 if err != nil { 542 if err != nil {
302 return nil, Errorf(codes.Internal, "grpc: error while marshaling: %v", err.Error()) 543 return nil, wrapErr(err)
303 } 544 }
304 if outPayload != nil { 545 if _, err := z.Write(in); err != nil {
305 outPayload.Payload = msg 546 return nil, wrapErr(err)
306 // TODO truncate large payload.
307 outPayload.Data = b
308 outPayload.Length = len(b)
309 } 547 }
310 if cp != nil { 548 if err := z.Close(); err != nil {
311 if err := cp.Do(cbuf, b); err != nil { 549 return nil, wrapErr(err)
312 return nil, Errorf(codes.Internal, "grpc: error while compressing: %v", err.Error()) 550 }
313 } 551 } else {
314 b = cbuf.Bytes() 552 if err := cp.Do(cbuf, in); err != nil {
553 return nil, wrapErr(err)
315 } 554 }
316 length = uint(len(b))
317 }
318 if length > math.MaxUint32 {
319 return nil, Errorf(codes.ResourceExhausted, "grpc: message too large (%d bytes)", length)
320 } 555 }
556 return cbuf.Bytes(), nil
557}
321 558
322 const ( 559const (
323 payloadLen = 1 560 payloadLen = 1
324 sizeLen = 4 561 sizeLen = 4
325 ) 562 headerLen = payloadLen + sizeLen
326 563)
327 var buf = make([]byte, payloadLen+sizeLen+len(b))
328 564
329 // Write payload format 565// msgHeader returns a 5-byte header for the message being transmitted and the
330 if cp == nil { 566// payload, which is compData if non-nil or data otherwise.
331 buf[0] = byte(compressionNone) 567func msgHeader(data, compData []byte) (hdr []byte, payload []byte) {
568 hdr = make([]byte, headerLen)
569 if compData != nil {
570 hdr[0] = byte(compressionMade)
571 data = compData
332 } else { 572 } else {
333 buf[0] = byte(compressionMade) 573 hdr[0] = byte(compressionNone)
334 } 574 }
335 // Write length of b into buf
336 binary.BigEndian.PutUint32(buf[1:], uint32(length))
337 // Copy encoded msg to buf
338 copy(buf[5:], b)
339 575
340 if outPayload != nil { 576 // Write length of payload into buf
341 outPayload.WireLength = len(buf) 577 binary.BigEndian.PutUint32(hdr[payloadLen:], uint32(len(data)))
342 } 578 return hdr, data
579}
343 580
344 return buf, nil 581func outPayload(client bool, msg interface{}, data, payload []byte, t time.Time) *stats.OutPayload {
582 return &stats.OutPayload{
583 Client: client,
584 Payload: msg,
585 Data: data,
586 Length: len(data),
587 WireLength: len(payload) + headerLen,
588 SentTime: t,
589 }
345} 590}
346 591
347func checkRecvPayload(pf payloadFormat, recvCompress string, dc Decompressor) error { 592func checkRecvPayload(pf payloadFormat, recvCompress string, haveCompressor bool) *status.Status {
348 switch pf { 593 switch pf {
349 case compressionNone: 594 case compressionNone:
350 case compressionMade: 595 case compressionMade:
351 if dc == nil || recvCompress != dc.Type() { 596 if recvCompress == "" || recvCompress == encoding.Identity {
352 return Errorf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", recvCompress) 597 return status.New(codes.Internal, "grpc: compressed flag set with identity or empty encoding")
598 }
599 if !haveCompressor {
600 return status.Newf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", recvCompress)
353 } 601 }
354 default: 602 default:
355 return Errorf(codes.Internal, "grpc: received unexpected payload format %d", pf) 603 return status.Newf(codes.Internal, "grpc: received unexpected payload format %d", pf)
356 } 604 }
357 return nil 605 return nil
358} 606}
359 607
360func recv(p *parser, c Codec, s *transport.Stream, dc Decompressor, m interface{}, maxReceiveMessageSize int, inPayload *stats.InPayload) error { 608type payloadInfo struct {
609 wireLength int // The compressed length got from wire.
610 uncompressedBytes []byte
611}
612
613func recvAndDecompress(p *parser, s *transport.Stream, dc Decompressor, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor) ([]byte, error) {
361 pf, d, err := p.recvMsg(maxReceiveMessageSize) 614 pf, d, err := p.recvMsg(maxReceiveMessageSize)
362 if err != nil { 615 if err != nil {
363 return err 616 return nil, err
364 } 617 }
365 if inPayload != nil { 618 if payInfo != nil {
366 inPayload.WireLength = len(d) 619 payInfo.wireLength = len(d)
367 } 620 }
368 if err := checkRecvPayload(pf, s.RecvCompress(), dc); err != nil { 621
369 return err 622 if st := checkRecvPayload(pf, s.RecvCompress(), compressor != nil || dc != nil); st != nil {
623 return nil, st.Err()
370 } 624 }
625
371 if pf == compressionMade { 626 if pf == compressionMade {
372 d, err = dc.Do(bytes.NewReader(d)) 627 // To match legacy behavior, if the decompressor is set by WithDecompressor or RPCDecompressor,
373 if err != nil { 628 // use this decompressor as the default.
374 return Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err) 629 if dc != nil {
630 d, err = dc.Do(bytes.NewReader(d))
631 if err != nil {
632 return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err)
633 }
634 } else {
635 dcReader, err := compressor.Decompress(bytes.NewReader(d))
636 if err != nil {
637 return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err)
638 }
639 d, err = ioutil.ReadAll(dcReader)
640 if err != nil {
641 return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err)
642 }
375 } 643 }
376 } 644 }
377 if len(d) > maxReceiveMessageSize { 645 if len(d) > maxReceiveMessageSize {
378 // TODO: Revisit the error code. Currently keep it consistent with java 646 // TODO: Revisit the error code. Currently keep it consistent with java
379 // implementation. 647 // implementation.
380 return Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", len(d), maxReceiveMessageSize) 648 return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", len(d), maxReceiveMessageSize)
649 }
650 return d, nil
651}
652
653// For the two compressor parameters, both should not be set, but if they are,
654// dc takes precedence over compressor.
655// TODO(dfawley): wrap the old compressor/decompressor using the new API?
656func recv(p *parser, c baseCodec, s *transport.Stream, dc Decompressor, m interface{}, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor) error {
657 d, err := recvAndDecompress(p, s, dc, maxReceiveMessageSize, payInfo, compressor)
658 if err != nil {
659 return err
381 } 660 }
382 if err := c.Unmarshal(d, m); err != nil { 661 if err := c.Unmarshal(d, m); err != nil {
383 return Errorf(codes.Internal, "grpc: failed to unmarshal the received message %v", err) 662 return status.Errorf(codes.Internal, "grpc: failed to unmarshal the received message %v", err)
384 } 663 }
385 if inPayload != nil { 664 if payInfo != nil {
386 inPayload.RecvTime = time.Now() 665 payInfo.uncompressedBytes = d
387 inPayload.Payload = m
388 // TODO truncate large payload.
389 inPayload.Data = d
390 inPayload.Length = len(d)
391 } 666 }
392 return nil 667 return nil
393} 668}
394 669
395type rpcInfo struct { 670type rpcInfo struct {
396 bytesSent bool 671 failfast bool
397 bytesReceived bool
398} 672}
399 673
400type rpcInfoContextKey struct{} 674type rpcInfoContextKey struct{}
401 675
402func newContextWithRPCInfo(ctx context.Context) context.Context { 676func newContextWithRPCInfo(ctx context.Context, failfast bool) context.Context {
403 return context.WithValue(ctx, rpcInfoContextKey{}, &rpcInfo{}) 677 return context.WithValue(ctx, rpcInfoContextKey{}, &rpcInfo{failfast: failfast})
404} 678}
405 679
406func rpcInfoFromContext(ctx context.Context) (s *rpcInfo, ok bool) { 680func rpcInfoFromContext(ctx context.Context) (s *rpcInfo, ok bool) {
@@ -408,117 +682,135 @@ func rpcInfoFromContext(ctx context.Context) (s *rpcInfo, ok bool) {
408 return 682 return
409} 683}
410 684
411func updateRPCInfoInContext(ctx context.Context, s rpcInfo) {
412 if ss, ok := rpcInfoFromContext(ctx); ok {
413 *ss = s
414 }
415 return
416}
417
418// Code returns the error code for err if it was produced by the rpc system. 685// Code returns the error code for err if it was produced by the rpc system.
419// Otherwise, it returns codes.Unknown. 686// Otherwise, it returns codes.Unknown.
420// 687//
421// Deprecated; use status.FromError and Code method instead. 688// Deprecated: use status.Code instead.
422func Code(err error) codes.Code { 689func Code(err error) codes.Code {
423 if s, ok := status.FromError(err); ok { 690 return status.Code(err)
424 return s.Code()
425 }
426 return codes.Unknown
427} 691}
428 692
429// ErrorDesc returns the error description of err if it was produced by the rpc system. 693// ErrorDesc returns the error description of err if it was produced by the rpc system.
430// Otherwise, it returns err.Error() or empty string when err is nil. 694// Otherwise, it returns err.Error() or empty string when err is nil.
431// 695//
432// Deprecated; use status.FromError and Message method instead. 696// Deprecated: use status.Convert and Message method instead.
433func ErrorDesc(err error) string { 697func ErrorDesc(err error) string {
434 if s, ok := status.FromError(err); ok { 698 return status.Convert(err).Message()
435 return s.Message()
436 }
437 return err.Error()
438} 699}
439 700
440// Errorf returns an error containing an error code and a description; 701// Errorf returns an error containing an error code and a description;
441// Errorf returns nil if c is OK. 702// Errorf returns nil if c is OK.
442// 703//
443// Deprecated; use status.Errorf instead. 704// Deprecated: use status.Errorf instead.
444func Errorf(c codes.Code, format string, a ...interface{}) error { 705func Errorf(c codes.Code, format string, a ...interface{}) error {
445 return status.Errorf(c, format, a...) 706 return status.Errorf(c, format, a...)
446} 707}
447 708
448// MethodConfig defines the configuration recommended by the service providers for a 709// toRPCErr converts an error into an error from the status package.
449// particular method. 710func toRPCErr(err error) error {
450// This is EXPERIMENTAL and subject to change. 711 if err == nil || err == io.EOF {
451type MethodConfig struct { 712 return err
452 // WaitForReady indicates whether RPCs sent to this method should wait until 713 }
453 // the connection is ready by default (!failfast). The value specified via the 714 if err == io.ErrUnexpectedEOF {
454 // gRPC client API will override the value set here. 715 return status.Error(codes.Internal, err.Error())
455 WaitForReady *bool 716 }
456 // Timeout is the default timeout for RPCs sent to this method. The actual 717 if _, ok := status.FromError(err); ok {
457 // deadline used will be the minimum of the value specified here and the value 718 return err
458 // set by the application via the gRPC client API. If either one is not set, 719 }
459 // then the other will be used. If neither is set, then the RPC has no deadline. 720 switch e := err.(type) {
460 Timeout *time.Duration 721 case transport.ConnectionError:
461 // MaxReqSize is the maximum allowed payload size for an individual request in a 722 return status.Error(codes.Unavailable, e.Desc)
462 // stream (client->server) in bytes. The size which is measured is the serialized 723 default:
463 // payload after per-message compression (but before stream compression) in bytes. 724 switch err {
464 // The actual value used is the minumum of the value specified here and the value set 725 case context.DeadlineExceeded:
465 // by the application via the gRPC client API. If either one is not set, then the other 726 return status.Error(codes.DeadlineExceeded, err.Error())
466 // will be used. If neither is set, then the built-in default is used. 727 case context.Canceled:
467 MaxReqSize *int 728 return status.Error(codes.Canceled, err.Error())
468 // MaxRespSize is the maximum allowed payload size for an individual response in a 729 }
469 // stream (server->client) in bytes. 730 }
470 MaxRespSize *int 731 return status.Error(codes.Unknown, err.Error())
471} 732}
472
473// ServiceConfig is provided by the service provider and contains parameters for how
474// clients that connect to the service should behave.
475// This is EXPERIMENTAL and subject to change.
476type ServiceConfig struct {
477 // LB is the load balancer the service providers recommends. The balancer specified
478 // via grpc.WithBalancer will override this.
479 LB Balancer
480 // Methods contains a map for the methods in this service.
481 // If there is an exact match for a method (i.e. /service/method) in the map, use the corresponding MethodConfig.
482 // If there's no exact match, look for the default config for the service (/service/) and use the corresponding MethodConfig if it exists.
483 // Otherwise, the method has no MethodConfig to use.
484 Methods map[string]MethodConfig
485}
486
487func min(a, b *int) *int {
488 if *a < *b {
489 return a
490 }
491 return b
492}
493
494func getMaxSize(mcMax, doptMax *int, defaultVal int) *int {
495 if mcMax == nil && doptMax == nil {
496 return &defaultVal
497 }
498 if mcMax != nil && doptMax != nil {
499 return min(mcMax, doptMax)
500 }
501 if mcMax != nil {
502 return mcMax
503 }
504 return doptMax
505}
506
507// SupportPackageIsVersion3 is referenced from generated protocol buffer files.
508// The latest support package version is 4.
509// SupportPackageIsVersion3 is kept for compability. It will be removed in the
510// next support package version update.
511const SupportPackageIsVersion3 = true
512
513// SupportPackageIsVersion4 is referenced from generated protocol buffer files
514// to assert that that code is compatible with this version of the grpc package.
515//
516// This constant may be renamed in the future if a change in the generated code
517// requires a synchronised update of grpc-go and protoc-gen-go. This constant
518// should not be referenced from any other code.
519const SupportPackageIsVersion4 = true
520 733
521// Version is the current grpc version. 734// setCallInfoCodec should only be called after CallOptions have been applied.
522const Version = "1.6.0-dev" 735func setCallInfoCodec(c *callInfo) error {
736 if c.codec != nil {
737 // codec was already set by a CallOption; use it.
738 return nil
739 }
740
741 if c.contentSubtype == "" {
742 // No codec specified in CallOptions; use proto by default.
743 c.codec = encoding.GetCodec(proto.Name)
744 return nil
745 }
746
747 // c.contentSubtype is already lowercased in CallContentSubtype
748 c.codec = encoding.GetCodec(c.contentSubtype)
749 if c.codec == nil {
750 return status.Errorf(codes.Internal, "no codec registered for content-subtype %s", c.contentSubtype)
751 }
752 return nil
753}
754
755// parseDialTarget returns the network and address to pass to dialer
756func parseDialTarget(target string) (net string, addr string) {
757 net = "tcp"
758
759 m1 := strings.Index(target, ":")
760 m2 := strings.Index(target, ":/")
761
762 // handle unix:addr which will fail with url.Parse
763 if m1 >= 0 && m2 < 0 {
764 if n := target[0:m1]; n == "unix" {
765 net = n
766 addr = target[m1+1:]
767 return net, addr
768 }
769 }
770 if m2 >= 0 {
771 t, err := url.Parse(target)
772 if err != nil {
773 return net, target
774 }
775 scheme := t.Scheme
776 addr = t.Path
777 if scheme == "unix" {
778 net = scheme
779 if addr == "" {
780 addr = t.Host
781 }
782 return net, addr
783 }
784 }
785
786 return net, target
787}
788
789// channelzData is used to store channelz related data for ClientConn, addrConn and Server.
790// These fields cannot be embedded in the original structs (e.g. ClientConn), since to do atomic
791// operation on int64 variable on 32-bit machine, user is responsible to enforce memory alignment.
792// Here, by grouping those int64 fields inside a struct, we are enforcing the alignment.
793type channelzData struct {
794 callsStarted int64
795 callsFailed int64
796 callsSucceeded int64
797 // lastCallStartedTime stores the timestamp that last call starts. It is of int64 type instead of
798 // time.Time since it's more costly to atomically update time.Time variable than int64 variable.
799 lastCallStartedTime int64
800}
801
802// The SupportPackageIsVersion variables are referenced from generated protocol
803// buffer files to ensure compatibility with the gRPC version used. The latest
804// support package version is 5.
805//
806// Older versions are kept for compatibility. They may be removed if
807// compatibility cannot be maintained.
808//
809// These constants should not be referenced from any other code.
810const (
811 SupportPackageIsVersion3 = true
812 SupportPackageIsVersion4 = true
813 SupportPackageIsVersion5 = true
814)
523 815
524const grpcUA = "grpc-go/" + Version 816const grpcUA = "grpc-go/" + Version
diff --git a/vendor/google.golang.org/grpc/server.go b/vendor/google.golang.org/grpc/server.go
index 42733e2..d705d7a 100644
--- a/vendor/google.golang.org/grpc/server.go
+++ b/vendor/google.golang.org/grpc/server.go
@@ -19,36 +19,41 @@
19package grpc 19package grpc
20 20
21import ( 21import (
22 "bytes" 22 "context"
23 "errors" 23 "errors"
24 "fmt" 24 "fmt"
25 "io" 25 "io"
26 "math"
26 "net" 27 "net"
27 "net/http" 28 "net/http"
28 "reflect" 29 "reflect"
29 "runtime" 30 "runtime"
30 "strings" 31 "strings"
31 "sync" 32 "sync"
33 "sync/atomic"
32 "time" 34 "time"
33 35
34 "golang.org/x/net/context"
35 "golang.org/x/net/http2"
36 "golang.org/x/net/trace" 36 "golang.org/x/net/trace"
37
37 "google.golang.org/grpc/codes" 38 "google.golang.org/grpc/codes"
38 "google.golang.org/grpc/credentials" 39 "google.golang.org/grpc/credentials"
40 "google.golang.org/grpc/encoding"
41 "google.golang.org/grpc/encoding/proto"
39 "google.golang.org/grpc/grpclog" 42 "google.golang.org/grpc/grpclog"
40 "google.golang.org/grpc/internal" 43 "google.golang.org/grpc/internal/binarylog"
44 "google.golang.org/grpc/internal/channelz"
45 "google.golang.org/grpc/internal/transport"
41 "google.golang.org/grpc/keepalive" 46 "google.golang.org/grpc/keepalive"
42 "google.golang.org/grpc/metadata" 47 "google.golang.org/grpc/metadata"
48 "google.golang.org/grpc/peer"
43 "google.golang.org/grpc/stats" 49 "google.golang.org/grpc/stats"
44 "google.golang.org/grpc/status" 50 "google.golang.org/grpc/status"
45 "google.golang.org/grpc/tap" 51 "google.golang.org/grpc/tap"
46 "google.golang.org/grpc/transport"
47) 52)
48 53
49const ( 54const (
50 defaultServerMaxReceiveMessageSize = 1024 * 1024 * 4 55 defaultServerMaxReceiveMessageSize = 1024 * 1024 * 4
51 defaultServerMaxSendMessageSize = 1024 * 1024 * 4 56 defaultServerMaxSendMessageSize = math.MaxInt32
52) 57)
53 58
54type methodHandler func(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor UnaryServerInterceptor) (interface{}, error) 59type methodHandler func(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor UnaryServerInterceptor) (interface{}, error)
@@ -88,18 +93,24 @@ type Server struct {
88 conns map[io.Closer]bool 93 conns map[io.Closer]bool
89 serve bool 94 serve bool
90 drain bool 95 drain bool
91 ctx context.Context 96 cv *sync.Cond // signaled when connections close for GracefulStop
92 cancel context.CancelFunc
93 // A CondVar to let GracefulStop() blocks until all the pending RPCs are finished
94 // and all the transport goes away.
95 cv *sync.Cond
96 m map[string]*service // service name -> service info 97 m map[string]*service // service name -> service info
97 events trace.EventLog 98 events trace.EventLog
99
100 quit chan struct{}
101 done chan struct{}
102 quitOnce sync.Once
103 doneOnce sync.Once
104 channelzRemoveOnce sync.Once
105 serveWG sync.WaitGroup // counts active Serve goroutines for GracefulStop
106
107 channelzID int64 // channelz unique identification number
108 czData *channelzData
98} 109}
99 110
100type options struct { 111type options struct {
101 creds credentials.TransportCredentials 112 creds credentials.TransportCredentials
102 codec Codec 113 codec baseCodec
103 cp Compressor 114 cp Compressor
104 dc Decompressor 115 dc Decompressor
105 unaryInt UnaryServerInterceptor 116 unaryInt UnaryServerInterceptor
@@ -109,22 +120,50 @@ type options struct {
109 maxConcurrentStreams uint32 120 maxConcurrentStreams uint32
110 maxReceiveMessageSize int 121 maxReceiveMessageSize int
111 maxSendMessageSize int 122 maxSendMessageSize int
112 useHandlerImpl bool // use http.Handler-based server
113 unknownStreamDesc *StreamDesc 123 unknownStreamDesc *StreamDesc
114 keepaliveParams keepalive.ServerParameters 124 keepaliveParams keepalive.ServerParameters
115 keepalivePolicy keepalive.EnforcementPolicy 125 keepalivePolicy keepalive.EnforcementPolicy
116 initialWindowSize int32 126 initialWindowSize int32
117 initialConnWindowSize int32 127 initialConnWindowSize int32
128 writeBufferSize int
129 readBufferSize int
130 connectionTimeout time.Duration
131 maxHeaderListSize *uint32
118} 132}
119 133
120var defaultServerOptions = options{ 134var defaultServerOptions = options{
121 maxReceiveMessageSize: defaultServerMaxReceiveMessageSize, 135 maxReceiveMessageSize: defaultServerMaxReceiveMessageSize,
122 maxSendMessageSize: defaultServerMaxSendMessageSize, 136 maxSendMessageSize: defaultServerMaxSendMessageSize,
137 connectionTimeout: 120 * time.Second,
138 writeBufferSize: defaultWriteBufSize,
139 readBufferSize: defaultReadBufSize,
123} 140}
124 141
125// A ServerOption sets options such as credentials, codec and keepalive parameters, etc. 142// A ServerOption sets options such as credentials, codec and keepalive parameters, etc.
126type ServerOption func(*options) 143type ServerOption func(*options)
127 144
145// WriteBufferSize determines how much data can be batched before doing a write on the wire.
146// The corresponding memory allocation for this buffer will be twice the size to keep syscalls low.
147// The default value for this buffer is 32KB.
148// Zero will disable the write buffer such that each write will be on underlying connection.
149// Note: A Send call may not directly translate to a write.
150func WriteBufferSize(s int) ServerOption {
151 return func(o *options) {
152 o.writeBufferSize = s
153 }
154}
155
156// ReadBufferSize lets you set the size of read buffer, this determines how much data can be read at most
157// for one read syscall.
158// The default value for this buffer is 32KB.
159// Zero will disable read buffer for a connection so data framer can access the underlying
160// conn directly.
161func ReadBufferSize(s int) ServerOption {
162 return func(o *options) {
163 o.readBufferSize = s
164 }
165}
166
128// InitialWindowSize returns a ServerOption that sets window size for stream. 167// InitialWindowSize returns a ServerOption that sets window size for stream.
129// The lower bound for window size is 64K and any value smaller than that will be ignored. 168// The lower bound for window size is 64K and any value smaller than that will be ignored.
130func InitialWindowSize(s int32) ServerOption { 169func InitialWindowSize(s int32) ServerOption {
@@ -156,20 +195,32 @@ func KeepaliveEnforcementPolicy(kep keepalive.EnforcementPolicy) ServerOption {
156} 195}
157 196
158// CustomCodec returns a ServerOption that sets a codec for message marshaling and unmarshaling. 197// CustomCodec returns a ServerOption that sets a codec for message marshaling and unmarshaling.
198//
199// This will override any lookups by content-subtype for Codecs registered with RegisterCodec.
159func CustomCodec(codec Codec) ServerOption { 200func CustomCodec(codec Codec) ServerOption {
160 return func(o *options) { 201 return func(o *options) {
161 o.codec = codec 202 o.codec = codec
162 } 203 }
163} 204}
164 205
165// RPCCompressor returns a ServerOption that sets a compressor for outbound messages. 206// RPCCompressor returns a ServerOption that sets a compressor for outbound
207// messages. For backward compatibility, all outbound messages will be sent
208// using this compressor, regardless of incoming message compression. By
209// default, server messages will be sent using the same compressor with which
210// request messages were sent.
211//
212// Deprecated: use encoding.RegisterCompressor instead.
166func RPCCompressor(cp Compressor) ServerOption { 213func RPCCompressor(cp Compressor) ServerOption {
167 return func(o *options) { 214 return func(o *options) {
168 o.cp = cp 215 o.cp = cp
169 } 216 }
170} 217}
171 218
172// RPCDecompressor returns a ServerOption that sets a decompressor for inbound messages. 219// RPCDecompressor returns a ServerOption that sets a decompressor for inbound
220// messages. It has higher priority than decompressors registered via
221// encoding.RegisterCompressor.
222//
223// Deprecated: use encoding.RegisterCompressor instead.
173func RPCDecompressor(dc Decompressor) ServerOption { 224func RPCDecompressor(dc Decompressor) ServerOption {
174 return func(o *options) { 225 return func(o *options) {
175 o.dc = dc 226 o.dc = dc
@@ -177,7 +228,9 @@ func RPCDecompressor(dc Decompressor) ServerOption {
177} 228}
178 229
179// MaxMsgSize returns a ServerOption to set the max message size in bytes the server can receive. 230// MaxMsgSize returns a ServerOption to set the max message size in bytes the server can receive.
180// If this is not set, gRPC uses the default limit. Deprecated: use MaxRecvMsgSize instead. 231// If this is not set, gRPC uses the default limit.
232//
233// Deprecated: use MaxRecvMsgSize instead.
181func MaxMsgSize(m int) ServerOption { 234func MaxMsgSize(m int) ServerOption {
182 return MaxRecvMsgSize(m) 235 return MaxRecvMsgSize(m)
183} 236}
@@ -259,7 +312,7 @@ func StatsHandler(h stats.Handler) ServerOption {
259// handler that will be invoked instead of returning the "unimplemented" gRPC 312// handler that will be invoked instead of returning the "unimplemented" gRPC
260// error whenever a request is received for an unregistered service or method. 313// error whenever a request is received for an unregistered service or method.
261// The handling function has full access to the Context of the request and the 314// The handling function has full access to the Context of the request and the
262// stream, and the invocation passes through interceptors. 315// stream, and the invocation bypasses interceptors.
263func UnknownServiceHandler(streamHandler StreamHandler) ServerOption { 316func UnknownServiceHandler(streamHandler StreamHandler) ServerOption {
264 return func(o *options) { 317 return func(o *options) {
265 o.unknownStreamDesc = &StreamDesc{ 318 o.unknownStreamDesc = &StreamDesc{
@@ -272,6 +325,26 @@ func UnknownServiceHandler(streamHandler StreamHandler) ServerOption {
272 } 325 }
273} 326}
274 327
328// ConnectionTimeout returns a ServerOption that sets the timeout for
329// connection establishment (up to and including HTTP/2 handshaking) for all
330// new connections. If this is not set, the default is 120 seconds. A zero or
331// negative value will result in an immediate timeout.
332//
333// This API is EXPERIMENTAL.
334func ConnectionTimeout(d time.Duration) ServerOption {
335 return func(o *options) {
336 o.connectionTimeout = d
337 }
338}
339
340// MaxHeaderListSize returns a ServerOption that sets the max (uncompressed) size
341// of header list that the server is prepared to accept.
342func MaxHeaderListSize(s uint32) ServerOption {
343 return func(o *options) {
344 o.maxHeaderListSize = &s
345 }
346}
347
275// NewServer creates a gRPC server which has no service registered and has not 348// NewServer creates a gRPC server which has no service registered and has not
276// started to accept requests yet. 349// started to accept requests yet.
277func NewServer(opt ...ServerOption) *Server { 350func NewServer(opt ...ServerOption) *Server {
@@ -279,22 +352,24 @@ func NewServer(opt ...ServerOption) *Server {
279 for _, o := range opt { 352 for _, o := range opt {
280 o(&opts) 353 o(&opts)
281 } 354 }
282 if opts.codec == nil {
283 // Set the default codec.
284 opts.codec = protoCodec{}
285 }
286 s := &Server{ 355 s := &Server{
287 lis: make(map[net.Listener]bool), 356 lis: make(map[net.Listener]bool),
288 opts: opts, 357 opts: opts,
289 conns: make(map[io.Closer]bool), 358 conns: make(map[io.Closer]bool),
290 m: make(map[string]*service), 359 m: make(map[string]*service),
360 quit: make(chan struct{}),
361 done: make(chan struct{}),
362 czData: new(channelzData),
291 } 363 }
292 s.cv = sync.NewCond(&s.mu) 364 s.cv = sync.NewCond(&s.mu)
293 s.ctx, s.cancel = context.WithCancel(context.Background())
294 if EnableTracing { 365 if EnableTracing {
295 _, file, line, _ := runtime.Caller(1) 366 _, file, line, _ := runtime.Caller(1)
296 s.events = trace.NewEventLog("grpc.Server", fmt.Sprintf("%s:%d", file, line)) 367 s.events = trace.NewEventLog("grpc.Server", fmt.Sprintf("%s:%d", file, line))
297 } 368 }
369
370 if channelz.IsOn() {
371 s.channelzID = channelz.RegisterServer(&channelzServer{s}, "")
372 }
298 return s 373 return s
299} 374}
300 375
@@ -399,11 +474,9 @@ func (s *Server) GetServiceInfo() map[string]ServiceInfo {
399 return ret 474 return ret
400} 475}
401 476
402var ( 477// ErrServerStopped indicates that the operation is now illegal because of
403 // ErrServerStopped indicates that the operation is now illegal because of 478// the server being stopped.
404 // the server being stopped. 479var ErrServerStopped = errors.New("grpc: the server has been stopped")
405 ErrServerStopped = errors.New("grpc: the server has been stopped")
406)
407 480
408func (s *Server) useTransportAuthenticator(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { 481func (s *Server) useTransportAuthenticator(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
409 if s.opts.creds == nil { 482 if s.opts.creds == nil {
@@ -412,28 +485,67 @@ func (s *Server) useTransportAuthenticator(rawConn net.Conn) (net.Conn, credenti
412 return s.opts.creds.ServerHandshake(rawConn) 485 return s.opts.creds.ServerHandshake(rawConn)
413} 486}
414 487
488type listenSocket struct {
489 net.Listener
490 channelzID int64
491}
492
493func (l *listenSocket) ChannelzMetric() *channelz.SocketInternalMetric {
494 return &channelz.SocketInternalMetric{
495 SocketOptions: channelz.GetSocketOption(l.Listener),
496 LocalAddr: l.Listener.Addr(),
497 }
498}
499
500func (l *listenSocket) Close() error {
501 err := l.Listener.Close()
502 if channelz.IsOn() {
503 channelz.RemoveEntry(l.channelzID)
504 }
505 return err
506}
507
415// Serve accepts incoming connections on the listener lis, creating a new 508// Serve accepts incoming connections on the listener lis, creating a new
416// ServerTransport and service goroutine for each. The service goroutines 509// ServerTransport and service goroutine for each. The service goroutines
417// read gRPC requests and then call the registered handlers to reply to them. 510// read gRPC requests and then call the registered handlers to reply to them.
418// Serve returns when lis.Accept fails with fatal errors. lis will be closed when 511// Serve returns when lis.Accept fails with fatal errors. lis will be closed when
419// this method returns. 512// this method returns.
420// Serve always returns non-nil error. 513// Serve will return a non-nil error unless Stop or GracefulStop is called.
421func (s *Server) Serve(lis net.Listener) error { 514func (s *Server) Serve(lis net.Listener) error {
422 s.mu.Lock() 515 s.mu.Lock()
423 s.printf("serving") 516 s.printf("serving")
424 s.serve = true 517 s.serve = true
425 if s.lis == nil { 518 if s.lis == nil {
519 // Serve called after Stop or GracefulStop.
426 s.mu.Unlock() 520 s.mu.Unlock()
427 lis.Close() 521 lis.Close()
428 return ErrServerStopped 522 return ErrServerStopped
429 } 523 }
430 s.lis[lis] = true 524
525 s.serveWG.Add(1)
526 defer func() {
527 s.serveWG.Done()
528 select {
529 // Stop or GracefulStop called; block until done and return nil.
530 case <-s.quit:
531 <-s.done
532 default:
533 }
534 }()
535
536 ls := &listenSocket{Listener: lis}
537 s.lis[ls] = true
538
539 if channelz.IsOn() {
540 ls.channelzID = channelz.RegisterListenSocket(ls, s.channelzID, lis.Addr().String())
541 }
431 s.mu.Unlock() 542 s.mu.Unlock()
543
432 defer func() { 544 defer func() {
433 s.mu.Lock() 545 s.mu.Lock()
434 if s.lis != nil && s.lis[lis] { 546 if s.lis != nil && s.lis[ls] {
435 lis.Close() 547 ls.Close()
436 delete(s.lis, lis) 548 delete(s.lis, ls)
437 } 549 }
438 s.mu.Unlock() 550 s.mu.Unlock()
439 }() 551 }()
@@ -460,36 +572,52 @@ func (s *Server) Serve(lis net.Listener) error {
460 timer := time.NewTimer(tempDelay) 572 timer := time.NewTimer(tempDelay)
461 select { 573 select {
462 case <-timer.C: 574 case <-timer.C:
463 case <-s.ctx.Done(): 575 case <-s.quit:
576 timer.Stop()
577 return nil
464 } 578 }
465 timer.Stop()
466 continue 579 continue
467 } 580 }
468 s.mu.Lock() 581 s.mu.Lock()
469 s.printf("done serving; Accept = %v", err) 582 s.printf("done serving; Accept = %v", err)
470 s.mu.Unlock() 583 s.mu.Unlock()
584
585 select {
586 case <-s.quit:
587 return nil
588 default:
589 }
471 return err 590 return err
472 } 591 }
473 tempDelay = 0 592 tempDelay = 0
474 // Start a new goroutine to deal with rawConn 593 // Start a new goroutine to deal with rawConn so we don't stall this Accept
475 // so we don't stall this Accept loop goroutine. 594 // loop goroutine.
476 go s.handleRawConn(rawConn) 595 //
596 // Make sure we account for the goroutine so GracefulStop doesn't nil out
597 // s.conns before this conn can be added.
598 s.serveWG.Add(1)
599 go func() {
600 s.handleRawConn(rawConn)
601 s.serveWG.Done()
602 }()
477 } 603 }
478} 604}
479 605
480// handleRawConn is run in its own goroutine and handles a just-accepted 606// handleRawConn forks a goroutine to handle a just-accepted connection that
481// connection that has not had any I/O performed on it yet. 607// has not had any I/O performed on it yet.
482func (s *Server) handleRawConn(rawConn net.Conn) { 608func (s *Server) handleRawConn(rawConn net.Conn) {
609 rawConn.SetDeadline(time.Now().Add(s.opts.connectionTimeout))
483 conn, authInfo, err := s.useTransportAuthenticator(rawConn) 610 conn, authInfo, err := s.useTransportAuthenticator(rawConn)
484 if err != nil { 611 if err != nil {
485 s.mu.Lock() 612 s.mu.Lock()
486 s.errorf("ServerHandshake(%q) failed: %v", rawConn.RemoteAddr(), err) 613 s.errorf("ServerHandshake(%q) failed: %v", rawConn.RemoteAddr(), err)
487 s.mu.Unlock() 614 s.mu.Unlock()
488 grpclog.Warningf("grpc: Server.Serve failed to complete security handshake from %q: %v", rawConn.RemoteAddr(), err) 615 grpclog.Warningf("grpc: Server.Serve failed to complete security handshake from %q: %v", rawConn.RemoteAddr(), err)
489 // If serverHandShake returns ErrConnDispatched, keep rawConn open. 616 // If serverHandshake returns ErrConnDispatched, keep rawConn open.
490 if err != credentials.ErrConnDispatched { 617 if err != credentials.ErrConnDispatched {
491 rawConn.Close() 618 rawConn.Close()
492 } 619 }
620 rawConn.SetDeadline(time.Time{})
493 return 621 return
494 } 622 }
495 623
@@ -501,19 +629,25 @@ func (s *Server) handleRawConn(rawConn net.Conn) {
501 } 629 }
502 s.mu.Unlock() 630 s.mu.Unlock()
503 631
504 if s.opts.useHandlerImpl { 632 // Finish handshaking (HTTP2)
505 s.serveUsingHandler(conn) 633 st := s.newHTTP2Transport(conn, authInfo)
506 } else { 634 if st == nil {
507 s.serveHTTP2Transport(conn, authInfo) 635 return
636 }
637
638 rawConn.SetDeadline(time.Time{})
639 if !s.addConn(st) {
640 return
508 } 641 }
642 go func() {
643 s.serveStreams(st)
644 s.removeConn(st)
645 }()
509} 646}
510 647
511// serveHTTP2Transport sets up a http/2 transport (using the 648// newHTTP2Transport sets up a http/2 transport (using the
512// gRPC http2 server transport in transport/http2_server.go) and 649// gRPC http2 server transport in transport/http2_server.go).
513// serves streams on it. 650func (s *Server) newHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo) transport.ServerTransport {
514// This is run in its own goroutine (it does network I/O in
515// transport.NewServerTransport).
516func (s *Server) serveHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo) {
517 config := &transport.ServerConfig{ 651 config := &transport.ServerConfig{
518 MaxStreams: s.opts.maxConcurrentStreams, 652 MaxStreams: s.opts.maxConcurrentStreams,
519 AuthInfo: authInfo, 653 AuthInfo: authInfo,
@@ -523,6 +657,10 @@ func (s *Server) serveHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo)
523 KeepalivePolicy: s.opts.keepalivePolicy, 657 KeepalivePolicy: s.opts.keepalivePolicy,
524 InitialWindowSize: s.opts.initialWindowSize, 658 InitialWindowSize: s.opts.initialWindowSize,
525 InitialConnWindowSize: s.opts.initialConnWindowSize, 659 InitialConnWindowSize: s.opts.initialConnWindowSize,
660 WriteBufferSize: s.opts.writeBufferSize,
661 ReadBufferSize: s.opts.readBufferSize,
662 ChannelzParentID: s.channelzID,
663 MaxHeaderListSize: s.opts.maxHeaderListSize,
526 } 664 }
527 st, err := transport.NewServerTransport("http2", c, config) 665 st, err := transport.NewServerTransport("http2", c, config)
528 if err != nil { 666 if err != nil {
@@ -531,17 +669,13 @@ func (s *Server) serveHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo)
531 s.mu.Unlock() 669 s.mu.Unlock()
532 c.Close() 670 c.Close()
533 grpclog.Warningln("grpc: Server.Serve failed to create ServerTransport: ", err) 671 grpclog.Warningln("grpc: Server.Serve failed to create ServerTransport: ", err)
534 return 672 return nil
535 }
536 if !s.addConn(st) {
537 st.Close()
538 return
539 } 673 }
540 s.serveStreams(st) 674
675 return st
541} 676}
542 677
543func (s *Server) serveStreams(st transport.ServerTransport) { 678func (s *Server) serveStreams(st transport.ServerTransport) {
544 defer s.removeConn(st)
545 defer st.Close() 679 defer st.Close()
546 var wg sync.WaitGroup 680 var wg sync.WaitGroup
547 st.HandleStreams(func(stream *transport.Stream) { 681 st.HandleStreams(func(stream *transport.Stream) {
@@ -562,32 +696,6 @@ func (s *Server) serveStreams(st transport.ServerTransport) {
562 696
563var _ http.Handler = (*Server)(nil) 697var _ http.Handler = (*Server)(nil)
564 698
565// serveUsingHandler is called from handleRawConn when s is configured
566// to handle requests via the http.Handler interface. It sets up a
567// net/http.Server to handle the just-accepted conn. The http.Server
568// is configured to route all incoming requests (all HTTP/2 streams)
569// to ServeHTTP, which creates a new ServerTransport for each stream.
570// serveUsingHandler blocks until conn closes.
571//
572// This codepath is only used when Server.TestingUseHandlerImpl has
573// been configured. This lets the end2end tests exercise the ServeHTTP
574// method as one of the environment types.
575//
576// conn is the *tls.Conn that's already been authenticated.
577func (s *Server) serveUsingHandler(conn net.Conn) {
578 if !s.addConn(conn) {
579 conn.Close()
580 return
581 }
582 defer s.removeConn(conn)
583 h2s := &http2.Server{
584 MaxConcurrentStreams: s.opts.maxConcurrentStreams,
585 }
586 h2s.ServeConn(conn, &http2.ServeConnOpts{
587 Handler: s,
588 })
589}
590
591// ServeHTTP implements the Go standard library's http.Handler 699// ServeHTTP implements the Go standard library's http.Handler
592// interface by responding to the gRPC request r, by looking up 700// interface by responding to the gRPC request r, by looking up
593// the requested gRPC method in the gRPC server s. 701// the requested gRPC method in the gRPC server s.
@@ -613,13 +721,12 @@ func (s *Server) serveUsingHandler(conn net.Conn) {
613// available through grpc-go's HTTP/2 server, and it is currently EXPERIMENTAL 721// available through grpc-go's HTTP/2 server, and it is currently EXPERIMENTAL
614// and subject to change. 722// and subject to change.
615func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { 723func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
616 st, err := transport.NewServerHandlerTransport(w, r) 724 st, err := transport.NewServerHandlerTransport(w, r, s.opts.statsHandler)
617 if err != nil { 725 if err != nil {
618 http.Error(w, err.Error(), http.StatusInternalServerError) 726 http.Error(w, err.Error(), http.StatusInternalServerError)
619 return 727 return
620 } 728 }
621 if !s.addConn(st) { 729 if !s.addConn(st) {
622 st.Close()
623 return 730 return
624 } 731 }
625 defer s.removeConn(st) 732 defer s.removeConn(st)
@@ -649,9 +756,15 @@ func (s *Server) traceInfo(st transport.ServerTransport, stream *transport.Strea
649func (s *Server) addConn(c io.Closer) bool { 756func (s *Server) addConn(c io.Closer) bool {
650 s.mu.Lock() 757 s.mu.Lock()
651 defer s.mu.Unlock() 758 defer s.mu.Unlock()
652 if s.conns == nil || s.drain { 759 if s.conns == nil {
760 c.Close()
653 return false 761 return false
654 } 762 }
763 if s.drain {
764 // Transport added after we drained our existing conns: drain it
765 // immediately.
766 c.(transport.ServerTransport).Drain()
767 }
655 s.conns[c] = true 768 s.conns[c] = true
656 return true 769 return true
657} 770}
@@ -665,43 +778,73 @@ func (s *Server) removeConn(c io.Closer) {
665 } 778 }
666} 779}
667 780
668func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Stream, msg interface{}, cp Compressor, opts *transport.Options) error { 781func (s *Server) channelzMetric() *channelz.ServerInternalMetric {
669 var ( 782 return &channelz.ServerInternalMetric{
670 cbuf *bytes.Buffer 783 CallsStarted: atomic.LoadInt64(&s.czData.callsStarted),
671 outPayload *stats.OutPayload 784 CallsSucceeded: atomic.LoadInt64(&s.czData.callsSucceeded),
672 ) 785 CallsFailed: atomic.LoadInt64(&s.czData.callsFailed),
673 if cp != nil { 786 LastCallStartedTimestamp: time.Unix(0, atomic.LoadInt64(&s.czData.lastCallStartedTime)),
674 cbuf = new(bytes.Buffer)
675 } 787 }
676 if s.opts.statsHandler != nil { 788}
677 outPayload = &stats.OutPayload{} 789
678 } 790func (s *Server) incrCallsStarted() {
679 p, err := encode(s.opts.codec, msg, cp, cbuf, outPayload) 791 atomic.AddInt64(&s.czData.callsStarted, 1)
792 atomic.StoreInt64(&s.czData.lastCallStartedTime, time.Now().UnixNano())
793}
794
795func (s *Server) incrCallsSucceeded() {
796 atomic.AddInt64(&s.czData.callsSucceeded, 1)
797}
798
799func (s *Server) incrCallsFailed() {
800 atomic.AddInt64(&s.czData.callsFailed, 1)
801}
802
803func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Stream, msg interface{}, cp Compressor, opts *transport.Options, comp encoding.Compressor) error {
804 data, err := encode(s.getCodec(stream.ContentSubtype()), msg)
680 if err != nil { 805 if err != nil {
681 grpclog.Errorln("grpc: server failed to encode response: ", err) 806 grpclog.Errorln("grpc: server failed to encode response: ", err)
682 return err 807 return err
683 } 808 }
684 if len(p) > s.opts.maxSendMessageSize { 809 compData, err := compress(data, cp, comp)
685 return status.Errorf(codes.ResourceExhausted, "grpc: trying to send message larger than max (%d vs. %d)", len(p), s.opts.maxSendMessageSize) 810 if err != nil {
811 grpclog.Errorln("grpc: server failed to compress response: ", err)
812 return err
813 }
814 hdr, payload := msgHeader(data, compData)
815 // TODO(dfawley): should we be checking len(data) instead?
816 if len(payload) > s.opts.maxSendMessageSize {
817 return status.Errorf(codes.ResourceExhausted, "grpc: trying to send message larger than max (%d vs. %d)", len(payload), s.opts.maxSendMessageSize)
686 } 818 }
687 err = t.Write(stream, p, opts) 819 err = t.Write(stream, hdr, payload, opts)
688 if err == nil && outPayload != nil { 820 if err == nil && s.opts.statsHandler != nil {
689 outPayload.SentTime = time.Now() 821 s.opts.statsHandler.HandleRPC(stream.Context(), outPayload(false, msg, data, payload, time.Now()))
690 s.opts.statsHandler.HandleRPC(stream.Context(), outPayload)
691 } 822 }
692 return err 823 return err
693} 824}
694 825
695func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, md *MethodDesc, trInfo *traceInfo) (err error) { 826func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, md *MethodDesc, trInfo *traceInfo) (err error) {
827 if channelz.IsOn() {
828 s.incrCallsStarted()
829 defer func() {
830 if err != nil && err != io.EOF {
831 s.incrCallsFailed()
832 } else {
833 s.incrCallsSucceeded()
834 }
835 }()
836 }
696 sh := s.opts.statsHandler 837 sh := s.opts.statsHandler
697 if sh != nil { 838 if sh != nil {
839 beginTime := time.Now()
698 begin := &stats.Begin{ 840 begin := &stats.Begin{
699 BeginTime: time.Now(), 841 BeginTime: beginTime,
700 } 842 }
701 sh.HandleRPC(stream.Context(), begin) 843 sh.HandleRPC(stream.Context(), begin)
702 defer func() { 844 defer func() {
703 end := &stats.End{ 845 end := &stats.End{
704 EndTime: time.Now(), 846 BeginTime: beginTime,
847 EndTime: time.Now(),
705 } 848 }
706 if err != nil && err != io.EOF { 849 if err != nil && err != io.EOF {
707 end.Error = toRPCErr(err) 850 end.Error = toRPCErr(err)
@@ -720,94 +863,112 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
720 } 863 }
721 }() 864 }()
722 } 865 }
723 if s.opts.cp != nil { 866
724 // NOTE: this needs to be ahead of all handling, https://github.com/grpc/grpc-go/issues/686. 867 binlog := binarylog.GetMethodLogger(stream.Method())
725 stream.SetSendCompress(s.opts.cp.Type()) 868 if binlog != nil {
869 ctx := stream.Context()
870 md, _ := metadata.FromIncomingContext(ctx)
871 logEntry := &binarylog.ClientHeader{
872 Header: md,
873 MethodName: stream.Method(),
874 PeerAddr: nil,
875 }
876 if deadline, ok := ctx.Deadline(); ok {
877 logEntry.Timeout = deadline.Sub(time.Now())
878 if logEntry.Timeout < 0 {
879 logEntry.Timeout = 0
880 }
881 }
882 if a := md[":authority"]; len(a) > 0 {
883 logEntry.Authority = a[0]
884 }
885 if peer, ok := peer.FromContext(ctx); ok {
886 logEntry.PeerAddr = peer.Addr
887 }
888 binlog.Log(logEntry)
889 }
890
891 // comp and cp are used for compression. decomp and dc are used for
892 // decompression. If comp and decomp are both set, they are the same;
893 // however they are kept separate to ensure that at most one of the
894 // compressor/decompressor variable pairs are set for use later.
895 var comp, decomp encoding.Compressor
896 var cp Compressor
897 var dc Decompressor
898
899 // If dc is set and matches the stream's compression, use it. Otherwise, try
900 // to find a matching registered compressor for decomp.
901 if rc := stream.RecvCompress(); s.opts.dc != nil && s.opts.dc.Type() == rc {
902 dc = s.opts.dc
903 } else if rc != "" && rc != encoding.Identity {
904 decomp = encoding.GetCompressor(rc)
905 if decomp == nil {
906 st := status.Newf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", rc)
907 t.WriteStatus(stream, st)
908 return st.Err()
909 }
726 } 910 }
727 p := &parser{r: stream} 911
728 pf, req, err := p.recvMsg(s.opts.maxReceiveMessageSize) 912 // If cp is set, use it. Otherwise, attempt to compress the response using
729 if err == io.EOF { 913 // the incoming message compression method.
730 // The entire stream is done (for unary RPC only). 914 //
731 return err 915 // NOTE: this needs to be ahead of all handling, https://github.com/grpc/grpc-go/issues/686.
916 if s.opts.cp != nil {
917 cp = s.opts.cp
918 stream.SetSendCompress(cp.Type())
919 } else if rc := stream.RecvCompress(); rc != "" && rc != encoding.Identity {
920 // Legacy compressor not specified; attempt to respond with same encoding.
921 comp = encoding.GetCompressor(rc)
922 if comp != nil {
923 stream.SetSendCompress(rc)
924 }
732 } 925 }
733 if err == io.ErrUnexpectedEOF { 926
734 err = Errorf(codes.Internal, io.ErrUnexpectedEOF.Error()) 927 var payInfo *payloadInfo
928 if sh != nil || binlog != nil {
929 payInfo = &payloadInfo{}
735 } 930 }
931 d, err := recvAndDecompress(&parser{r: stream}, stream, dc, s.opts.maxReceiveMessageSize, payInfo, decomp)
736 if err != nil { 932 if err != nil {
737 if st, ok := status.FromError(err); ok { 933 if st, ok := status.FromError(err); ok {
738 if e := t.WriteStatus(stream, st); e != nil { 934 if e := t.WriteStatus(stream, st); e != nil {
739 grpclog.Warningf("grpc: Server.processUnaryRPC failed to write status %v", e) 935 grpclog.Warningf("grpc: Server.processUnaryRPC failed to write status %v", e)
740 } 936 }
741 } else {
742 switch st := err.(type) {
743 case transport.ConnectionError:
744 // Nothing to do here.
745 case transport.StreamError:
746 if e := t.WriteStatus(stream, status.New(st.Code, st.Desc)); e != nil {
747 grpclog.Warningf("grpc: Server.processUnaryRPC failed to write status %v", e)
748 }
749 default:
750 panic(fmt.Sprintf("grpc: Unexpected error (%T) from recvMsg: %v", st, st))
751 }
752 } 937 }
753 return err 938 return err
754 } 939 }
755 940 if channelz.IsOn() {
756 if err := checkRecvPayload(pf, stream.RecvCompress(), s.opts.dc); err != nil { 941 t.IncrMsgRecv()
757 if st, ok := status.FromError(err); ok {
758 if e := t.WriteStatus(stream, st); e != nil {
759 grpclog.Warningf("grpc: Server.processUnaryRPC failed to write status %v", e)
760 }
761 return err
762 }
763 if e := t.WriteStatus(stream, status.New(codes.Internal, err.Error())); e != nil {
764 grpclog.Warningf("grpc: Server.processUnaryRPC failed to write status %v", e)
765 }
766
767 // TODO checkRecvPayload always return RPC error. Add a return here if necessary.
768 }
769 var inPayload *stats.InPayload
770 if sh != nil {
771 inPayload = &stats.InPayload{
772 RecvTime: time.Now(),
773 }
774 } 942 }
775 df := func(v interface{}) error { 943 df := func(v interface{}) error {
776 if inPayload != nil { 944 if err := s.getCodec(stream.ContentSubtype()).Unmarshal(d, v); err != nil {
777 inPayload.WireLength = len(req)
778 }
779 if pf == compressionMade {
780 var err error
781 req, err = s.opts.dc.Do(bytes.NewReader(req))
782 if err != nil {
783 return Errorf(codes.Internal, err.Error())
784 }
785 }
786 if len(req) > s.opts.maxReceiveMessageSize {
787 // TODO: Revisit the error code. Currently keep it consistent with
788 // java implementation.
789 return status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", len(req), s.opts.maxReceiveMessageSize)
790 }
791 if err := s.opts.codec.Unmarshal(req, v); err != nil {
792 return status.Errorf(codes.Internal, "grpc: error unmarshalling request: %v", err) 945 return status.Errorf(codes.Internal, "grpc: error unmarshalling request: %v", err)
793 } 946 }
794 if inPayload != nil { 947 if sh != nil {
795 inPayload.Payload = v 948 sh.HandleRPC(stream.Context(), &stats.InPayload{
796 inPayload.Data = req 949 RecvTime: time.Now(),
797 inPayload.Length = len(req) 950 Payload: v,
798 sh.HandleRPC(stream.Context(), inPayload) 951 Data: d,
952 Length: len(d),
953 })
954 }
955 if binlog != nil {
956 binlog.Log(&binarylog.ClientMessage{
957 Message: d,
958 })
799 } 959 }
800 if trInfo != nil { 960 if trInfo != nil {
801 trInfo.tr.LazyLog(&payload{sent: false, msg: v}, true) 961 trInfo.tr.LazyLog(&payload{sent: false, msg: v}, true)
802 } 962 }
803 return nil 963 return nil
804 } 964 }
805 reply, appErr := md.Handler(srv.server, stream.Context(), df, s.opts.unaryInt) 965 ctx := NewContextWithServerTransportStream(stream.Context(), stream)
966 reply, appErr := md.Handler(srv.server, ctx, df, s.opts.unaryInt)
806 if appErr != nil { 967 if appErr != nil {
807 appStatus, ok := status.FromError(appErr) 968 appStatus, ok := status.FromError(appErr)
808 if !ok { 969 if !ok {
809 // Convert appErr if it is not a grpc status error. 970 // Convert appErr if it is not a grpc status error.
810 appErr = status.Error(convertCode(appErr), appErr.Error()) 971 appErr = status.Error(codes.Unknown, appErr.Error())
811 appStatus, _ = status.FromError(appErr) 972 appStatus, _ = status.FromError(appErr)
812 } 973 }
813 if trInfo != nil { 974 if trInfo != nil {
@@ -817,16 +978,27 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
817 if e := t.WriteStatus(stream, appStatus); e != nil { 978 if e := t.WriteStatus(stream, appStatus); e != nil {
818 grpclog.Warningf("grpc: Server.processUnaryRPC failed to write status: %v", e) 979 grpclog.Warningf("grpc: Server.processUnaryRPC failed to write status: %v", e)
819 } 980 }
981 if binlog != nil {
982 if h, _ := stream.Header(); h.Len() > 0 {
983 // Only log serverHeader if there was header. Otherwise it can
984 // be trailer only.
985 binlog.Log(&binarylog.ServerHeader{
986 Header: h,
987 })
988 }
989 binlog.Log(&binarylog.ServerTrailer{
990 Trailer: stream.Trailer(),
991 Err: appErr,
992 })
993 }
820 return appErr 994 return appErr
821 } 995 }
822 if trInfo != nil { 996 if trInfo != nil {
823 trInfo.tr.LazyLog(stringer("OK"), false) 997 trInfo.tr.LazyLog(stringer("OK"), false)
824 } 998 }
825 opts := &transport.Options{ 999 opts := &transport.Options{Last: true}
826 Last: true, 1000
827 Delay: false, 1001 if err := s.sendResponse(t, stream, reply, cp, opts, comp); err != nil {
828 }
829 if err := s.sendResponse(t, stream, reply, s.opts.cp, opts); err != nil {
830 if err == io.EOF { 1002 if err == io.EOF {
831 // The entire stream is done (for unary RPC only). 1003 // The entire stream is done (for unary RPC only).
832 return err 1004 return err
@@ -839,35 +1011,72 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
839 switch st := err.(type) { 1011 switch st := err.(type) {
840 case transport.ConnectionError: 1012 case transport.ConnectionError:
841 // Nothing to do here. 1013 // Nothing to do here.
842 case transport.StreamError:
843 if e := t.WriteStatus(stream, status.New(st.Code, st.Desc)); e != nil {
844 grpclog.Warningf("grpc: Server.processUnaryRPC failed to write status %v", e)
845 }
846 default: 1014 default:
847 panic(fmt.Sprintf("grpc: Unexpected error (%T) from sendResponse: %v", st, st)) 1015 panic(fmt.Sprintf("grpc: Unexpected error (%T) from sendResponse: %v", st, st))
848 } 1016 }
849 } 1017 }
1018 if binlog != nil {
1019 h, _ := stream.Header()
1020 binlog.Log(&binarylog.ServerHeader{
1021 Header: h,
1022 })
1023 binlog.Log(&binarylog.ServerTrailer{
1024 Trailer: stream.Trailer(),
1025 Err: appErr,
1026 })
1027 }
850 return err 1028 return err
851 } 1029 }
1030 if binlog != nil {
1031 h, _ := stream.Header()
1032 binlog.Log(&binarylog.ServerHeader{
1033 Header: h,
1034 })
1035 binlog.Log(&binarylog.ServerMessage{
1036 Message: reply,
1037 })
1038 }
1039 if channelz.IsOn() {
1040 t.IncrMsgSent()
1041 }
852 if trInfo != nil { 1042 if trInfo != nil {
853 trInfo.tr.LazyLog(&payload{sent: true, msg: reply}, true) 1043 trInfo.tr.LazyLog(&payload{sent: true, msg: reply}, true)
854 } 1044 }
855 // TODO: Should we be logging if writing status failed here, like above? 1045 // TODO: Should we be logging if writing status failed here, like above?
856 // Should the logging be in WriteStatus? Should we ignore the WriteStatus 1046 // Should the logging be in WriteStatus? Should we ignore the WriteStatus
857 // error or allow the stats handler to see it? 1047 // error or allow the stats handler to see it?
858 return t.WriteStatus(stream, status.New(codes.OK, "")) 1048 err = t.WriteStatus(stream, status.New(codes.OK, ""))
1049 if binlog != nil {
1050 binlog.Log(&binarylog.ServerTrailer{
1051 Trailer: stream.Trailer(),
1052 Err: appErr,
1053 })
1054 }
1055 return err
859} 1056}
860 1057
861func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, sd *StreamDesc, trInfo *traceInfo) (err error) { 1058func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, sd *StreamDesc, trInfo *traceInfo) (err error) {
1059 if channelz.IsOn() {
1060 s.incrCallsStarted()
1061 defer func() {
1062 if err != nil && err != io.EOF {
1063 s.incrCallsFailed()
1064 } else {
1065 s.incrCallsSucceeded()
1066 }
1067 }()
1068 }
862 sh := s.opts.statsHandler 1069 sh := s.opts.statsHandler
863 if sh != nil { 1070 if sh != nil {
1071 beginTime := time.Now()
864 begin := &stats.Begin{ 1072 begin := &stats.Begin{
865 BeginTime: time.Now(), 1073 BeginTime: beginTime,
866 } 1074 }
867 sh.HandleRPC(stream.Context(), begin) 1075 sh.HandleRPC(stream.Context(), begin)
868 defer func() { 1076 defer func() {
869 end := &stats.End{ 1077 end := &stats.End{
870 EndTime: time.Now(), 1078 BeginTime: beginTime,
1079 EndTime: time.Now(),
871 } 1080 }
872 if err != nil && err != io.EOF { 1081 if err != nil && err != io.EOF {
873 end.Error = toRPCErr(err) 1082 end.Error = toRPCErr(err)
@@ -875,24 +1084,70 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp
875 sh.HandleRPC(stream.Context(), end) 1084 sh.HandleRPC(stream.Context(), end)
876 }() 1085 }()
877 } 1086 }
878 if s.opts.cp != nil { 1087 ctx := NewContextWithServerTransportStream(stream.Context(), stream)
879 stream.SetSendCompress(s.opts.cp.Type())
880 }
881 ss := &serverStream{ 1088 ss := &serverStream{
882 t: t, 1089 ctx: ctx,
883 s: stream, 1090 t: t,
884 p: &parser{r: stream}, 1091 s: stream,
885 codec: s.opts.codec, 1092 p: &parser{r: stream},
886 cp: s.opts.cp, 1093 codec: s.getCodec(stream.ContentSubtype()),
887 dc: s.opts.dc,
888 maxReceiveMessageSize: s.opts.maxReceiveMessageSize, 1094 maxReceiveMessageSize: s.opts.maxReceiveMessageSize,
889 maxSendMessageSize: s.opts.maxSendMessageSize, 1095 maxSendMessageSize: s.opts.maxSendMessageSize,
890 trInfo: trInfo, 1096 trInfo: trInfo,
891 statsHandler: sh, 1097 statsHandler: sh,
892 } 1098 }
893 if ss.cp != nil { 1099
894 ss.cbuf = new(bytes.Buffer) 1100 ss.binlog = binarylog.GetMethodLogger(stream.Method())
1101 if ss.binlog != nil {
1102 md, _ := metadata.FromIncomingContext(ctx)
1103 logEntry := &binarylog.ClientHeader{
1104 Header: md,
1105 MethodName: stream.Method(),
1106 PeerAddr: nil,
1107 }
1108 if deadline, ok := ctx.Deadline(); ok {
1109 logEntry.Timeout = deadline.Sub(time.Now())
1110 if logEntry.Timeout < 0 {
1111 logEntry.Timeout = 0
1112 }
1113 }
1114 if a := md[":authority"]; len(a) > 0 {
1115 logEntry.Authority = a[0]
1116 }
1117 if peer, ok := peer.FromContext(ss.Context()); ok {
1118 logEntry.PeerAddr = peer.Addr
1119 }
1120 ss.binlog.Log(logEntry)
1121 }
1122
1123 // If dc is set and matches the stream's compression, use it. Otherwise, try
1124 // to find a matching registered compressor for decomp.
1125 if rc := stream.RecvCompress(); s.opts.dc != nil && s.opts.dc.Type() == rc {
1126 ss.dc = s.opts.dc
1127 } else if rc != "" && rc != encoding.Identity {
1128 ss.decomp = encoding.GetCompressor(rc)
1129 if ss.decomp == nil {
1130 st := status.Newf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", rc)
1131 t.WriteStatus(ss.s, st)
1132 return st.Err()
1133 }
1134 }
1135
1136 // If cp is set, use it. Otherwise, attempt to compress the response using
1137 // the incoming message compression method.
1138 //
1139 // NOTE: this needs to be ahead of all handling, https://github.com/grpc/grpc-go/issues/686.
1140 if s.opts.cp != nil {
1141 ss.cp = s.opts.cp
1142 stream.SetSendCompress(s.opts.cp.Type())
1143 } else if rc := stream.RecvCompress(); rc != "" && rc != encoding.Identity {
1144 // Legacy compressor not specified; attempt to respond with same encoding.
1145 ss.comp = encoding.GetCompressor(rc)
1146 if ss.comp != nil {
1147 stream.SetSendCompress(rc)
1148 }
895 } 1149 }
1150
896 if trInfo != nil { 1151 if trInfo != nil {
897 trInfo.tr.LazyLog(&trInfo.firstLine, false) 1152 trInfo.tr.LazyLog(&trInfo.firstLine, false)
898 defer func() { 1153 defer func() {
@@ -924,12 +1179,7 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp
924 if appErr != nil { 1179 if appErr != nil {
925 appStatus, ok := status.FromError(appErr) 1180 appStatus, ok := status.FromError(appErr)
926 if !ok { 1181 if !ok {
927 switch err := appErr.(type) { 1182 appStatus = status.New(codes.Unknown, appErr.Error())
928 case transport.StreamError:
929 appStatus = status.New(err.Code, err.Desc)
930 default:
931 appStatus = status.New(convertCode(appErr), appErr.Error())
932 }
933 appErr = appStatus.Err() 1183 appErr = appStatus.Err()
934 } 1184 }
935 if trInfo != nil { 1185 if trInfo != nil {
@@ -939,6 +1189,12 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp
939 ss.mu.Unlock() 1189 ss.mu.Unlock()
940 } 1190 }
941 t.WriteStatus(ss.s, appStatus) 1191 t.WriteStatus(ss.s, appStatus)
1192 if ss.binlog != nil {
1193 ss.binlog.Log(&binarylog.ServerTrailer{
1194 Trailer: ss.s.Trailer(),
1195 Err: appErr,
1196 })
1197 }
942 // TODO: Should we log an error from WriteStatus here and below? 1198 // TODO: Should we log an error from WriteStatus here and below?
943 return appErr 1199 return appErr
944 } 1200 }
@@ -947,8 +1203,14 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp
947 ss.trInfo.tr.LazyLog(stringer("OK"), false) 1203 ss.trInfo.tr.LazyLog(stringer("OK"), false)
948 ss.mu.Unlock() 1204 ss.mu.Unlock()
949 } 1205 }
950 return t.WriteStatus(ss.s, status.New(codes.OK, "")) 1206 err = t.WriteStatus(ss.s, status.New(codes.OK, ""))
951 1207 if ss.binlog != nil {
1208 ss.binlog.Log(&binarylog.ServerTrailer{
1209 Trailer: ss.s.Trailer(),
1210 Err: appErr,
1211 })
1212 }
1213 return err
952} 1214}
953 1215
954func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Stream, trInfo *traceInfo) { 1216func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Stream, trInfo *traceInfo) {
@@ -977,47 +1239,27 @@ func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Str
977 } 1239 }
978 service := sm[:pos] 1240 service := sm[:pos]
979 method := sm[pos+1:] 1241 method := sm[pos+1:]
980 srv, ok := s.m[service] 1242
981 if !ok { 1243 if srv, ok := s.m[service]; ok {
982 if unknownDesc := s.opts.unknownStreamDesc; unknownDesc != nil { 1244 if md, ok := srv.md[method]; ok {
983 s.processStreamingRPC(t, stream, nil, unknownDesc, trInfo) 1245 s.processUnaryRPC(t, stream, srv, md, trInfo)
984 return 1246 return
985 } 1247 }
986 if trInfo != nil { 1248 if sd, ok := srv.sd[method]; ok {
987 trInfo.tr.LazyLog(&fmtStringer{"Unknown service %v", []interface{}{service}}, true) 1249 s.processStreamingRPC(t, stream, srv, sd, trInfo)
988 trInfo.tr.SetError() 1250 return
989 }
990 errDesc := fmt.Sprintf("unknown service %v", service)
991 if err := t.WriteStatus(stream, status.New(codes.Unimplemented, errDesc)); err != nil {
992 if trInfo != nil {
993 trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
994 trInfo.tr.SetError()
995 }
996 grpclog.Warningf("grpc: Server.handleStream failed to write status: %v", err)
997 }
998 if trInfo != nil {
999 trInfo.tr.Finish()
1000 } 1251 }
1001 return
1002 }
1003 // Unary RPC or Streaming RPC?
1004 if md, ok := srv.md[method]; ok {
1005 s.processUnaryRPC(t, stream, srv, md, trInfo)
1006 return
1007 } 1252 }
1008 if sd, ok := srv.sd[method]; ok { 1253 // Unknown service, or known server unknown method.
1009 s.processStreamingRPC(t, stream, srv, sd, trInfo) 1254 if unknownDesc := s.opts.unknownStreamDesc; unknownDesc != nil {
1255 s.processStreamingRPC(t, stream, nil, unknownDesc, trInfo)
1010 return 1256 return
1011 } 1257 }
1012 if trInfo != nil { 1258 if trInfo != nil {
1013 trInfo.tr.LazyLog(&fmtStringer{"Unknown method %v", []interface{}{method}}, true) 1259 trInfo.tr.LazyLog(&fmtStringer{"Unknown service %v", []interface{}{service}}, true)
1014 trInfo.tr.SetError() 1260 trInfo.tr.SetError()
1015 } 1261 }
1016 if unknownDesc := s.opts.unknownStreamDesc; unknownDesc != nil { 1262 errDesc := fmt.Sprintf("unknown service %v", service)
1017 s.processStreamingRPC(t, stream, nil, unknownDesc, trInfo)
1018 return
1019 }
1020 errDesc := fmt.Sprintf("unknown method %v", method)
1021 if err := t.WriteStatus(stream, status.New(codes.Unimplemented, errDesc)); err != nil { 1263 if err := t.WriteStatus(stream, status.New(codes.Unimplemented, errDesc)); err != nil {
1022 if trInfo != nil { 1264 if trInfo != nil {
1023 trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) 1265 trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
@@ -1030,12 +1272,65 @@ func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Str
1030 } 1272 }
1031} 1273}
1032 1274
1275// The key to save ServerTransportStream in the context.
1276type streamKey struct{}
1277
1278// NewContextWithServerTransportStream creates a new context from ctx and
1279// attaches stream to it.
1280//
1281// This API is EXPERIMENTAL.
1282func NewContextWithServerTransportStream(ctx context.Context, stream ServerTransportStream) context.Context {
1283 return context.WithValue(ctx, streamKey{}, stream)
1284}
1285
1286// ServerTransportStream is a minimal interface that a transport stream must
1287// implement. This can be used to mock an actual transport stream for tests of
1288// handler code that use, for example, grpc.SetHeader (which requires some
1289// stream to be in context).
1290//
1291// See also NewContextWithServerTransportStream.
1292//
1293// This API is EXPERIMENTAL.
1294type ServerTransportStream interface {
1295 Method() string
1296 SetHeader(md metadata.MD) error
1297 SendHeader(md metadata.MD) error
1298 SetTrailer(md metadata.MD) error
1299}
1300
1301// ServerTransportStreamFromContext returns the ServerTransportStream saved in
1302// ctx. Returns nil if the given context has no stream associated with it
1303// (which implies it is not an RPC invocation context).
1304//
1305// This API is EXPERIMENTAL.
1306func ServerTransportStreamFromContext(ctx context.Context) ServerTransportStream {
1307 s, _ := ctx.Value(streamKey{}).(ServerTransportStream)
1308 return s
1309}
1310
1033// Stop stops the gRPC server. It immediately closes all open 1311// Stop stops the gRPC server. It immediately closes all open
1034// connections and listeners. 1312// connections and listeners.
1035// It cancels all active RPCs on the server side and the corresponding 1313// It cancels all active RPCs on the server side and the corresponding
1036// pending RPCs on the client side will get notified by connection 1314// pending RPCs on the client side will get notified by connection
1037// errors. 1315// errors.
1038func (s *Server) Stop() { 1316func (s *Server) Stop() {
1317 s.quitOnce.Do(func() {
1318 close(s.quit)
1319 })
1320
1321 defer func() {
1322 s.serveWG.Wait()
1323 s.doneOnce.Do(func() {
1324 close(s.done)
1325 })
1326 }()
1327
1328 s.channelzRemoveOnce.Do(func() {
1329 if channelz.IsOn() {
1330 channelz.RemoveEntry(s.channelzID)
1331 }
1332 })
1333
1039 s.mu.Lock() 1334 s.mu.Lock()
1040 listeners := s.lis 1335 listeners := s.lis
1041 s.lis = nil 1336 s.lis = nil
@@ -1053,7 +1348,6 @@ func (s *Server) Stop() {
1053 } 1348 }
1054 1349
1055 s.mu.Lock() 1350 s.mu.Lock()
1056 s.cancel()
1057 if s.events != nil { 1351 if s.events != nil {
1058 s.events.Finish() 1352 s.events.Finish()
1059 s.events = nil 1353 s.events = nil
@@ -1065,22 +1359,44 @@ func (s *Server) Stop() {
1065// accepting new connections and RPCs and blocks until all the pending RPCs are 1359// accepting new connections and RPCs and blocks until all the pending RPCs are
1066// finished. 1360// finished.
1067func (s *Server) GracefulStop() { 1361func (s *Server) GracefulStop() {
1362 s.quitOnce.Do(func() {
1363 close(s.quit)
1364 })
1365
1366 defer func() {
1367 s.doneOnce.Do(func() {
1368 close(s.done)
1369 })
1370 }()
1371
1372 s.channelzRemoveOnce.Do(func() {
1373 if channelz.IsOn() {
1374 channelz.RemoveEntry(s.channelzID)
1375 }
1376 })
1068 s.mu.Lock() 1377 s.mu.Lock()
1069 defer s.mu.Unlock()
1070 if s.conns == nil { 1378 if s.conns == nil {
1379 s.mu.Unlock()
1071 return 1380 return
1072 } 1381 }
1382
1073 for lis := range s.lis { 1383 for lis := range s.lis {
1074 lis.Close() 1384 lis.Close()
1075 } 1385 }
1076 s.lis = nil 1386 s.lis = nil
1077 s.cancel()
1078 if !s.drain { 1387 if !s.drain {
1079 for c := range s.conns { 1388 for c := range s.conns {
1080 c.(transport.ServerTransport).Drain() 1389 c.(transport.ServerTransport).Drain()
1081 } 1390 }
1082 s.drain = true 1391 s.drain = true
1083 } 1392 }
1393
1394 // Wait for serving threads to be ready to exit. Only then can we be sure no
1395 // new conns will be created.
1396 s.mu.Unlock()
1397 s.serveWG.Wait()
1398 s.mu.Lock()
1399
1084 for len(s.conns) != 0 { 1400 for len(s.conns) != 0 {
1085 s.cv.Wait() 1401 s.cv.Wait()
1086 } 1402 }
@@ -1089,26 +1405,23 @@ func (s *Server) GracefulStop() {
1089 s.events.Finish() 1405 s.events.Finish()
1090 s.events = nil 1406 s.events = nil
1091 } 1407 }
1408 s.mu.Unlock()
1092} 1409}
1093 1410
1094func init() { 1411// contentSubtype must be lowercase
1095 internal.TestingCloseConns = func(arg interface{}) { 1412// cannot return nil
1096 arg.(*Server).testingCloseConns() 1413func (s *Server) getCodec(contentSubtype string) baseCodec {
1414 if s.opts.codec != nil {
1415 return s.opts.codec
1097 } 1416 }
1098 internal.TestingUseHandlerImpl = func(arg interface{}) { 1417 if contentSubtype == "" {
1099 arg.(*Server).opts.useHandlerImpl = true 1418 return encoding.GetCodec(proto.Name)
1100 } 1419 }
1101} 1420 codec := encoding.GetCodec(contentSubtype)
1102 1421 if codec == nil {
1103// testingCloseConns closes all existing transports but keeps s.lis 1422 return encoding.GetCodec(proto.Name)
1104// accepting new connections.
1105func (s *Server) testingCloseConns() {
1106 s.mu.Lock()
1107 for c := range s.conns {
1108 c.Close()
1109 delete(s.conns, c)
1110 } 1423 }
1111 s.mu.Unlock() 1424 return codec
1112} 1425}
1113 1426
1114// SetHeader sets the header metadata. 1427// SetHeader sets the header metadata.
@@ -1121,9 +1434,9 @@ func SetHeader(ctx context.Context, md metadata.MD) error {
1121 if md.Len() == 0 { 1434 if md.Len() == 0 {
1122 return nil 1435 return nil
1123 } 1436 }
1124 stream, ok := transport.StreamFromContext(ctx) 1437 stream := ServerTransportStreamFromContext(ctx)
1125 if !ok { 1438 if stream == nil {
1126 return Errorf(codes.Internal, "grpc: failed to fetch the stream from the context %v", ctx) 1439 return status.Errorf(codes.Internal, "grpc: failed to fetch the stream from the context %v", ctx)
1127 } 1440 }
1128 return stream.SetHeader(md) 1441 return stream.SetHeader(md)
1129} 1442}
@@ -1131,15 +1444,11 @@ func SetHeader(ctx context.Context, md metadata.MD) error {
1131// SendHeader sends header metadata. It may be called at most once. 1444// SendHeader sends header metadata. It may be called at most once.
1132// The provided md and headers set by SetHeader() will be sent. 1445// The provided md and headers set by SetHeader() will be sent.
1133func SendHeader(ctx context.Context, md metadata.MD) error { 1446func SendHeader(ctx context.Context, md metadata.MD) error {
1134 stream, ok := transport.StreamFromContext(ctx) 1447 stream := ServerTransportStreamFromContext(ctx)
1135 if !ok { 1448 if stream == nil {
1136 return Errorf(codes.Internal, "grpc: failed to fetch the stream from the context %v", ctx) 1449 return status.Errorf(codes.Internal, "grpc: failed to fetch the stream from the context %v", ctx)
1137 } 1450 }
1138 t := stream.ServerTransport() 1451 if err := stream.SendHeader(md); err != nil {
1139 if t == nil {
1140 grpclog.Fatalf("grpc: SendHeader: %v has no ServerTransport to send header metadata.", stream)
1141 }
1142 if err := t.WriteHeader(stream, md); err != nil {
1143 return toRPCErr(err) 1452 return toRPCErr(err)
1144 } 1453 }
1145 return nil 1454 return nil
@@ -1151,9 +1460,27 @@ func SetTrailer(ctx context.Context, md metadata.MD) error {
1151 if md.Len() == 0 { 1460 if md.Len() == 0 {
1152 return nil 1461 return nil
1153 } 1462 }
1154 stream, ok := transport.StreamFromContext(ctx) 1463 stream := ServerTransportStreamFromContext(ctx)
1155 if !ok { 1464 if stream == nil {
1156 return Errorf(codes.Internal, "grpc: failed to fetch the stream from the context %v", ctx) 1465 return status.Errorf(codes.Internal, "grpc: failed to fetch the stream from the context %v", ctx)
1157 } 1466 }
1158 return stream.SetTrailer(md) 1467 return stream.SetTrailer(md)
1159} 1468}
1469
1470// Method returns the method string for the server context. The returned
1471// string is in the format of "/service/method".
1472func Method(ctx context.Context) (string, bool) {
1473 s := ServerTransportStreamFromContext(ctx)
1474 if s == nil {
1475 return "", false
1476 }
1477 return s.Method(), true
1478}
1479
1480type channelzServer struct {
1481 s *Server
1482}
1483
1484func (c *channelzServer) ChannelzMetric() *channelz.ServerInternalMetric {
1485 return c.s.channelzMetric()
1486}
diff --git a/vendor/google.golang.org/grpc/service_config.go b/vendor/google.golang.org/grpc/service_config.go
new file mode 100644
index 0000000..162857e
--- /dev/null
+++ b/vendor/google.golang.org/grpc/service_config.go
@@ -0,0 +1,372 @@
1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package grpc
20
21import (
22 "encoding/json"
23 "fmt"
24 "strconv"
25 "strings"
26 "time"
27
28 "google.golang.org/grpc/codes"
29 "google.golang.org/grpc/grpclog"
30)
31
32const maxInt = int(^uint(0) >> 1)
33
34// MethodConfig defines the configuration recommended by the service providers for a
35// particular method.
36//
37// Deprecated: Users should not use this struct. Service config should be received
38// through name resolver, as specified here
39// https://github.com/grpc/grpc/blob/master/doc/service_config.md
40type MethodConfig struct {
41 // WaitForReady indicates whether RPCs sent to this method should wait until
42 // the connection is ready by default (!failfast). The value specified via the
43 // gRPC client API will override the value set here.
44 WaitForReady *bool
45 // Timeout is the default timeout for RPCs sent to this method. The actual
46 // deadline used will be the minimum of the value specified here and the value
47 // set by the application via the gRPC client API. If either one is not set,
48 // then the other will be used. If neither is set, then the RPC has no deadline.
49 Timeout *time.Duration
50 // MaxReqSize is the maximum allowed payload size for an individual request in a
51 // stream (client->server) in bytes. The size which is measured is the serialized
52 // payload after per-message compression (but before stream compression) in bytes.
53 // The actual value used is the minimum of the value specified here and the value set
54 // by the application via the gRPC client API. If either one is not set, then the other
55 // will be used. If neither is set, then the built-in default is used.
56 MaxReqSize *int
57 // MaxRespSize is the maximum allowed payload size for an individual response in a
58 // stream (server->client) in bytes.
59 MaxRespSize *int
60 // RetryPolicy configures retry options for the method.
61 retryPolicy *retryPolicy
62}
63
64// ServiceConfig is provided by the service provider and contains parameters for how
65// clients that connect to the service should behave.
66//
67// Deprecated: Users should not use this struct. Service config should be received
68// through name resolver, as specified here
69// https://github.com/grpc/grpc/blob/master/doc/service_config.md
70type ServiceConfig struct {
71 // LB is the load balancer the service providers recommends. The balancer specified
72 // via grpc.WithBalancer will override this.
73 LB *string
74
75 // Methods contains a map for the methods in this service. If there is an
76 // exact match for a method (i.e. /service/method) in the map, use the
77 // corresponding MethodConfig. If there's no exact match, look for the
78 // default config for the service (/service/) and use the corresponding
79 // MethodConfig if it exists. Otherwise, the method has no MethodConfig to
80 // use.
81 Methods map[string]MethodConfig
82
83 // If a retryThrottlingPolicy is provided, gRPC will automatically throttle
84 // retry attempts and hedged RPCs when the client’s ratio of failures to
85 // successes exceeds a threshold.
86 //
87 // For each server name, the gRPC client will maintain a token_count which is
88 // initially set to maxTokens, and can take values between 0 and maxTokens.
89 //
90 // Every outgoing RPC (regardless of service or method invoked) will change
91 // token_count as follows:
92 //
93 // - Every failed RPC will decrement the token_count by 1.
94 // - Every successful RPC will increment the token_count by tokenRatio.
95 //
96 // If token_count is less than or equal to maxTokens / 2, then RPCs will not
97 // be retried and hedged RPCs will not be sent.
98 retryThrottling *retryThrottlingPolicy
99 // healthCheckConfig must be set as one of the requirement to enable LB channel
100 // health check.
101 healthCheckConfig *healthCheckConfig
102}
103
104// healthCheckConfig defines the go-native version of the LB channel health check config.
105type healthCheckConfig struct {
106 // serviceName is the service name to use in the health-checking request.
107 ServiceName string
108}
109
110// retryPolicy defines the go-native version of the retry policy defined by the
111// service config here:
112// https://github.com/grpc/proposal/blob/master/A6-client-retries.md#integration-with-service-config
113type retryPolicy struct {
114 // MaxAttempts is the maximum number of attempts, including the original RPC.
115 //
116 // This field is required and must be two or greater.
117 maxAttempts int
118
119 // Exponential backoff parameters. The initial retry attempt will occur at
120 // random(0, initialBackoffMS). In general, the nth attempt will occur at
121 // random(0,
122 // min(initialBackoffMS*backoffMultiplier**(n-1), maxBackoffMS)).
123 //
124 // These fields are required and must be greater than zero.
125 initialBackoff time.Duration
126 maxBackoff time.Duration
127 backoffMultiplier float64
128
129 // The set of status codes which may be retried.
130 //
131 // Status codes are specified as strings, e.g., "UNAVAILABLE".
132 //
133 // This field is required and must be non-empty.
134 // Note: a set is used to store this for easy lookup.
135 retryableStatusCodes map[codes.Code]bool
136}
137
138type jsonRetryPolicy struct {
139 MaxAttempts int
140 InitialBackoff string
141 MaxBackoff string
142 BackoffMultiplier float64
143 RetryableStatusCodes []codes.Code
144}
145
146// retryThrottlingPolicy defines the go-native version of the retry throttling
147// policy defined by the service config here:
148// https://github.com/grpc/proposal/blob/master/A6-client-retries.md#integration-with-service-config
149type retryThrottlingPolicy struct {
150 // The number of tokens starts at maxTokens. The token_count will always be
151 // between 0 and maxTokens.
152 //
153 // This field is required and must be greater than zero.
154 MaxTokens float64
155 // The amount of tokens to add on each successful RPC. Typically this will
156 // be some number between 0 and 1, e.g., 0.1.
157 //
158 // This field is required and must be greater than zero. Up to 3 decimal
159 // places are supported.
160 TokenRatio float64
161}
162
163func parseDuration(s *string) (*time.Duration, error) {
164 if s == nil {
165 return nil, nil
166 }
167 if !strings.HasSuffix(*s, "s") {
168 return nil, fmt.Errorf("malformed duration %q", *s)
169 }
170 ss := strings.SplitN((*s)[:len(*s)-1], ".", 3)
171 if len(ss) > 2 {
172 return nil, fmt.Errorf("malformed duration %q", *s)
173 }
174 // hasDigits is set if either the whole or fractional part of the number is
175 // present, since both are optional but one is required.
176 hasDigits := false
177 var d time.Duration
178 if len(ss[0]) > 0 {
179 i, err := strconv.ParseInt(ss[0], 10, 32)
180 if err != nil {
181 return nil, fmt.Errorf("malformed duration %q: %v", *s, err)
182 }
183 d = time.Duration(i) * time.Second
184 hasDigits = true
185 }
186 if len(ss) == 2 && len(ss[1]) > 0 {
187 if len(ss[1]) > 9 {
188 return nil, fmt.Errorf("malformed duration %q", *s)
189 }
190 f, err := strconv.ParseInt(ss[1], 10, 64)
191 if err != nil {
192 return nil, fmt.Errorf("malformed duration %q: %v", *s, err)
193 }
194 for i := 9; i > len(ss[1]); i-- {
195 f *= 10
196 }
197 d += time.Duration(f)
198 hasDigits = true
199 }
200 if !hasDigits {
201 return nil, fmt.Errorf("malformed duration %q", *s)
202 }
203
204 return &d, nil
205}
206
207type jsonName struct {
208 Service *string
209 Method *string
210}
211
212func (j jsonName) generatePath() (string, bool) {
213 if j.Service == nil {
214 return "", false
215 }
216 res := "/" + *j.Service + "/"
217 if j.Method != nil {
218 res += *j.Method
219 }
220 return res, true
221}
222
223// TODO(lyuxuan): delete this struct after cleaning up old service config implementation.
224type jsonMC struct {
225 Name *[]jsonName
226 WaitForReady *bool
227 Timeout *string
228 MaxRequestMessageBytes *int64
229 MaxResponseMessageBytes *int64
230 RetryPolicy *jsonRetryPolicy
231}
232
233// TODO(lyuxuan): delete this struct after cleaning up old service config implementation.
234type jsonSC struct {
235 LoadBalancingPolicy *string
236 MethodConfig *[]jsonMC
237 RetryThrottling *retryThrottlingPolicy
238 HealthCheckConfig *healthCheckConfig
239}
240
241func parseServiceConfig(js string) (ServiceConfig, error) {
242 if len(js) == 0 {
243 return ServiceConfig{}, fmt.Errorf("no JSON service config provided")
244 }
245 var rsc jsonSC
246 err := json.Unmarshal([]byte(js), &rsc)
247 if err != nil {
248 grpclog.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err)
249 return ServiceConfig{}, err
250 }
251 sc := ServiceConfig{
252 LB: rsc.LoadBalancingPolicy,
253 Methods: make(map[string]MethodConfig),
254 retryThrottling: rsc.RetryThrottling,
255 healthCheckConfig: rsc.HealthCheckConfig,
256 }
257 if rsc.MethodConfig == nil {
258 return sc, nil
259 }
260
261 for _, m := range *rsc.MethodConfig {
262 if m.Name == nil {
263 continue
264 }
265 d, err := parseDuration(m.Timeout)
266 if err != nil {
267 grpclog.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err)
268 return ServiceConfig{}, err
269 }
270
271 mc := MethodConfig{
272 WaitForReady: m.WaitForReady,
273 Timeout: d,
274 }
275 if mc.retryPolicy, err = convertRetryPolicy(m.RetryPolicy); err != nil {
276 grpclog.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err)
277 return ServiceConfig{}, err
278 }
279 if m.MaxRequestMessageBytes != nil {
280 if *m.MaxRequestMessageBytes > int64(maxInt) {
281 mc.MaxReqSize = newInt(maxInt)
282 } else {
283 mc.MaxReqSize = newInt(int(*m.MaxRequestMessageBytes))
284 }
285 }
286 if m.MaxResponseMessageBytes != nil {
287 if *m.MaxResponseMessageBytes > int64(maxInt) {
288 mc.MaxRespSize = newInt(maxInt)
289 } else {
290 mc.MaxRespSize = newInt(int(*m.MaxResponseMessageBytes))
291 }
292 }
293 for _, n := range *m.Name {
294 if path, valid := n.generatePath(); valid {
295 sc.Methods[path] = mc
296 }
297 }
298 }
299
300 if sc.retryThrottling != nil {
301 if sc.retryThrottling.MaxTokens <= 0 ||
302 sc.retryThrottling.MaxTokens >= 1000 ||
303 sc.retryThrottling.TokenRatio <= 0 {
304 // Illegal throttling config; disable throttling.
305 sc.retryThrottling = nil
306 }
307 }
308 return sc, nil
309}
310
311func convertRetryPolicy(jrp *jsonRetryPolicy) (p *retryPolicy, err error) {
312 if jrp == nil {
313 return nil, nil
314 }
315 ib, err := parseDuration(&jrp.InitialBackoff)
316 if err != nil {
317 return nil, err
318 }
319 mb, err := parseDuration(&jrp.MaxBackoff)
320 if err != nil {
321 return nil, err
322 }
323
324 if jrp.MaxAttempts <= 1 ||
325 *ib <= 0 ||
326 *mb <= 0 ||
327 jrp.BackoffMultiplier <= 0 ||
328 len(jrp.RetryableStatusCodes) == 0 {
329 grpclog.Warningf("grpc: ignoring retry policy %v due to illegal configuration", jrp)
330 return nil, nil
331 }
332
333 rp := &retryPolicy{
334 maxAttempts: jrp.MaxAttempts,
335 initialBackoff: *ib,
336 maxBackoff: *mb,
337 backoffMultiplier: jrp.BackoffMultiplier,
338 retryableStatusCodes: make(map[codes.Code]bool),
339 }
340 if rp.maxAttempts > 5 {
341 // TODO(retry): Make the max maxAttempts configurable.
342 rp.maxAttempts = 5
343 }
344 for _, code := range jrp.RetryableStatusCodes {
345 rp.retryableStatusCodes[code] = true
346 }
347 return rp, nil
348}
349
350func min(a, b *int) *int {
351 if *a < *b {
352 return a
353 }
354 return b
355}
356
357func getMaxSize(mcMax, doptMax *int, defaultVal int) *int {
358 if mcMax == nil && doptMax == nil {
359 return &defaultVal
360 }
361 if mcMax != nil && doptMax != nil {
362 return min(mcMax, doptMax)
363 }
364 if mcMax != nil {
365 return mcMax
366 }
367 return doptMax
368}
369
370func newInt(b int) *int {
371 return &b
372}
diff --git a/vendor/google.golang.org/grpc/stats/handlers.go b/vendor/google.golang.org/grpc/stats/handlers.go
index 05b384c..dc03731 100644
--- a/vendor/google.golang.org/grpc/stats/handlers.go
+++ b/vendor/google.golang.org/grpc/stats/handlers.go
@@ -19,9 +19,8 @@
19package stats 19package stats
20 20
21import ( 21import (
22 "context"
22 "net" 23 "net"
23
24 "golang.org/x/net/context"
25) 24)
26 25
27// ConnTagInfo defines the relevant information needed by connection context tagger. 26// ConnTagInfo defines the relevant information needed by connection context tagger.
diff --git a/vendor/google.golang.org/grpc/stats/stats.go b/vendor/google.golang.org/grpc/stats/stats.go
index 338a3a7..84f77da 100644
--- a/vendor/google.golang.org/grpc/stats/stats.go
+++ b/vendor/google.golang.org/grpc/stats/stats.go
@@ -16,12 +16,15 @@
16 * 16 *
17 */ 17 */
18 18
19//go:generate protoc --go_out=plugins=grpc:. grpc_testing/test.proto
20
19// Package stats is for collecting and reporting various network and RPC stats. 21// Package stats is for collecting and reporting various network and RPC stats.
20// This package is for monitoring purpose only. All fields are read-only. 22// This package is for monitoring purpose only. All fields are read-only.
21// All APIs are experimental. 23// All APIs are experimental.
22package stats // import "google.golang.org/grpc/stats" 24package stats // import "google.golang.org/grpc/stats"
23 25
24import ( 26import (
27 "context"
25 "net" 28 "net"
26 "time" 29 "time"
27) 30)
@@ -131,8 +134,6 @@ func (s *OutPayload) isRPCStats() {}
131type OutHeader struct { 134type OutHeader struct {
132 // Client is true if this OutHeader is from client side. 135 // Client is true if this OutHeader is from client side.
133 Client bool 136 Client bool
134 // WireLength is the wire length of header.
135 WireLength int
136 137
137 // The following fields are valid only if Client is true. 138 // The following fields are valid only if Client is true.
138 // FullMethod is the full RPC method string, i.e., /package.service/method. 139 // FullMethod is the full RPC method string, i.e., /package.service/method.
@@ -167,6 +168,8 @@ func (s *OutTrailer) isRPCStats() {}
167type End struct { 168type End struct {
168 // Client is true if this End is from client side. 169 // Client is true if this End is from client side.
169 Client bool 170 Client bool
171 // BeginTime is the time when the RPC began.
172 BeginTime time.Time
170 // EndTime is the time when the RPC ends. 173 // EndTime is the time when the RPC ends.
171 EndTime time.Time 174 EndTime time.Time
172 // Error is the error the RPC ended with. It is an error generated from 175 // Error is the error the RPC ended with. It is an error generated from
@@ -208,3 +211,85 @@ type ConnEnd struct {
208func (s *ConnEnd) IsClient() bool { return s.Client } 211func (s *ConnEnd) IsClient() bool { return s.Client }
209 212
210func (s *ConnEnd) isConnStats() {} 213func (s *ConnEnd) isConnStats() {}
214
215type incomingTagsKey struct{}
216type outgoingTagsKey struct{}
217
218// SetTags attaches stats tagging data to the context, which will be sent in
219// the outgoing RPC with the header grpc-tags-bin. Subsequent calls to
220// SetTags will overwrite the values from earlier calls.
221//
222// NOTE: this is provided only for backward compatibility with existing clients
223// and will likely be removed in an upcoming release. New uses should transmit
224// this type of data using metadata with a different, non-reserved (i.e. does
225// not begin with "grpc-") header name.
226func SetTags(ctx context.Context, b []byte) context.Context {
227 return context.WithValue(ctx, outgoingTagsKey{}, b)
228}
229
230// Tags returns the tags from the context for the inbound RPC.
231//
232// NOTE: this is provided only for backward compatibility with existing clients
233// and will likely be removed in an upcoming release. New uses should transmit
234// this type of data using metadata with a different, non-reserved (i.e. does
235// not begin with "grpc-") header name.
236func Tags(ctx context.Context) []byte {
237 b, _ := ctx.Value(incomingTagsKey{}).([]byte)
238 return b
239}
240
241// SetIncomingTags attaches stats tagging data to the context, to be read by
242// the application (not sent in outgoing RPCs).
243//
244// This is intended for gRPC-internal use ONLY.
245func SetIncomingTags(ctx context.Context, b []byte) context.Context {
246 return context.WithValue(ctx, incomingTagsKey{}, b)
247}
248
249// OutgoingTags returns the tags from the context for the outbound RPC.
250//
251// This is intended for gRPC-internal use ONLY.
252func OutgoingTags(ctx context.Context) []byte {
253 b, _ := ctx.Value(outgoingTagsKey{}).([]byte)
254 return b
255}
256
257type incomingTraceKey struct{}
258type outgoingTraceKey struct{}
259
260// SetTrace attaches stats tagging data to the context, which will be sent in
261// the outgoing RPC with the header grpc-trace-bin. Subsequent calls to
262// SetTrace will overwrite the values from earlier calls.
263//
264// NOTE: this is provided only for backward compatibility with existing clients
265// and will likely be removed in an upcoming release. New uses should transmit
266// this type of data using metadata with a different, non-reserved (i.e. does
267// not begin with "grpc-") header name.
268func SetTrace(ctx context.Context, b []byte) context.Context {
269 return context.WithValue(ctx, outgoingTraceKey{}, b)
270}
271
272// Trace returns the trace from the context for the inbound RPC.
273//
274// NOTE: this is provided only for backward compatibility with existing clients
275// and will likely be removed in an upcoming release. New uses should transmit
276// this type of data using metadata with a different, non-reserved (i.e. does
277// not begin with "grpc-") header name.
278func Trace(ctx context.Context) []byte {
279 b, _ := ctx.Value(incomingTraceKey{}).([]byte)
280 return b
281}
282
283// SetIncomingTrace attaches stats tagging data to the context, to be read by
284// the application (not sent in outgoing RPCs). It is intended for
285// gRPC-internal use.
286func SetIncomingTrace(ctx context.Context, b []byte) context.Context {
287 return context.WithValue(ctx, incomingTraceKey{}, b)
288}
289
290// OutgoingTrace returns the trace from the context for the outbound RPC. It is
291// intended for gRPC-internal use.
292func OutgoingTrace(ctx context.Context) []byte {
293 b, _ := ctx.Value(outgoingTraceKey{}).([]byte)
294 return b
295}
diff --git a/vendor/google.golang.org/grpc/status/status.go b/vendor/google.golang.org/grpc/status/status.go
index 871dc4b..ed36681 100644
--- a/vendor/google.golang.org/grpc/status/status.go
+++ b/vendor/google.golang.org/grpc/status/status.go
@@ -28,6 +28,7 @@
28package status 28package status
29 29
30import ( 30import (
31 "context"
31 "errors" 32 "errors"
32 "fmt" 33 "fmt"
33 34
@@ -46,7 +47,7 @@ func (se *statusError) Error() string {
46 return fmt.Sprintf("rpc error: code = %s desc = %s", codes.Code(p.GetCode()), p.GetMessage()) 47 return fmt.Sprintf("rpc error: code = %s desc = %s", codes.Code(p.GetCode()), p.GetMessage())
47} 48}
48 49
49func (se *statusError) status() *Status { 50func (se *statusError) GRPCStatus() *Status {
50 return &Status{s: (*spb.Status)(se)} 51 return &Status{s: (*spb.Status)(se)}
51} 52}
52 53
@@ -120,15 +121,25 @@ func FromProto(s *spb.Status) *Status {
120} 121}
121 122
122// FromError returns a Status representing err if it was produced from this 123// FromError returns a Status representing err if it was produced from this
123// package, otherwise it returns nil, false. 124// package or has a method `GRPCStatus() *Status`. Otherwise, ok is false and a
125// Status is returned with codes.Unknown and the original error message.
124func FromError(err error) (s *Status, ok bool) { 126func FromError(err error) (s *Status, ok bool) {
125 if err == nil { 127 if err == nil {
126 return &Status{s: &spb.Status{Code: int32(codes.OK)}}, true 128 return &Status{s: &spb.Status{Code: int32(codes.OK)}}, true
127 } 129 }
128 if s, ok := err.(*statusError); ok { 130 if se, ok := err.(interface {
129 return s.status(), true 131 GRPCStatus() *Status
132 }); ok {
133 return se.GRPCStatus(), true
130 } 134 }
131 return nil, false 135 return New(codes.Unknown, err.Error()), false
136}
137
138// Convert is a convenience function which removes the need to handle the
139// boolean return value from FromError.
140func Convert(err error) *Status {
141 s, _ := FromError(err)
142 return s
132} 143}
133 144
134// WithDetails returns a new status with the provided details messages appended to the status. 145// WithDetails returns a new status with the provided details messages appended to the status.
@@ -166,3 +177,34 @@ func (s *Status) Details() []interface{} {
166 } 177 }
167 return details 178 return details
168} 179}
180
181// Code returns the Code of the error if it is a Status error, codes.OK if err
182// is nil, or codes.Unknown otherwise.
183func Code(err error) codes.Code {
184 // Don't use FromError to avoid allocation of OK status.
185 if err == nil {
186 return codes.OK
187 }
188 if se, ok := err.(interface {
189 GRPCStatus() *Status
190 }); ok {
191 return se.GRPCStatus().Code()
192 }
193 return codes.Unknown
194}
195
196// FromContextError converts a context error into a Status. It returns a
197// Status with codes.OK if err is nil, or a Status with codes.Unknown if err is
198// non-nil and not a context error.
199func FromContextError(err error) *Status {
200 switch err {
201 case nil:
202 return New(codes.OK, "")
203 case context.DeadlineExceeded:
204 return New(codes.DeadlineExceeded, err.Error())
205 case context.Canceled:
206 return New(codes.Canceled, err.Error())
207 default:
208 return New(codes.Unknown, err.Error())
209 }
210}
diff --git a/vendor/google.golang.org/grpc/stream.go b/vendor/google.golang.org/grpc/stream.go
index 1c621ba..d06279a 100644
--- a/vendor/google.golang.org/grpc/stream.go
+++ b/vendor/google.golang.org/grpc/stream.go
@@ -19,24 +19,35 @@
19package grpc 19package grpc
20 20
21import ( 21import (
22 "bytes" 22 "context"
23 "errors" 23 "errors"
24 "io" 24 "io"
25 "math"
26 "strconv"
25 "sync" 27 "sync"
26 "time" 28 "time"
27 29
28 "golang.org/x/net/context"
29 "golang.org/x/net/trace" 30 "golang.org/x/net/trace"
31 "google.golang.org/grpc/balancer"
30 "google.golang.org/grpc/codes" 32 "google.golang.org/grpc/codes"
33 "google.golang.org/grpc/connectivity"
34 "google.golang.org/grpc/encoding"
35 "google.golang.org/grpc/grpclog"
36 "google.golang.org/grpc/internal/binarylog"
37 "google.golang.org/grpc/internal/channelz"
38 "google.golang.org/grpc/internal/grpcrand"
39 "google.golang.org/grpc/internal/transport"
31 "google.golang.org/grpc/metadata" 40 "google.golang.org/grpc/metadata"
32 "google.golang.org/grpc/peer" 41 "google.golang.org/grpc/peer"
33 "google.golang.org/grpc/stats" 42 "google.golang.org/grpc/stats"
34 "google.golang.org/grpc/status" 43 "google.golang.org/grpc/status"
35 "google.golang.org/grpc/transport"
36) 44)
37 45
38// StreamHandler defines the handler called by gRPC server to complete the 46// StreamHandler defines the handler called by gRPC server to complete the
39// execution of a streaming RPC. 47// execution of a streaming RPC. If a StreamHandler returns an error, it
48// should be produced by the status package, or else gRPC will use
49// codes.Unknown as the status code and err.Error() as the status message
50// of the RPC.
40type StreamHandler func(srv interface{}, stream ServerStream) error 51type StreamHandler func(srv interface{}, stream ServerStream) error
41 52
42// StreamDesc represents a streaming RPC service's method specification. 53// StreamDesc represents a streaming RPC service's method specification.
@@ -50,30 +61,21 @@ type StreamDesc struct {
50} 61}
51 62
52// Stream defines the common interface a client or server stream has to satisfy. 63// Stream defines the common interface a client or server stream has to satisfy.
64//
65// Deprecated: See ClientStream and ServerStream documentation instead.
53type Stream interface { 66type Stream interface {
54 // Context returns the context for this stream. 67 // Deprecated: See ClientStream and ServerStream documentation instead.
55 Context() context.Context 68 Context() context.Context
56 // SendMsg blocks until it sends m, the stream is done or the stream 69 // Deprecated: See ClientStream and ServerStream documentation instead.
57 // breaks.
58 // On error, it aborts the stream and returns an RPC status on client
59 // side. On server side, it simply returns the error to the caller.
60 // SendMsg is called by generated code. Also Users can call SendMsg
61 // directly when it is really needed in their use cases.
62 // It's safe to have a goroutine calling SendMsg and another goroutine calling
63 // recvMsg on the same stream at the same time.
64 // But it is not safe to call SendMsg on the same stream in different goroutines.
65 SendMsg(m interface{}) error 70 SendMsg(m interface{}) error
66 // RecvMsg blocks until it receives a message or the stream is 71 // Deprecated: See ClientStream and ServerStream documentation instead.
67 // done. On client side, it returns io.EOF when the stream is done. On
68 // any other error, it aborts the stream and returns an RPC status. On
69 // server side, it simply returns the error to the caller.
70 // It's safe to have a goroutine calling SendMsg and another goroutine calling
71 // recvMsg on the same stream at the same time.
72 // But it is not safe to call RecvMsg on the same stream in different goroutines.
73 RecvMsg(m interface{}) error 72 RecvMsg(m interface{}) error
74} 73}
75 74
76// ClientStream defines the interface a client stream has to satisfy. 75// ClientStream defines the client-side behavior of a streaming RPC.
76//
77// All errors returned from ClientStream methods are compatible with the
78// status package.
77type ClientStream interface { 79type ClientStream interface {
78 // Header returns the header metadata received from the server if there 80 // Header returns the header metadata received from the server if there
79 // is any. It blocks if the metadata is not ready to read. 81 // is any. It blocks if the metadata is not ready to read.
@@ -83,62 +85,147 @@ type ClientStream interface {
83 // stream.Recv has returned a non-nil error (including io.EOF). 85 // stream.Recv has returned a non-nil error (including io.EOF).
84 Trailer() metadata.MD 86 Trailer() metadata.MD
85 // CloseSend closes the send direction of the stream. It closes the stream 87 // CloseSend closes the send direction of the stream. It closes the stream
86 // when non-nil error is met. 88 // when non-nil error is met. It is also not safe to call CloseSend
89 // concurrently with SendMsg.
87 CloseSend() error 90 CloseSend() error
88 // Stream.SendMsg() may return a non-nil error when something wrong happens sending 91 // Context returns the context for this stream.
89 // the request. The returned error indicates the status of this sending, not the final 92 //
90 // status of the RPC. 93 // It should not be called until after Header or RecvMsg has returned. Once
91 // Always call Stream.RecvMsg() to get the final status if you care about the status of 94 // called, subsequent client-side retries are disabled.
92 // the RPC. 95 Context() context.Context
93 Stream 96 // SendMsg is generally called by generated code. On error, SendMsg aborts
97 // the stream. If the error was generated by the client, the status is
98 // returned directly; otherwise, io.EOF is returned and the status of
99 // the stream may be discovered using RecvMsg.
100 //
101 // SendMsg blocks until:
102 // - There is sufficient flow control to schedule m with the transport, or
103 // - The stream is done, or
104 // - The stream breaks.
105 //
106 // SendMsg does not wait until the message is received by the server. An
107 // untimely stream closure may result in lost messages. To ensure delivery,
108 // users should ensure the RPC completed successfully using RecvMsg.
109 //
110 // It is safe to have a goroutine calling SendMsg and another goroutine
111 // calling RecvMsg on the same stream at the same time, but it is not safe
112 // to call SendMsg on the same stream in different goroutines. It is also
113 // not safe to call CloseSend concurrently with SendMsg.
114 SendMsg(m interface{}) error
115 // RecvMsg blocks until it receives a message into m or the stream is
116 // done. It returns io.EOF when the stream completes successfully. On
117 // any other error, the stream is aborted and the error contains the RPC
118 // status.
119 //
120 // It is safe to have a goroutine calling SendMsg and another goroutine
121 // calling RecvMsg on the same stream at the same time, but it is not
122 // safe to call RecvMsg on the same stream in different goroutines.
123 RecvMsg(m interface{}) error
94} 124}
95 125
96// NewClientStream creates a new Stream for the client side. This is called 126// NewStream creates a new Stream for the client side. This is typically
97// by generated code. 127// called by generated code. ctx is used for the lifetime of the stream.
98func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (_ ClientStream, err error) { 128//
129// To ensure resources are not leaked due to the stream returned, one of the following
130// actions must be performed:
131//
132// 1. Call Close on the ClientConn.
133// 2. Cancel the context provided.
134// 3. Call RecvMsg until a non-nil error is returned. A protobuf-generated
135// client-streaming RPC, for instance, might use the helper function
136// CloseAndRecv (note that CloseSend does not Recv, therefore is not
137// guaranteed to release all resources).
138// 4. Receive a non-nil, non-io.EOF error from Header or SendMsg.
139//
140// If none of the above happen, a goroutine and a context will be leaked, and grpc
141// will not call the optionally-configured stats handler with a stats.End message.
142func (cc *ClientConn) NewStream(ctx context.Context, desc *StreamDesc, method string, opts ...CallOption) (ClientStream, error) {
143 // allow interceptor to see all applicable call options, which means those
144 // configured as defaults from dial option as well as per-call options
145 opts = combine(cc.dopts.callOptions, opts)
146
99 if cc.dopts.streamInt != nil { 147 if cc.dopts.streamInt != nil {
100 return cc.dopts.streamInt(ctx, desc, cc, method, newClientStream, opts...) 148 return cc.dopts.streamInt(ctx, desc, cc, method, newClientStream, opts...)
101 } 149 }
102 return newClientStream(ctx, desc, cc, method, opts...) 150 return newClientStream(ctx, desc, cc, method, opts...)
103} 151}
104 152
153// NewClientStream is a wrapper for ClientConn.NewStream.
154func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (ClientStream, error) {
155 return cc.NewStream(ctx, desc, method, opts...)
156}
157
105func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (_ ClientStream, err error) { 158func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (_ ClientStream, err error) {
106 var ( 159 if channelz.IsOn() {
107 t transport.ClientTransport 160 cc.incrCallsStarted()
108 s *transport.Stream 161 defer func() {
109 put func() 162 if err != nil {
110 cancel context.CancelFunc 163 cc.incrCallsFailed()
111 ) 164 }
112 c := defaultCallInfo 165 }()
166 }
167 c := defaultCallInfo()
168 // Provide an opportunity for the first RPC to see the first service config
169 // provided by the resolver.
170 if err := cc.waitForResolvedAddrs(ctx); err != nil {
171 return nil, err
172 }
113 mc := cc.GetMethodConfig(method) 173 mc := cc.GetMethodConfig(method)
114 if mc.WaitForReady != nil { 174 if mc.WaitForReady != nil {
115 c.failFast = !*mc.WaitForReady 175 c.failFast = !*mc.WaitForReady
116 } 176 }
117 177
118 if mc.Timeout != nil { 178 // Possible context leak:
179 // The cancel function for the child context we create will only be called
180 // when RecvMsg returns a non-nil error, if the ClientConn is closed, or if
181 // an error is generated by SendMsg.
182 // https://github.com/grpc/grpc-go/issues/1818.
183 var cancel context.CancelFunc
184 if mc.Timeout != nil && *mc.Timeout >= 0 {
119 ctx, cancel = context.WithTimeout(ctx, *mc.Timeout) 185 ctx, cancel = context.WithTimeout(ctx, *mc.Timeout)
186 } else {
187 ctx, cancel = context.WithCancel(ctx)
120 } 188 }
189 defer func() {
190 if err != nil {
191 cancel()
192 }
193 }()
121 194
122 opts = append(cc.dopts.callOptions, opts...)
123 for _, o := range opts { 195 for _, o := range opts {
124 if err := o.before(&c); err != nil { 196 if err := o.before(c); err != nil {
125 return nil, toRPCErr(err) 197 return nil, toRPCErr(err)
126 } 198 }
127 } 199 }
128 c.maxSendMessageSize = getMaxSize(mc.MaxReqSize, c.maxSendMessageSize, defaultClientMaxSendMessageSize) 200 c.maxSendMessageSize = getMaxSize(mc.MaxReqSize, c.maxSendMessageSize, defaultClientMaxSendMessageSize)
129 c.maxReceiveMessageSize = getMaxSize(mc.MaxRespSize, c.maxReceiveMessageSize, defaultClientMaxReceiveMessageSize) 201 c.maxReceiveMessageSize = getMaxSize(mc.MaxRespSize, c.maxReceiveMessageSize, defaultClientMaxReceiveMessageSize)
202 if err := setCallInfoCodec(c); err != nil {
203 return nil, err
204 }
130 205
131 callHdr := &transport.CallHdr{ 206 callHdr := &transport.CallHdr{
132 Host: cc.authority, 207 Host: cc.authority,
133 Method: method, 208 Method: method,
134 // If it's not client streaming, we should already have the request to be sent, 209 ContentSubtype: c.contentSubtype,
135 // so we don't flush the header. 210 }
136 // If it's client streaming, the user may never send a request or send it any 211
137 // time soon, so we ask the transport to flush the header. 212 // Set our outgoing compression according to the UseCompressor CallOption, if
138 Flush: desc.ClientStreams, 213 // set. In that case, also find the compressor from the encoding package.
139 } 214 // Otherwise, use the compressor configured by the WithCompressor DialOption,
140 if cc.dopts.cp != nil { 215 // if set.
216 var cp Compressor
217 var comp encoding.Compressor
218 if ct := c.compressorType; ct != "" {
219 callHdr.SendCompress = ct
220 if ct != encoding.Identity {
221 comp = encoding.GetCompressor(ct)
222 if comp == nil {
223 return nil, status.Errorf(codes.Internal, "grpc: Compressor is not installed for requested grpc-encoding %q", ct)
224 }
225 }
226 } else if cc.dopts.cp != nil {
141 callHdr.SendCompress = cc.dopts.cp.Type() 227 callHdr.SendCompress = cc.dopts.cp.Type()
228 cp = cc.dopts.cp
142 } 229 }
143 if c.creds != nil { 230 if c.creds != nil {
144 callHdr.Creds = c.creds 231 callHdr.Creds = c.creds
@@ -152,380 +239,1019 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth
152 } 239 }
153 trInfo.tr.LazyLog(&trInfo.firstLine, false) 240 trInfo.tr.LazyLog(&trInfo.firstLine, false)
154 ctx = trace.NewContext(ctx, trInfo.tr) 241 ctx = trace.NewContext(ctx, trInfo.tr)
155 defer func() {
156 if err != nil {
157 // Need to call tr.finish() if error is returned.
158 // Because tr will not be returned to caller.
159 trInfo.tr.LazyPrintf("RPC: [%v]", err)
160 trInfo.tr.SetError()
161 trInfo.tr.Finish()
162 }
163 }()
164 } 242 }
165 ctx = newContextWithRPCInfo(ctx) 243 ctx = newContextWithRPCInfo(ctx, c.failFast)
166 sh := cc.dopts.copts.StatsHandler 244 sh := cc.dopts.copts.StatsHandler
245 var beginTime time.Time
167 if sh != nil { 246 if sh != nil {
168 ctx = sh.TagRPC(ctx, &stats.RPCTagInfo{FullMethodName: method, FailFast: c.failFast}) 247 ctx = sh.TagRPC(ctx, &stats.RPCTagInfo{FullMethodName: method, FailFast: c.failFast})
248 beginTime = time.Now()
169 begin := &stats.Begin{ 249 begin := &stats.Begin{
170 Client: true, 250 Client: true,
171 BeginTime: time.Now(), 251 BeginTime: beginTime,
172 FailFast: c.failFast, 252 FailFast: c.failFast,
173 } 253 }
174 sh.HandleRPC(ctx, begin) 254 sh.HandleRPC(ctx, begin)
175 defer func() {
176 if err != nil {
177 // Only handle end stats if err != nil.
178 end := &stats.End{
179 Client: true,
180 Error: err,
181 }
182 sh.HandleRPC(ctx, end)
183 }
184 }()
185 } 255 }
186 gopts := BalancerGetOptions{ 256
187 BlockingWait: !c.failFast, 257 cs := &clientStream{
258 callHdr: callHdr,
259 ctx: ctx,
260 methodConfig: &mc,
261 opts: opts,
262 callInfo: c,
263 cc: cc,
264 desc: desc,
265 codec: c.codec,
266 cp: cp,
267 comp: comp,
268 cancel: cancel,
269 beginTime: beginTime,
270 firstAttempt: true,
271 }
272 if !cc.dopts.disableRetry {
273 cs.retryThrottler = cc.retryThrottler.Load().(*retryThrottler)
188 } 274 }
189 for { 275 cs.binlog = binarylog.GetMethodLogger(method)
190 t, put, err = cc.getTransport(ctx, gopts)
191 if err != nil {
192 // TODO(zhaoq): Probably revisit the error handling.
193 if _, ok := status.FromError(err); ok {
194 return nil, err
195 }
196 if err == errConnClosing || err == errConnUnavailable {
197 if c.failFast {
198 return nil, Errorf(codes.Unavailable, "%v", err)
199 }
200 continue
201 }
202 // All the other errors are treated as Internal errors.
203 return nil, Errorf(codes.Internal, "%v", err)
204 }
205 276
206 s, err = t.NewStream(ctx, callHdr) 277 cs.callInfo.stream = cs
207 if err != nil { 278 // Only this initial attempt has stats/tracing.
208 if _, ok := err.(transport.ConnectionError); ok && put != nil { 279 // TODO(dfawley): move to newAttempt when per-attempt stats are implemented.
209 // If error is connection error, transport was sending data on wire, 280 if err := cs.newAttemptLocked(sh, trInfo); err != nil {
210 // and we are not sure if anything has been sent on wire. 281 cs.finish(err)
211 // If error is not connection error, we are sure nothing has been sent. 282 return nil, err
212 updateRPCInfoInContext(ctx, rpcInfo{bytesSent: true, bytesReceived: false}) 283 }
213 } 284
214 if put != nil { 285 op := func(a *csAttempt) error { return a.newStream() }
215 put() 286 if err := cs.withRetry(op, func() { cs.bufferForRetryLocked(0, op) }); err != nil {
216 put = nil 287 cs.finish(err)
217 } 288 return nil, err
218 if _, ok := err.(transport.ConnectionError); (ok || err == transport.ErrStreamDrain) && !c.failFast { 289 }
219 continue 290
291 if cs.binlog != nil {
292 md, _ := metadata.FromOutgoingContext(ctx)
293 logEntry := &binarylog.ClientHeader{
294 OnClientSide: true,
295 Header: md,
296 MethodName: method,
297 Authority: cs.cc.authority,
298 }
299 if deadline, ok := ctx.Deadline(); ok {
300 logEntry.Timeout = deadline.Sub(time.Now())
301 if logEntry.Timeout < 0 {
302 logEntry.Timeout = 0
220 } 303 }
221 return nil, toRPCErr(err)
222 } 304 }
223 break 305 cs.binlog.Log(logEntry)
224 } 306 }
225 // Set callInfo.peer object from stream's context. 307
226 if peer, ok := peer.FromContext(s.Context()); ok { 308 if desc != unaryStreamDesc {
227 c.peer = peer 309 // Listen on cc and stream contexts to cleanup when the user closes the
310 // ClientConn or cancels the stream context. In all other cases, an error
311 // should already be injected into the recv buffer by the transport, which
312 // the client will eventually receive, and then we will cancel the stream's
313 // context in clientStream.finish.
314 go func() {
315 select {
316 case <-cc.ctx.Done():
317 cs.finish(ErrClientConnClosing)
318 case <-ctx.Done():
319 cs.finish(toRPCErr(ctx.Err()))
320 }
321 }()
228 } 322 }
229 cs := &clientStream{
230 opts: opts,
231 c: c,
232 desc: desc,
233 codec: cc.dopts.codec,
234 cp: cc.dopts.cp,
235 dc: cc.dopts.dc,
236 cancel: cancel,
237
238 put: put,
239 t: t,
240 s: s,
241 p: &parser{r: s},
242
243 tracing: EnableTracing,
244 trInfo: trInfo,
245
246 statsCtx: ctx,
247 statsHandler: cc.dopts.copts.StatsHandler,
248 }
249 if cc.dopts.cp != nil {
250 cs.cbuf = new(bytes.Buffer)
251 }
252 // Listen on ctx.Done() to detect cancellation and s.Done() to detect normal termination
253 // when there is no pending I/O operations on this stream.
254 go func() {
255 select {
256 case <-t.Error():
257 // Incur transport error, simply exit.
258 case <-cc.ctx.Done():
259 cs.finish(ErrClientConnClosing)
260 cs.closeTransportStream(ErrClientConnClosing)
261 case <-s.Done():
262 // TODO: The trace of the RPC is terminated here when there is no pending
263 // I/O, which is probably not the optimal solution.
264 cs.finish(s.Status().Err())
265 cs.closeTransportStream(nil)
266 case <-s.GoAway():
267 cs.finish(errConnDrain)
268 cs.closeTransportStream(errConnDrain)
269 case <-s.Context().Done():
270 err := s.Context().Err()
271 cs.finish(err)
272 cs.closeTransportStream(transport.ContextErr(err))
273 }
274 }()
275 return cs, nil 323 return cs, nil
276} 324}
277 325
326func (cs *clientStream) newAttemptLocked(sh stats.Handler, trInfo traceInfo) error {
327 cs.attempt = &csAttempt{
328 cs: cs,
329 dc: cs.cc.dopts.dc,
330 statsHandler: sh,
331 trInfo: trInfo,
332 }
333
334 if err := cs.ctx.Err(); err != nil {
335 return toRPCErr(err)
336 }
337 t, done, err := cs.cc.getTransport(cs.ctx, cs.callInfo.failFast, cs.callHdr.Method)
338 if err != nil {
339 return err
340 }
341 cs.attempt.t = t
342 cs.attempt.done = done
343 return nil
344}
345
346func (a *csAttempt) newStream() error {
347 cs := a.cs
348 cs.callHdr.PreviousAttempts = cs.numRetries
349 s, err := a.t.NewStream(cs.ctx, cs.callHdr)
350 if err != nil {
351 return toRPCErr(err)
352 }
353 cs.attempt.s = s
354 cs.attempt.p = &parser{r: s}
355 return nil
356}
357
278// clientStream implements a client side Stream. 358// clientStream implements a client side Stream.
279type clientStream struct { 359type clientStream struct {
280 opts []CallOption 360 callHdr *transport.CallHdr
281 c callInfo 361 opts []CallOption
282 t transport.ClientTransport 362 callInfo *callInfo
283 s *transport.Stream 363 cc *ClientConn
284 p *parser 364 desc *StreamDesc
285 desc *StreamDesc 365
286 codec Codec 366 codec baseCodec
287 cp Compressor 367 cp Compressor
288 cbuf *bytes.Buffer 368 comp encoding.Compressor
289 dc Decompressor 369
290 cancel context.CancelFunc 370 cancel context.CancelFunc // cancels all attempts
371
372 sentLast bool // sent an end stream
373 beginTime time.Time
374
375 methodConfig *MethodConfig
376
377 ctx context.Context // the application's context, wrapped by stats/tracing
291 378
292 tracing bool // set to EnableTracing when the clientStream is created. 379 retryThrottler *retryThrottler // The throttler active when the RPC began.
293 380
294 mu sync.Mutex 381 binlog *binarylog.MethodLogger // Binary logger, can be nil.
295 put func() 382 // serverHeaderBinlogged is a boolean for whether server header has been
296 closed bool 383 // logged. Server header will be logged when the first time one of those
297 finished bool 384 // happens: stream.Header(), stream.Recv().
298 // trInfo.tr is set when the clientStream is created (if EnableTracing is true), 385 //
299 // and is set to nil when the clientStream's finish method is called. 386 // It's only read and used by Recv() and Header(), so it doesn't need to be
387 // synchronized.
388 serverHeaderBinlogged bool
389
390 mu sync.Mutex
391 firstAttempt bool // if true, transparent retry is valid
392 numRetries int // exclusive of transparent retry attempt(s)
393 numRetriesSincePushback int // retries since pushback; to reset backoff
394 finished bool // TODO: replace with atomic cmpxchg or sync.Once?
395 attempt *csAttempt // the active client stream attempt
396 // TODO(hedging): hedging will have multiple attempts simultaneously.
397 committed bool // active attempt committed for retry?
398 buffer []func(a *csAttempt) error // operations to replay on retry
399 bufferSize int // current size of buffer
400}
401
402// csAttempt implements a single transport stream attempt within a
403// clientStream.
404type csAttempt struct {
405 cs *clientStream
406 t transport.ClientTransport
407 s *transport.Stream
408 p *parser
409 done func(balancer.DoneInfo)
410
411 finished bool
412 dc Decompressor
413 decomp encoding.Compressor
414 decompSet bool
415
416 mu sync.Mutex // guards trInfo.tr
417 // trInfo.tr is set when created (if EnableTracing is true),
418 // and cleared when the finish method is called.
300 trInfo traceInfo 419 trInfo traceInfo
301 420
302 // statsCtx keeps the user context for stats handling.
303 // All stats collection should use the statsCtx (instead of the stream context)
304 // so that all the generated stats for a particular RPC can be associated in the processing phase.
305 statsCtx context.Context
306 statsHandler stats.Handler 421 statsHandler stats.Handler
307} 422}
308 423
424func (cs *clientStream) commitAttemptLocked() {
425 cs.committed = true
426 cs.buffer = nil
427}
428
429func (cs *clientStream) commitAttempt() {
430 cs.mu.Lock()
431 cs.commitAttemptLocked()
432 cs.mu.Unlock()
433}
434
435// shouldRetry returns nil if the RPC should be retried; otherwise it returns
436// the error that should be returned by the operation.
437func (cs *clientStream) shouldRetry(err error) error {
438 if cs.attempt.s == nil && !cs.callInfo.failFast {
439 // In the event of any error from NewStream (attempt.s == nil), we
440 // never attempted to write anything to the wire, so we can retry
441 // indefinitely for non-fail-fast RPCs.
442 return nil
443 }
444 if cs.finished || cs.committed {
445 // RPC is finished or committed; cannot retry.
446 return err
447 }
448 // Wait for the trailers.
449 if cs.attempt.s != nil {
450 <-cs.attempt.s.Done()
451 }
452 if cs.firstAttempt && !cs.callInfo.failFast && (cs.attempt.s == nil || cs.attempt.s.Unprocessed()) {
453 // First attempt, wait-for-ready, stream unprocessed: transparently retry.
454 cs.firstAttempt = false
455 return nil
456 }
457 cs.firstAttempt = false
458 if cs.cc.dopts.disableRetry {
459 return err
460 }
461
462 pushback := 0
463 hasPushback := false
464 if cs.attempt.s != nil {
465 if to, toErr := cs.attempt.s.TrailersOnly(); toErr != nil || !to {
466 return err
467 }
468
469 // TODO(retry): Move down if the spec changes to not check server pushback
470 // before considering this a failure for throttling.
471 sps := cs.attempt.s.Trailer()["grpc-retry-pushback-ms"]
472 if len(sps) == 1 {
473 var e error
474 if pushback, e = strconv.Atoi(sps[0]); e != nil || pushback < 0 {
475 grpclog.Infof("Server retry pushback specified to abort (%q).", sps[0])
476 cs.retryThrottler.throttle() // This counts as a failure for throttling.
477 return err
478 }
479 hasPushback = true
480 } else if len(sps) > 1 {
481 grpclog.Warningf("Server retry pushback specified multiple values (%q); not retrying.", sps)
482 cs.retryThrottler.throttle() // This counts as a failure for throttling.
483 return err
484 }
485 }
486
487 var code codes.Code
488 if cs.attempt.s != nil {
489 code = cs.attempt.s.Status().Code()
490 } else {
491 code = status.Convert(err).Code()
492 }
493
494 rp := cs.methodConfig.retryPolicy
495 if rp == nil || !rp.retryableStatusCodes[code] {
496 return err
497 }
498
499 // Note: the ordering here is important; we count this as a failure
500 // only if the code matched a retryable code.
501 if cs.retryThrottler.throttle() {
502 return err
503 }
504 if cs.numRetries+1 >= rp.maxAttempts {
505 return err
506 }
507
508 var dur time.Duration
509 if hasPushback {
510 dur = time.Millisecond * time.Duration(pushback)
511 cs.numRetriesSincePushback = 0
512 } else {
513 fact := math.Pow(rp.backoffMultiplier, float64(cs.numRetriesSincePushback))
514 cur := float64(rp.initialBackoff) * fact
515 if max := float64(rp.maxBackoff); cur > max {
516 cur = max
517 }
518 dur = time.Duration(grpcrand.Int63n(int64(cur)))
519 cs.numRetriesSincePushback++
520 }
521
522 // TODO(dfawley): we could eagerly fail here if dur puts us past the
523 // deadline, but unsure if it is worth doing.
524 t := time.NewTimer(dur)
525 select {
526 case <-t.C:
527 cs.numRetries++
528 return nil
529 case <-cs.ctx.Done():
530 t.Stop()
531 return status.FromContextError(cs.ctx.Err()).Err()
532 }
533}
534
535// Returns nil if a retry was performed and succeeded; error otherwise.
536func (cs *clientStream) retryLocked(lastErr error) error {
537 for {
538 cs.attempt.finish(lastErr)
539 if err := cs.shouldRetry(lastErr); err != nil {
540 cs.commitAttemptLocked()
541 return err
542 }
543 if err := cs.newAttemptLocked(nil, traceInfo{}); err != nil {
544 return err
545 }
546 if lastErr = cs.replayBufferLocked(); lastErr == nil {
547 return nil
548 }
549 }
550}
551
309func (cs *clientStream) Context() context.Context { 552func (cs *clientStream) Context() context.Context {
310 return cs.s.Context() 553 cs.commitAttempt()
554 // No need to lock before using attempt, since we know it is committed and
555 // cannot change.
556 return cs.attempt.s.Context()
557}
558
559func (cs *clientStream) withRetry(op func(a *csAttempt) error, onSuccess func()) error {
560 cs.mu.Lock()
561 for {
562 if cs.committed {
563 cs.mu.Unlock()
564 return op(cs.attempt)
565 }
566 a := cs.attempt
567 cs.mu.Unlock()
568 err := op(a)
569 cs.mu.Lock()
570 if a != cs.attempt {
571 // We started another attempt already.
572 continue
573 }
574 if err == io.EOF {
575 <-a.s.Done()
576 }
577 if err == nil || (err == io.EOF && a.s.Status().Code() == codes.OK) {
578 onSuccess()
579 cs.mu.Unlock()
580 return err
581 }
582 if err := cs.retryLocked(err); err != nil {
583 cs.mu.Unlock()
584 return err
585 }
586 }
311} 587}
312 588
313func (cs *clientStream) Header() (metadata.MD, error) { 589func (cs *clientStream) Header() (metadata.MD, error) {
314 m, err := cs.s.Header() 590 var m metadata.MD
591 err := cs.withRetry(func(a *csAttempt) error {
592 var err error
593 m, err = a.s.Header()
594 return toRPCErr(err)
595 }, cs.commitAttemptLocked)
315 if err != nil { 596 if err != nil {
316 if _, ok := err.(transport.ConnectionError); !ok { 597 cs.finish(err)
317 cs.closeTransportStream(err) 598 return nil, err
599 }
600 if cs.binlog != nil && !cs.serverHeaderBinlogged {
601 // Only log if binary log is on and header has not been logged.
602 logEntry := &binarylog.ServerHeader{
603 OnClientSide: true,
604 Header: m,
605 PeerAddr: nil,
318 } 606 }
607 if peer, ok := peer.FromContext(cs.Context()); ok {
608 logEntry.PeerAddr = peer.Addr
609 }
610 cs.binlog.Log(logEntry)
611 cs.serverHeaderBinlogged = true
319 } 612 }
320 return m, err 613 return m, err
321} 614}
322 615
323func (cs *clientStream) Trailer() metadata.MD { 616func (cs *clientStream) Trailer() metadata.MD {
324 return cs.s.Trailer() 617 // On RPC failure, we never need to retry, because usage requires that
618 // RecvMsg() returned a non-nil error before calling this function is valid.
619 // We would have retried earlier if necessary.
620 //
621 // Commit the attempt anyway, just in case users are not following those
622 // directions -- it will prevent races and should not meaningfully impact
623 // performance.
624 cs.commitAttempt()
625 if cs.attempt.s == nil {
626 return nil
627 }
628 return cs.attempt.s.Trailer()
325} 629}
326 630
327func (cs *clientStream) SendMsg(m interface{}) (err error) { 631func (cs *clientStream) replayBufferLocked() error {
328 if cs.tracing { 632 a := cs.attempt
329 cs.mu.Lock() 633 for _, f := range cs.buffer {
330 if cs.trInfo.tr != nil { 634 if err := f(a); err != nil {
331 cs.trInfo.tr.LazyLog(&payload{sent: true, msg: m}, true) 635 return err
332 } 636 }
333 cs.mu.Unlock()
334 } 637 }
335 // TODO Investigate how to signal the stats handling party. 638 return nil
336 // generate error stats if err != nil && err != io.EOF? 639}
640
641func (cs *clientStream) bufferForRetryLocked(sz int, op func(a *csAttempt) error) {
642 // Note: we still will buffer if retry is disabled (for transparent retries).
643 if cs.committed {
644 return
645 }
646 cs.bufferSize += sz
647 if cs.bufferSize > cs.callInfo.maxRetryRPCBufferSize {
648 cs.commitAttemptLocked()
649 return
650 }
651 cs.buffer = append(cs.buffer, op)
652}
653
654func (cs *clientStream) SendMsg(m interface{}) (err error) {
337 defer func() { 655 defer func() {
338 if err != nil { 656 if err != nil && err != io.EOF {
657 // Call finish on the client stream for errors generated by this SendMsg
658 // call, as these indicate problems created by this client. (Transport
659 // errors are converted to an io.EOF error in csAttempt.sendMsg; the real
660 // error will be returned from RecvMsg eventually in that case, or be
661 // retried.)
339 cs.finish(err) 662 cs.finish(err)
340 } 663 }
341 if err == nil {
342 return
343 }
344 if err == io.EOF {
345 // Specialize the process for server streaming. SendMesg is only called
346 // once when creating the stream object. io.EOF needs to be skipped when
347 // the rpc is early finished (before the stream object is created.).
348 // TODO: It is probably better to move this into the generated code.
349 if !cs.desc.ClientStreams && cs.desc.ServerStreams {
350 err = nil
351 }
352 return
353 }
354 if _, ok := err.(transport.ConnectionError); !ok {
355 cs.closeTransportStream(err)
356 }
357 err = toRPCErr(err)
358 }() 664 }()
359 var outPayload *stats.OutPayload 665 if cs.sentLast {
360 if cs.statsHandler != nil { 666 return status.Errorf(codes.Internal, "SendMsg called after CloseSend")
361 outPayload = &stats.OutPayload{
362 Client: true,
363 }
364 } 667 }
365 out, err := encode(cs.codec, m, cs.cp, cs.cbuf, outPayload) 668 if !cs.desc.ClientStreams {
366 defer func() { 669 cs.sentLast = true
367 if cs.cbuf != nil { 670 }
368 cs.cbuf.Reset() 671 data, err := encode(cs.codec, m)
369 }
370 }()
371 if err != nil { 672 if err != nil {
372 return err 673 return err
373 } 674 }
374 if cs.c.maxSendMessageSize == nil { 675 compData, err := compress(data, cs.cp, cs.comp)
375 return Errorf(codes.Internal, "callInfo maxSendMessageSize field uninitialized(nil)") 676 if err != nil {
677 return err
376 } 678 }
377 if len(out) > *cs.c.maxSendMessageSize { 679 hdr, payload := msgHeader(data, compData)
378 return Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", len(out), *cs.c.maxSendMessageSize) 680 // TODO(dfawley): should we be checking len(data) instead?
681 if len(payload) > *cs.callInfo.maxSendMessageSize {
682 return status.Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", len(payload), *cs.callInfo.maxSendMessageSize)
379 } 683 }
380 err = cs.t.Write(cs.s, out, &transport.Options{Last: false}) 684 msgBytes := data // Store the pointer before setting to nil. For binary logging.
381 if err == nil && outPayload != nil { 685 op := func(a *csAttempt) error {
382 outPayload.SentTime = time.Now() 686 err := a.sendMsg(m, hdr, payload, data)
383 cs.statsHandler.HandleRPC(cs.statsCtx, outPayload) 687 // nil out the message and uncomp when replaying; they are only needed for
688 // stats which is disabled for subsequent attempts.
689 m, data = nil, nil
690 return err
384 } 691 }
385 return err 692 err = cs.withRetry(op, func() { cs.bufferForRetryLocked(len(hdr)+len(payload), op) })
693 if cs.binlog != nil && err == nil {
694 cs.binlog.Log(&binarylog.ClientMessage{
695 OnClientSide: true,
696 Message: msgBytes,
697 })
698 }
699 return
386} 700}
387 701
388func (cs *clientStream) RecvMsg(m interface{}) (err error) { 702func (cs *clientStream) RecvMsg(m interface{}) error {
389 var inPayload *stats.InPayload 703 if cs.binlog != nil && !cs.serverHeaderBinlogged {
390 if cs.statsHandler != nil { 704 // Call Header() to binary log header if it's not already logged.
391 inPayload = &stats.InPayload{ 705 cs.Header()
392 Client: true,
393 }
394 } 706 }
395 if cs.c.maxReceiveMessageSize == nil { 707 var recvInfo *payloadInfo
396 return Errorf(codes.Internal, "callInfo maxReceiveMessageSize field uninitialized(nil)") 708 if cs.binlog != nil {
709 recvInfo = &payloadInfo{}
397 } 710 }
398 err = recv(cs.p, cs.codec, cs.s, cs.dc, m, *cs.c.maxReceiveMessageSize, inPayload) 711 err := cs.withRetry(func(a *csAttempt) error {
399 defer func() { 712 return a.recvMsg(m, recvInfo)
400 // err != nil indicates the termination of the stream. 713 }, cs.commitAttemptLocked)
401 if err != nil { 714 if cs.binlog != nil && err == nil {
402 cs.finish(err) 715 cs.binlog.Log(&binarylog.ServerMessage{
716 OnClientSide: true,
717 Message: recvInfo.uncompressedBytes,
718 })
719 }
720 if err != nil || !cs.desc.ServerStreams {
721 // err != nil or non-server-streaming indicates end of stream.
722 cs.finish(err)
723
724 if cs.binlog != nil {
725 // finish will not log Trailer. Log Trailer here.
726 logEntry := &binarylog.ServerTrailer{
727 OnClientSide: true,
728 Trailer: cs.Trailer(),
729 Err: err,
730 }
731 if logEntry.Err == io.EOF {
732 logEntry.Err = nil
733 }
734 if peer, ok := peer.FromContext(cs.Context()); ok {
735 logEntry.PeerAddr = peer.Addr
736 }
737 cs.binlog.Log(logEntry)
403 } 738 }
404 }() 739 }
740 return err
741}
742
743func (cs *clientStream) CloseSend() error {
744 if cs.sentLast {
745 // TODO: return an error and finish the stream instead, due to API misuse?
746 return nil
747 }
748 cs.sentLast = true
749 op := func(a *csAttempt) error {
750 a.t.Write(a.s, nil, nil, &transport.Options{Last: true})
751 // Always return nil; io.EOF is the only error that might make sense
752 // instead, but there is no need to signal the client to call RecvMsg
753 // as the only use left for the stream after CloseSend is to call
754 // RecvMsg. This also matches historical behavior.
755 return nil
756 }
757 cs.withRetry(op, func() { cs.bufferForRetryLocked(0, op) })
758 if cs.binlog != nil {
759 cs.binlog.Log(&binarylog.ClientHalfClose{
760 OnClientSide: true,
761 })
762 }
763 // We never returned an error here for reasons.
764 return nil
765}
766
767func (cs *clientStream) finish(err error) {
768 if err == io.EOF {
769 // Ending a stream with EOF indicates a success.
770 err = nil
771 }
772 cs.mu.Lock()
773 if cs.finished {
774 cs.mu.Unlock()
775 return
776 }
777 cs.finished = true
778 cs.commitAttemptLocked()
779 cs.mu.Unlock()
780 // For binary logging. only log cancel in finish (could be caused by RPC ctx
781 // canceled or ClientConn closed). Trailer will be logged in RecvMsg.
782 //
783 // Only one of cancel or trailer needs to be logged. In the cases where
784 // users don't call RecvMsg, users must have already canceled the RPC.
785 if cs.binlog != nil && status.Code(err) == codes.Canceled {
786 cs.binlog.Log(&binarylog.Cancel{
787 OnClientSide: true,
788 })
789 }
405 if err == nil { 790 if err == nil {
406 if cs.tracing { 791 cs.retryThrottler.successfulRPC()
407 cs.mu.Lock() 792 }
408 if cs.trInfo.tr != nil { 793 if channelz.IsOn() {
409 cs.trInfo.tr.LazyLog(&payload{sent: false, msg: m}, true) 794 if err != nil {
410 } 795 cs.cc.incrCallsFailed()
411 cs.mu.Unlock() 796 } else {
797 cs.cc.incrCallsSucceeded()
412 } 798 }
413 if inPayload != nil { 799 }
414 cs.statsHandler.HandleRPC(cs.statsCtx, inPayload) 800 if cs.attempt != nil {
801 cs.attempt.finish(err)
802 }
803 // after functions all rely upon having a stream.
804 if cs.attempt.s != nil {
805 for _, o := range cs.opts {
806 o.after(cs.callInfo)
415 } 807 }
416 if !cs.desc.ClientStreams || cs.desc.ServerStreams { 808 }
417 return 809 cs.cancel()
810}
811
812func (a *csAttempt) sendMsg(m interface{}, hdr, payld, data []byte) error {
813 cs := a.cs
814 if EnableTracing {
815 a.mu.Lock()
816 if a.trInfo.tr != nil {
817 a.trInfo.tr.LazyLog(&payload{sent: true, msg: m}, true)
418 } 818 }
419 // Special handling for client streaming rpc. 819 a.mu.Unlock()
420 // This recv expects EOF or errors, so we don't collect inPayload. 820 }
421 if cs.c.maxReceiveMessageSize == nil { 821 if err := a.t.Write(a.s, hdr, payld, &transport.Options{Last: !cs.desc.ClientStreams}); err != nil {
422 return Errorf(codes.Internal, "callInfo maxReceiveMessageSize field uninitialized(nil)") 822 if !cs.desc.ClientStreams {
823 // For non-client-streaming RPCs, we return nil instead of EOF on error
824 // because the generated code requires it. finish is not called; RecvMsg()
825 // will call it with the stream's status independently.
826 return nil
423 } 827 }
424 err = recv(cs.p, cs.codec, cs.s, cs.dc, m, *cs.c.maxReceiveMessageSize, nil) 828 return io.EOF
425 cs.closeTransportStream(err) 829 }
426 if err == nil { 830 if a.statsHandler != nil {
427 return toRPCErr(errors.New("grpc: client streaming protocol violation: get <nil>, want <EOF>")) 831 a.statsHandler.HandleRPC(cs.ctx, outPayload(true, m, data, payld, time.Now()))
832 }
833 if channelz.IsOn() {
834 a.t.IncrMsgSent()
835 }
836 return nil
837}
838
839func (a *csAttempt) recvMsg(m interface{}, payInfo *payloadInfo) (err error) {
840 cs := a.cs
841 if a.statsHandler != nil && payInfo == nil {
842 payInfo = &payloadInfo{}
843 }
844
845 if !a.decompSet {
846 // Block until we receive headers containing received message encoding.
847 if ct := a.s.RecvCompress(); ct != "" && ct != encoding.Identity {
848 if a.dc == nil || a.dc.Type() != ct {
849 // No configured decompressor, or it does not match the incoming
850 // message encoding; attempt to find a registered compressor that does.
851 a.dc = nil
852 a.decomp = encoding.GetCompressor(ct)
853 }
854 } else {
855 // No compression is used; disable our decompressor.
856 a.dc = nil
428 } 857 }
858 // Only initialize this state once per stream.
859 a.decompSet = true
860 }
861 err = recv(a.p, cs.codec, a.s, a.dc, m, *cs.callInfo.maxReceiveMessageSize, payInfo, a.decomp)
862 if err != nil {
429 if err == io.EOF { 863 if err == io.EOF {
430 if se := cs.s.Status().Err(); se != nil { 864 if statusErr := a.s.Status().Err(); statusErr != nil {
431 return se 865 return statusErr
432 } 866 }
433 cs.finish(err) 867 return io.EOF // indicates successful end of stream.
434 return nil
435 } 868 }
436 return toRPCErr(err) 869 return toRPCErr(err)
437 } 870 }
438 if _, ok := err.(transport.ConnectionError); !ok { 871 if EnableTracing {
439 cs.closeTransportStream(err) 872 a.mu.Lock()
873 if a.trInfo.tr != nil {
874 a.trInfo.tr.LazyLog(&payload{sent: false, msg: m}, true)
875 }
876 a.mu.Unlock()
877 }
878 if a.statsHandler != nil {
879 a.statsHandler.HandleRPC(cs.ctx, &stats.InPayload{
880 Client: true,
881 RecvTime: time.Now(),
882 Payload: m,
883 // TODO truncate large payload.
884 Data: payInfo.uncompressedBytes,
885 Length: len(payInfo.uncompressedBytes),
886 })
887 }
888 if channelz.IsOn() {
889 a.t.IncrMsgRecv()
890 }
891 if cs.desc.ServerStreams {
892 // Subsequent messages should be received by subsequent RecvMsg calls.
893 return nil
894 }
895 // Special handling for non-server-stream rpcs.
896 // This recv expects EOF or errors, so we don't collect inPayload.
897 err = recv(a.p, cs.codec, a.s, a.dc, m, *cs.callInfo.maxReceiveMessageSize, nil, a.decomp)
898 if err == nil {
899 return toRPCErr(errors.New("grpc: client streaming protocol violation: get <nil>, want <EOF>"))
440 } 900 }
441 if err == io.EOF { 901 if err == io.EOF {
442 if statusErr := cs.s.Status().Err(); statusErr != nil { 902 return a.s.Status().Err() // non-server streaming Recv returns nil on success
443 return statusErr
444 }
445 // Returns io.EOF to indicate the end of the stream.
446 return
447 } 903 }
448 return toRPCErr(err) 904 return toRPCErr(err)
449} 905}
450 906
451func (cs *clientStream) CloseSend() (err error) { 907func (a *csAttempt) finish(err error) {
452 err = cs.t.Write(cs.s, nil, &transport.Options{Last: true}) 908 a.mu.Lock()
909 if a.finished {
910 a.mu.Unlock()
911 return
912 }
913 a.finished = true
914 if err == io.EOF {
915 // Ending a stream with EOF indicates a success.
916 err = nil
917 }
918 if a.s != nil {
919 a.t.CloseStream(a.s, err)
920 }
921
922 if a.done != nil {
923 br := false
924 var tr metadata.MD
925 if a.s != nil {
926 br = a.s.BytesReceived()
927 tr = a.s.Trailer()
928 }
929 a.done(balancer.DoneInfo{
930 Err: err,
931 Trailer: tr,
932 BytesSent: a.s != nil,
933 BytesReceived: br,
934 })
935 }
936 if a.statsHandler != nil {
937 end := &stats.End{
938 Client: true,
939 BeginTime: a.cs.beginTime,
940 EndTime: time.Now(),
941 Error: err,
942 }
943 a.statsHandler.HandleRPC(a.cs.ctx, end)
944 }
945 if a.trInfo.tr != nil {
946 if err == nil {
947 a.trInfo.tr.LazyPrintf("RPC: [OK]")
948 } else {
949 a.trInfo.tr.LazyPrintf("RPC: [%v]", err)
950 a.trInfo.tr.SetError()
951 }
952 a.trInfo.tr.Finish()
953 a.trInfo.tr = nil
954 }
955 a.mu.Unlock()
956}
957
958func (ac *addrConn) newClientStream(ctx context.Context, desc *StreamDesc, method string, t transport.ClientTransport, opts ...CallOption) (_ ClientStream, err error) {
959 ac.mu.Lock()
960 if ac.transport != t {
961 ac.mu.Unlock()
962 return nil, status.Error(codes.Canceled, "the provided transport is no longer valid to use")
963 }
964 // transition to CONNECTING state when an attempt starts
965 if ac.state != connectivity.Connecting {
966 ac.updateConnectivityState(connectivity.Connecting)
967 ac.cc.handleSubConnStateChange(ac.acbw, ac.state)
968 }
969 ac.mu.Unlock()
970
971 if t == nil {
972 // TODO: return RPC error here?
973 return nil, errors.New("transport provided is nil")
974 }
975 // defaultCallInfo contains unnecessary info(i.e. failfast, maxRetryRPCBufferSize), so we just initialize an empty struct.
976 c := &callInfo{}
977
978 for _, o := range opts {
979 if err := o.before(c); err != nil {
980 return nil, toRPCErr(err)
981 }
982 }
983 c.maxReceiveMessageSize = getMaxSize(nil, c.maxReceiveMessageSize, defaultClientMaxReceiveMessageSize)
984 c.maxSendMessageSize = getMaxSize(nil, c.maxSendMessageSize, defaultServerMaxSendMessageSize)
985
986 // Possible context leak:
987 // The cancel function for the child context we create will only be called
988 // when RecvMsg returns a non-nil error, if the ClientConn is closed, or if
989 // an error is generated by SendMsg.
990 // https://github.com/grpc/grpc-go/issues/1818.
991 ctx, cancel := context.WithCancel(ctx)
453 defer func() { 992 defer func() {
454 if err != nil { 993 if err != nil {
455 cs.finish(err) 994 cancel()
456 } 995 }
457 }() 996 }()
458 if err == nil || err == io.EOF { 997
459 return nil 998 if err := setCallInfoCodec(c); err != nil {
999 return nil, err
460 } 1000 }
461 if _, ok := err.(transport.ConnectionError); !ok { 1001
462 cs.closeTransportStream(err) 1002 callHdr := &transport.CallHdr{
1003 Host: ac.cc.authority,
1004 Method: method,
1005 ContentSubtype: c.contentSubtype,
463 } 1006 }
464 err = toRPCErr(err) 1007
465 return 1008 // Set our outgoing compression according to the UseCompressor CallOption, if
1009 // set. In that case, also find the compressor from the encoding package.
1010 // Otherwise, use the compressor configured by the WithCompressor DialOption,
1011 // if set.
1012 var cp Compressor
1013 var comp encoding.Compressor
1014 if ct := c.compressorType; ct != "" {
1015 callHdr.SendCompress = ct
1016 if ct != encoding.Identity {
1017 comp = encoding.GetCompressor(ct)
1018 if comp == nil {
1019 return nil, status.Errorf(codes.Internal, "grpc: Compressor is not installed for requested grpc-encoding %q", ct)
1020 }
1021 }
1022 } else if ac.cc.dopts.cp != nil {
1023 callHdr.SendCompress = ac.cc.dopts.cp.Type()
1024 cp = ac.cc.dopts.cp
1025 }
1026 if c.creds != nil {
1027 callHdr.Creds = c.creds
1028 }
1029
1030 as := &addrConnStream{
1031 callHdr: callHdr,
1032 ac: ac,
1033 ctx: ctx,
1034 cancel: cancel,
1035 opts: opts,
1036 callInfo: c,
1037 desc: desc,
1038 codec: c.codec,
1039 cp: cp,
1040 comp: comp,
1041 t: t,
1042 }
1043
1044 as.callInfo.stream = as
1045 s, err := as.t.NewStream(as.ctx, as.callHdr)
1046 if err != nil {
1047 err = toRPCErr(err)
1048 return nil, err
1049 }
1050 as.s = s
1051 as.p = &parser{r: s}
1052 ac.incrCallsStarted()
1053 if desc != unaryStreamDesc {
1054 // Listen on cc and stream contexts to cleanup when the user closes the
1055 // ClientConn or cancels the stream context. In all other cases, an error
1056 // should already be injected into the recv buffer by the transport, which
1057 // the client will eventually receive, and then we will cancel the stream's
1058 // context in clientStream.finish.
1059 go func() {
1060 select {
1061 case <-ac.ctx.Done():
1062 as.finish(status.Error(codes.Canceled, "grpc: the SubConn is closing"))
1063 case <-ctx.Done():
1064 as.finish(toRPCErr(ctx.Err()))
1065 }
1066 }()
1067 }
1068 return as, nil
466} 1069}
467 1070
468func (cs *clientStream) closeTransportStream(err error) { 1071type addrConnStream struct {
469 cs.mu.Lock() 1072 s *transport.Stream
470 if cs.closed { 1073 ac *addrConn
471 cs.mu.Unlock() 1074 callHdr *transport.CallHdr
472 return 1075 cancel context.CancelFunc
1076 opts []CallOption
1077 callInfo *callInfo
1078 t transport.ClientTransport
1079 ctx context.Context
1080 sentLast bool
1081 desc *StreamDesc
1082 codec baseCodec
1083 cp Compressor
1084 comp encoding.Compressor
1085 decompSet bool
1086 dc Decompressor
1087 decomp encoding.Compressor
1088 p *parser
1089 done func(balancer.DoneInfo)
1090 mu sync.Mutex
1091 finished bool
1092}
1093
1094func (as *addrConnStream) Header() (metadata.MD, error) {
1095 m, err := as.s.Header()
1096 if err != nil {
1097 as.finish(toRPCErr(err))
473 } 1098 }
474 cs.closed = true 1099 return m, err
475 cs.mu.Unlock()
476 cs.t.CloseStream(cs.s, err)
477} 1100}
478 1101
479func (cs *clientStream) finish(err error) { 1102func (as *addrConnStream) Trailer() metadata.MD {
480 cs.mu.Lock() 1103 return as.s.Trailer()
481 defer cs.mu.Unlock() 1104}
482 if cs.finished { 1105
483 return 1106func (as *addrConnStream) CloseSend() error {
1107 if as.sentLast {
1108 // TODO: return an error and finish the stream instead, due to API misuse?
1109 return nil
484 } 1110 }
485 cs.finished = true 1111 as.sentLast = true
1112
1113 as.t.Write(as.s, nil, nil, &transport.Options{Last: true})
1114 // Always return nil; io.EOF is the only error that might make sense
1115 // instead, but there is no need to signal the client to call RecvMsg
1116 // as the only use left for the stream after CloseSend is to call
1117 // RecvMsg. This also matches historical behavior.
1118 return nil
1119}
1120
1121func (as *addrConnStream) Context() context.Context {
1122 return as.s.Context()
1123}
1124
1125func (as *addrConnStream) SendMsg(m interface{}) (err error) {
486 defer func() { 1126 defer func() {
487 if cs.cancel != nil { 1127 if err != nil && err != io.EOF {
488 cs.cancel() 1128 // Call finish on the client stream for errors generated by this SendMsg
1129 // call, as these indicate problems created by this client. (Transport
1130 // errors are converted to an io.EOF error in csAttempt.sendMsg; the real
1131 // error will be returned from RecvMsg eventually in that case, or be
1132 // retried.)
1133 as.finish(err)
489 } 1134 }
490 }() 1135 }()
491 for _, o := range cs.opts { 1136 if as.sentLast {
492 o.after(&cs.c) 1137 return status.Errorf(codes.Internal, "SendMsg called after CloseSend")
493 } 1138 }
494 if cs.put != nil { 1139 if !as.desc.ClientStreams {
495 updateRPCInfoInContext(cs.s.Context(), rpcInfo{ 1140 as.sentLast = true
496 bytesSent: cs.s.BytesSent(),
497 bytesReceived: cs.s.BytesReceived(),
498 })
499 cs.put()
500 cs.put = nil
501 } 1141 }
502 if cs.statsHandler != nil { 1142 data, err := encode(as.codec, m)
503 end := &stats.End{ 1143 if err != nil {
504 Client: true, 1144 return err
505 EndTime: time.Now(), 1145 }
506 } 1146 compData, err := compress(data, as.cp, as.comp)
507 if err != io.EOF { 1147 if err != nil {
508 // end.Error is nil if the RPC finished successfully. 1148 return err
509 end.Error = toRPCErr(err) 1149 }
1150 hdr, payld := msgHeader(data, compData)
1151 // TODO(dfawley): should we be checking len(data) instead?
1152 if len(payld) > *as.callInfo.maxSendMessageSize {
1153 return status.Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", len(payld), *as.callInfo.maxSendMessageSize)
1154 }
1155
1156 if err := as.t.Write(as.s, hdr, payld, &transport.Options{Last: !as.desc.ClientStreams}); err != nil {
1157 if !as.desc.ClientStreams {
1158 // For non-client-streaming RPCs, we return nil instead of EOF on error
1159 // because the generated code requires it. finish is not called; RecvMsg()
1160 // will call it with the stream's status independently.
1161 return nil
510 } 1162 }
511 cs.statsHandler.HandleRPC(cs.statsCtx, end) 1163 return io.EOF
512 } 1164 }
513 if !cs.tracing { 1165
514 return 1166 if channelz.IsOn() {
1167 as.t.IncrMsgSent()
515 } 1168 }
516 if cs.trInfo.tr != nil { 1169 return nil
517 if err == nil || err == io.EOF { 1170}
518 cs.trInfo.tr.LazyPrintf("RPC: [OK]") 1171
1172func (as *addrConnStream) RecvMsg(m interface{}) (err error) {
1173 defer func() {
1174 if err != nil || !as.desc.ServerStreams {
1175 // err != nil or non-server-streaming indicates end of stream.
1176 as.finish(err)
1177 }
1178 }()
1179
1180 if !as.decompSet {
1181 // Block until we receive headers containing received message encoding.
1182 if ct := as.s.RecvCompress(); ct != "" && ct != encoding.Identity {
1183 if as.dc == nil || as.dc.Type() != ct {
1184 // No configured decompressor, or it does not match the incoming
1185 // message encoding; attempt to find a registered compressor that does.
1186 as.dc = nil
1187 as.decomp = encoding.GetCompressor(ct)
1188 }
519 } else { 1189 } else {
520 cs.trInfo.tr.LazyPrintf("RPC: [%v]", err) 1190 // No compression is used; disable our decompressor.
521 cs.trInfo.tr.SetError() 1191 as.dc = nil
522 } 1192 }
523 cs.trInfo.tr.Finish() 1193 // Only initialize this state once per stream.
524 cs.trInfo.tr = nil 1194 as.decompSet = true
1195 }
1196 err = recv(as.p, as.codec, as.s, as.dc, m, *as.callInfo.maxReceiveMessageSize, nil, as.decomp)
1197 if err != nil {
1198 if err == io.EOF {
1199 if statusErr := as.s.Status().Err(); statusErr != nil {
1200 return statusErr
1201 }
1202 return io.EOF // indicates successful end of stream.
1203 }
1204 return toRPCErr(err)
1205 }
1206
1207 if channelz.IsOn() {
1208 as.t.IncrMsgRecv()
525 } 1209 }
1210 if as.desc.ServerStreams {
1211 // Subsequent messages should be received by subsequent RecvMsg calls.
1212 return nil
1213 }
1214
1215 // Special handling for non-server-stream rpcs.
1216 // This recv expects EOF or errors, so we don't collect inPayload.
1217 err = recv(as.p, as.codec, as.s, as.dc, m, *as.callInfo.maxReceiveMessageSize, nil, as.decomp)
1218 if err == nil {
1219 return toRPCErr(errors.New("grpc: client streaming protocol violation: get <nil>, want <EOF>"))
1220 }
1221 if err == io.EOF {
1222 return as.s.Status().Err() // non-server streaming Recv returns nil on success
1223 }
1224 return toRPCErr(err)
526} 1225}
527 1226
528// ServerStream defines the interface a server stream has to satisfy. 1227func (as *addrConnStream) finish(err error) {
1228 as.mu.Lock()
1229 if as.finished {
1230 as.mu.Unlock()
1231 return
1232 }
1233 as.finished = true
1234 if err == io.EOF {
1235 // Ending a stream with EOF indicates a success.
1236 err = nil
1237 }
1238 if as.s != nil {
1239 as.t.CloseStream(as.s, err)
1240 }
1241
1242 if err != nil {
1243 as.ac.incrCallsFailed()
1244 } else {
1245 as.ac.incrCallsSucceeded()
1246 }
1247 as.cancel()
1248 as.mu.Unlock()
1249}
1250
1251// ServerStream defines the server-side behavior of a streaming RPC.
1252//
1253// All errors returned from ServerStream methods are compatible with the
1254// status package.
529type ServerStream interface { 1255type ServerStream interface {
530 // SetHeader sets the header metadata. It may be called multiple times. 1256 // SetHeader sets the header metadata. It may be called multiple times.
531 // When call multiple times, all the provided metadata will be merged. 1257 // When call multiple times, all the provided metadata will be merged.
@@ -541,29 +1267,67 @@ type ServerStream interface {
541 // SetTrailer sets the trailer metadata which will be sent with the RPC status. 1267 // SetTrailer sets the trailer metadata which will be sent with the RPC status.
542 // When called more than once, all the provided metadata will be merged. 1268 // When called more than once, all the provided metadata will be merged.
543 SetTrailer(metadata.MD) 1269 SetTrailer(metadata.MD)
544 Stream 1270 // Context returns the context for this stream.
1271 Context() context.Context
1272 // SendMsg sends a message. On error, SendMsg aborts the stream and the
1273 // error is returned directly.
1274 //
1275 // SendMsg blocks until:
1276 // - There is sufficient flow control to schedule m with the transport, or
1277 // - The stream is done, or
1278 // - The stream breaks.
1279 //
1280 // SendMsg does not wait until the message is received by the client. An
1281 // untimely stream closure may result in lost messages.
1282 //
1283 // It is safe to have a goroutine calling SendMsg and another goroutine
1284 // calling RecvMsg on the same stream at the same time, but it is not safe
1285 // to call SendMsg on the same stream in different goroutines.
1286 SendMsg(m interface{}) error
1287 // RecvMsg blocks until it receives a message into m or the stream is
1288 // done. It returns io.EOF when the client has performed a CloseSend. On
1289 // any non-EOF error, the stream is aborted and the error contains the
1290 // RPC status.
1291 //
1292 // It is safe to have a goroutine calling SendMsg and another goroutine
1293 // calling RecvMsg on the same stream at the same time, but it is not
1294 // safe to call RecvMsg on the same stream in different goroutines.
1295 RecvMsg(m interface{}) error
545} 1296}
546 1297
547// serverStream implements a server side Stream. 1298// serverStream implements a server side Stream.
548type serverStream struct { 1299type serverStream struct {
549 t transport.ServerTransport 1300 ctx context.Context
550 s *transport.Stream 1301 t transport.ServerTransport
551 p *parser 1302 s *transport.Stream
552 codec Codec 1303 p *parser
553 cp Compressor 1304 codec baseCodec
554 dc Decompressor 1305
555 cbuf *bytes.Buffer 1306 cp Compressor
1307 dc Decompressor
1308 comp encoding.Compressor
1309 decomp encoding.Compressor
1310
556 maxReceiveMessageSize int 1311 maxReceiveMessageSize int
557 maxSendMessageSize int 1312 maxSendMessageSize int
558 trInfo *traceInfo 1313 trInfo *traceInfo
559 1314
560 statsHandler stats.Handler 1315 statsHandler stats.Handler
561 1316
1317 binlog *binarylog.MethodLogger
1318 // serverHeaderBinlogged indicates whether server header has been logged. It
1319 // will happen when one of the following two happens: stream.SendHeader(),
1320 // stream.Send().
1321 //
1322 // It's only checked in send and sendHeader, doesn't need to be
1323 // synchronized.
1324 serverHeaderBinlogged bool
1325
562 mu sync.Mutex // protects trInfo.tr after the service handler runs. 1326 mu sync.Mutex // protects trInfo.tr after the service handler runs.
563} 1327}
564 1328
565func (ss *serverStream) Context() context.Context { 1329func (ss *serverStream) Context() context.Context {
566 return ss.s.Context() 1330 return ss.ctx
567} 1331}
568 1332
569func (ss *serverStream) SetHeader(md metadata.MD) error { 1333func (ss *serverStream) SetHeader(md metadata.MD) error {
@@ -574,7 +1338,15 @@ func (ss *serverStream) SetHeader(md metadata.MD) error {
574} 1338}
575 1339
576func (ss *serverStream) SendHeader(md metadata.MD) error { 1340func (ss *serverStream) SendHeader(md metadata.MD) error {
577 return ss.t.WriteHeader(ss.s, md) 1341 err := ss.t.WriteHeader(ss.s, md)
1342 if ss.binlog != nil && !ss.serverHeaderBinlogged {
1343 h, _ := ss.s.Header()
1344 ss.binlog.Log(&binarylog.ServerHeader{
1345 Header: h,
1346 })
1347 ss.serverHeaderBinlogged = true
1348 }
1349 return err
578} 1350}
579 1351
580func (ss *serverStream) SetTrailer(md metadata.MD) { 1352func (ss *serverStream) SetTrailer(md metadata.MD) {
@@ -582,7 +1354,6 @@ func (ss *serverStream) SetTrailer(md metadata.MD) {
582 return 1354 return
583 } 1355 }
584 ss.s.SetTrailer(md) 1356 ss.s.SetTrailer(md)
585 return
586} 1357}
587 1358
588func (ss *serverStream) SendMsg(m interface{}) (err error) { 1359func (ss *serverStream) SendMsg(m interface{}) (err error) {
@@ -599,29 +1370,50 @@ func (ss *serverStream) SendMsg(m interface{}) (err error) {
599 } 1370 }
600 ss.mu.Unlock() 1371 ss.mu.Unlock()
601 } 1372 }
602 }() 1373 if err != nil && err != io.EOF {
603 var outPayload *stats.OutPayload 1374 st, _ := status.FromError(toRPCErr(err))
604 if ss.statsHandler != nil { 1375 ss.t.WriteStatus(ss.s, st)
605 outPayload = &stats.OutPayload{} 1376 // Non-user specified status was sent out. This should be an error
606 } 1377 // case (as a server side Cancel maybe).
607 out, err := encode(ss.codec, m, ss.cp, ss.cbuf, outPayload) 1378 //
608 defer func() { 1379 // This is not handled specifically now. User will return a final
609 if ss.cbuf != nil { 1380 // status from the service handler, we will log that error instead.
610 ss.cbuf.Reset() 1381 // This behavior is similar to an interceptor.
1382 }
1383 if channelz.IsOn() && err == nil {
1384 ss.t.IncrMsgSent()
611 } 1385 }
612 }() 1386 }()
1387 data, err := encode(ss.codec, m)
1388 if err != nil {
1389 return err
1390 }
1391 compData, err := compress(data, ss.cp, ss.comp)
613 if err != nil { 1392 if err != nil {
614 return err 1393 return err
615 } 1394 }
616 if len(out) > ss.maxSendMessageSize { 1395 hdr, payload := msgHeader(data, compData)
617 return Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", len(out), ss.maxSendMessageSize) 1396 // TODO(dfawley): should we be checking len(data) instead?
1397 if len(payload) > ss.maxSendMessageSize {
1398 return status.Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", len(payload), ss.maxSendMessageSize)
618 } 1399 }
619 if err := ss.t.Write(ss.s, out, &transport.Options{Last: false}); err != nil { 1400 if err := ss.t.Write(ss.s, hdr, payload, &transport.Options{Last: false}); err != nil {
620 return toRPCErr(err) 1401 return toRPCErr(err)
621 } 1402 }
622 if outPayload != nil { 1403 if ss.binlog != nil {
623 outPayload.SentTime = time.Now() 1404 if !ss.serverHeaderBinlogged {
624 ss.statsHandler.HandleRPC(ss.s.Context(), outPayload) 1405 h, _ := ss.s.Header()
1406 ss.binlog.Log(&binarylog.ServerHeader{
1407 Header: h,
1408 })
1409 ss.serverHeaderBinlogged = true
1410 }
1411 ss.binlog.Log(&binarylog.ServerMessage{
1412 Message: data,
1413 })
1414 }
1415 if ss.statsHandler != nil {
1416 ss.statsHandler.HandleRPC(ss.s.Context(), outPayload(false, m, data, payload, time.Now()))
625 } 1417 }
626 return nil 1418 return nil
627} 1419}
@@ -640,22 +1432,55 @@ func (ss *serverStream) RecvMsg(m interface{}) (err error) {
640 } 1432 }
641 ss.mu.Unlock() 1433 ss.mu.Unlock()
642 } 1434 }
1435 if err != nil && err != io.EOF {
1436 st, _ := status.FromError(toRPCErr(err))
1437 ss.t.WriteStatus(ss.s, st)
1438 // Non-user specified status was sent out. This should be an error
1439 // case (as a server side Cancel maybe).
1440 //
1441 // This is not handled specifically now. User will return a final
1442 // status from the service handler, we will log that error instead.
1443 // This behavior is similar to an interceptor.
1444 }
1445 if channelz.IsOn() && err == nil {
1446 ss.t.IncrMsgRecv()
1447 }
643 }() 1448 }()
644 var inPayload *stats.InPayload 1449 var payInfo *payloadInfo
645 if ss.statsHandler != nil { 1450 if ss.statsHandler != nil || ss.binlog != nil {
646 inPayload = &stats.InPayload{} 1451 payInfo = &payloadInfo{}
647 } 1452 }
648 if err := recv(ss.p, ss.codec, ss.s, ss.dc, m, ss.maxReceiveMessageSize, inPayload); err != nil { 1453 if err := recv(ss.p, ss.codec, ss.s, ss.dc, m, ss.maxReceiveMessageSize, payInfo, ss.decomp); err != nil {
649 if err == io.EOF { 1454 if err == io.EOF {
1455 if ss.binlog != nil {
1456 ss.binlog.Log(&binarylog.ClientHalfClose{})
1457 }
650 return err 1458 return err
651 } 1459 }
652 if err == io.ErrUnexpectedEOF { 1460 if err == io.ErrUnexpectedEOF {
653 err = Errorf(codes.Internal, io.ErrUnexpectedEOF.Error()) 1461 err = status.Errorf(codes.Internal, io.ErrUnexpectedEOF.Error())
654 } 1462 }
655 return toRPCErr(err) 1463 return toRPCErr(err)
656 } 1464 }
657 if inPayload != nil { 1465 if ss.statsHandler != nil {
658 ss.statsHandler.HandleRPC(ss.s.Context(), inPayload) 1466 ss.statsHandler.HandleRPC(ss.s.Context(), &stats.InPayload{
1467 RecvTime: time.Now(),
1468 Payload: m,
1469 // TODO truncate large payload.
1470 Data: payInfo.uncompressedBytes,
1471 Length: len(payInfo.uncompressedBytes),
1472 })
1473 }
1474 if ss.binlog != nil {
1475 ss.binlog.Log(&binarylog.ClientMessage{
1476 Message: payInfo.uncompressedBytes,
1477 })
659 } 1478 }
660 return nil 1479 return nil
661} 1480}
1481
1482// MethodFromServerStream returns the method string for the input stream.
1483// The returned string is in the format of "/service/method".
1484func MethodFromServerStream(stream ServerStream) (string, bool) {
1485 return Method(stream.Context())
1486}
diff --git a/vendor/google.golang.org/grpc/tap/tap.go b/vendor/google.golang.org/grpc/tap/tap.go
index decb678..584360f 100644
--- a/vendor/google.golang.org/grpc/tap/tap.go
+++ b/vendor/google.golang.org/grpc/tap/tap.go
@@ -21,7 +21,7 @@
21package tap 21package tap
22 22
23import ( 23import (
24 "golang.org/x/net/context" 24 "context"
25) 25)
26 26
27// Info defines the relevant information needed by the handles. 27// Info defines the relevant information needed by the handles.
@@ -32,8 +32,20 @@ type Info struct {
32 // TODO: More to be added. 32 // TODO: More to be added.
33} 33}
34 34
35// ServerInHandle defines the function which runs when a new stream is created 35// ServerInHandle defines the function which runs before a new stream is created
36// on the server side. Note that it is executed in the per-connection I/O goroutine(s) instead 36// on the server side. If it returns a non-nil error, the stream will not be
37// of per-RPC goroutine. Therefore, users should NOT have any blocking/time-consuming 37// created and a RST_STREAM will be sent back to the client with REFUSED_STREAM.
38// work in this handle. Otherwise all the RPCs would slow down. 38// The client will receive an RPC error "code = Unavailable, desc = stream
39// terminated by RST_STREAM with error code: REFUSED_STREAM".
40//
41// It's intended to be used in situations where you don't want to waste the
42// resources to accept the new stream (e.g. rate-limiting). And the content of
43// the error will be ignored and won't be sent back to the client. For other
44// general usages, please use interceptors.
45//
46// Note that it is executed in the per-connection I/O goroutine(s) instead of
47// per-RPC goroutine. Therefore, users should NOT have any
48// blocking/time-consuming work in this handle. Otherwise all the RPCs would
49// slow down. Also, for the same reason, this handle won't be called
50// concurrently by gRPC.
39type ServerInHandle func(ctx context.Context, info *Info) (context.Context, error) 51type ServerInHandle func(ctx context.Context, info *Info) (context.Context, error)
diff --git a/vendor/google.golang.org/grpc/test/bufconn/bufconn.go b/vendor/google.golang.org/grpc/test/bufconn/bufconn.go
new file mode 100644
index 0000000..bdb5d81
--- /dev/null
+++ b/vendor/google.golang.org/grpc/test/bufconn/bufconn.go
@@ -0,0 +1,244 @@
1/*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19// Package bufconn provides a net.Conn implemented by a buffer and related
20// dialing and listening functionality.
21package bufconn
22
23import (
24 "fmt"
25 "io"
26 "net"
27 "sync"
28 "time"
29)
30
31// Listener implements a net.Listener that creates local, buffered net.Conns
32// via its Accept and Dial method.
33type Listener struct {
34 mu sync.Mutex
35 sz int
36 ch chan net.Conn
37 done chan struct{}
38}
39
40var errClosed = fmt.Errorf("Closed")
41
42// Listen returns a Listener that can only be contacted by its own Dialers and
43// creates buffered connections between the two.
44func Listen(sz int) *Listener {
45 return &Listener{sz: sz, ch: make(chan net.Conn), done: make(chan struct{})}
46}
47
48// Accept blocks until Dial is called, then returns a net.Conn for the server
49// half of the connection.
50func (l *Listener) Accept() (net.Conn, error) {
51 select {
52 case <-l.done:
53 return nil, errClosed
54 case c := <-l.ch:
55 return c, nil
56 }
57}
58
59// Close stops the listener.
60func (l *Listener) Close() error {
61 l.mu.Lock()
62 defer l.mu.Unlock()
63 select {
64 case <-l.done:
65 // Already closed.
66 break
67 default:
68 close(l.done)
69 }
70 return nil
71}
72
73// Addr reports the address of the listener.
74func (l *Listener) Addr() net.Addr { return addr{} }
75
76// Dial creates an in-memory full-duplex network connection, unblocks Accept by
77// providing it the server half of the connection, and returns the client half
78// of the connection.
79func (l *Listener) Dial() (net.Conn, error) {
80 p1, p2 := newPipe(l.sz), newPipe(l.sz)
81 select {
82 case <-l.done:
83 return nil, errClosed
84 case l.ch <- &conn{p1, p2}:
85 return &conn{p2, p1}, nil
86 }
87}
88
89type pipe struct {
90 mu sync.Mutex
91
92 // buf contains the data in the pipe. It is a ring buffer of fixed capacity,
93 // with r and w pointing to the offset to read and write, respsectively.
94 //
95 // Data is read between [r, w) and written to [w, r), wrapping around the end
96 // of the slice if necessary.
97 //
98 // The buffer is empty if r == len(buf), otherwise if r == w, it is full.
99 //
100 // w and r are always in the range [0, cap(buf)) and [0, len(buf)].
101 buf []byte
102 w, r int
103
104 wwait sync.Cond
105 rwait sync.Cond
106
107 closed bool
108 writeClosed bool
109}
110
111func newPipe(sz int) *pipe {
112 p := &pipe{buf: make([]byte, 0, sz)}
113 p.wwait.L = &p.mu
114 p.rwait.L = &p.mu
115 return p
116}
117
118func (p *pipe) empty() bool {
119 return p.r == len(p.buf)
120}
121
122func (p *pipe) full() bool {
123 return p.r < len(p.buf) && p.r == p.w
124}
125
126func (p *pipe) Read(b []byte) (n int, err error) {
127 p.mu.Lock()
128 defer p.mu.Unlock()
129 // Block until p has data.
130 for {
131 if p.closed {
132 return 0, io.ErrClosedPipe
133 }
134 if !p.empty() {
135 break
136 }
137 if p.writeClosed {
138 return 0, io.EOF
139 }
140 p.rwait.Wait()
141 }
142 wasFull := p.full()
143
144 n = copy(b, p.buf[p.r:len(p.buf)])
145 p.r += n
146 if p.r == cap(p.buf) {
147 p.r = 0
148 p.buf = p.buf[:p.w]
149 }
150
151 // Signal a blocked writer, if any
152 if wasFull {
153 p.wwait.Signal()
154 }
155
156 return n, nil
157}
158
159func (p *pipe) Write(b []byte) (n int, err error) {
160 p.mu.Lock()
161 defer p.mu.Unlock()
162 if p.closed {
163 return 0, io.ErrClosedPipe
164 }
165 for len(b) > 0 {
166 // Block until p is not full.
167 for {
168 if p.closed || p.writeClosed {
169 return 0, io.ErrClosedPipe
170 }
171 if !p.full() {
172 break
173 }
174 p.wwait.Wait()
175 }
176 wasEmpty := p.empty()
177
178 end := cap(p.buf)
179 if p.w < p.r {
180 end = p.r
181 }
182 x := copy(p.buf[p.w:end], b)
183 b = b[x:]
184 n += x
185 p.w += x
186 if p.w > len(p.buf) {
187 p.buf = p.buf[:p.w]
188 }
189 if p.w == cap(p.buf) {
190 p.w = 0
191 }
192
193 // Signal a blocked reader, if any.
194 if wasEmpty {
195 p.rwait.Signal()
196 }
197 }
198 return n, nil
199}
200
201func (p *pipe) Close() error {
202 p.mu.Lock()
203 defer p.mu.Unlock()
204 p.closed = true
205 // Signal all blocked readers and writers to return an error.
206 p.rwait.Broadcast()
207 p.wwait.Broadcast()
208 return nil
209}
210
211func (p *pipe) closeWrite() error {
212 p.mu.Lock()
213 defer p.mu.Unlock()
214 p.writeClosed = true
215 // Signal all blocked readers and writers to return an error.
216 p.rwait.Broadcast()
217 p.wwait.Broadcast()
218 return nil
219}
220
221type conn struct {
222 io.Reader
223 io.Writer
224}
225
226func (c *conn) Close() error {
227 err1 := c.Reader.(*pipe).Close()
228 err2 := c.Writer.(*pipe).closeWrite()
229 if err1 != nil {
230 return err1
231 }
232 return err2
233}
234
235func (*conn) LocalAddr() net.Addr { return addr{} }
236func (*conn) RemoteAddr() net.Addr { return addr{} }
237func (c *conn) SetDeadline(t time.Time) error { return fmt.Errorf("unsupported") }
238func (c *conn) SetReadDeadline(t time.Time) error { return fmt.Errorf("unsupported") }
239func (c *conn) SetWriteDeadline(t time.Time) error { return fmt.Errorf("unsupported") }
240
241type addr struct{}
242
243func (addr) Network() string { return "bufconn" }
244func (addr) String() string { return "bufconn" }
diff --git a/vendor/google.golang.org/grpc/trace.go b/vendor/google.golang.org/grpc/trace.go
index b419c9e..c1c96de 100644
--- a/vendor/google.golang.org/grpc/trace.go
+++ b/vendor/google.golang.org/grpc/trace.go
@@ -31,7 +31,7 @@ import (
31 31
32// EnableTracing controls whether to trace RPCs using the golang.org/x/net/trace package. 32// EnableTracing controls whether to trace RPCs using the golang.org/x/net/trace package.
33// This should only be set before any RPCs are sent or received by this program. 33// This should only be set before any RPCs are sent or received by this program.
34var EnableTracing = true 34var EnableTracing bool
35 35
36// methodFamily returns the trace family for the given method. 36// methodFamily returns the trace family for the given method.
37// It turns "/pkg.Service/GetFoo" into "pkg.Service". 37// It turns "/pkg.Service/GetFoo" into "pkg.Service".
@@ -76,6 +76,15 @@ func (f *firstLine) String() string {
76 return line.String() 76 return line.String()
77} 77}
78 78
79const truncateSize = 100
80
81func truncate(x string, l int) string {
82 if l > len(x) {
83 return x
84 }
85 return x[:l]
86}
87
79// payload represents an RPC request or response payload. 88// payload represents an RPC request or response payload.
80type payload struct { 89type payload struct {
81 sent bool // whether this is an outgoing payload 90 sent bool // whether this is an outgoing payload
@@ -85,9 +94,9 @@ type payload struct {
85 94
86func (p payload) String() string { 95func (p payload) String() string {
87 if p.sent { 96 if p.sent {
88 return fmt.Sprintf("sent: %v", p.msg) 97 return truncate(fmt.Sprintf("sent: %v", p.msg), truncateSize)
89 } 98 }
90 return fmt.Sprintf("recv: %v", p.msg) 99 return truncate(fmt.Sprintf("recv: %v", p.msg), truncateSize)
91} 100}
92 101
93type fmtStringer struct { 102type fmtStringer struct {
diff --git a/vendor/google.golang.org/grpc/transport/go16.go b/vendor/google.golang.org/grpc/transport/go16.go
deleted file mode 100644
index 7cffee1..0000000
--- a/vendor/google.golang.org/grpc/transport/go16.go
+++ /dev/null
@@ -1,45 +0,0 @@
1// +build go1.6,!go1.7
2
3/*
4 *
5 * Copyright 2016 gRPC authors.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */
20
21package transport
22
23import (
24 "net"
25
26 "google.golang.org/grpc/codes"
27
28 "golang.org/x/net/context"
29)
30
31// dialContext connects to the address on the named network.
32func dialContext(ctx context.Context, network, address string) (net.Conn, error) {
33 return (&net.Dialer{Cancel: ctx.Done()}).Dial(network, address)
34}
35
36// ContextErr converts the error from context package into a StreamError.
37func ContextErr(err error) StreamError {
38 switch err {
39 case context.DeadlineExceeded:
40 return streamErrorf(codes.DeadlineExceeded, "%v", err)
41 case context.Canceled:
42 return streamErrorf(codes.Canceled, "%v", err)
43 }
44 return streamErrorf(codes.Internal, "Unexpected error from context packet: %v", err)
45}
diff --git a/vendor/google.golang.org/grpc/transport/go17.go b/vendor/google.golang.org/grpc/transport/go17.go
deleted file mode 100644
index 2464e69..0000000
--- a/vendor/google.golang.org/grpc/transport/go17.go
+++ /dev/null
@@ -1,46 +0,0 @@
1// +build go1.7
2
3/*
4 *
5 * Copyright 2016 gRPC authors.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */
20
21package transport
22
23import (
24 "context"
25 "net"
26
27 "google.golang.org/grpc/codes"
28
29 netctx "golang.org/x/net/context"
30)
31
32// dialContext connects to the address on the named network.
33func dialContext(ctx context.Context, network, address string) (net.Conn, error) {
34 return (&net.Dialer{}).DialContext(ctx, network, address)
35}
36
37// ContextErr converts the error from context package into a StreamError.
38func ContextErr(err error) StreamError {
39 switch err {
40 case context.DeadlineExceeded, netctx.DeadlineExceeded:
41 return streamErrorf(codes.DeadlineExceeded, "%v", err)
42 case context.Canceled, netctx.Canceled:
43 return streamErrorf(codes.Canceled, "%v", err)
44 }
45 return streamErrorf(codes.Internal, "Unexpected error from context packet: %v", err)
46}
diff --git a/vendor/google.golang.org/grpc/transport/http2_client.go b/vendor/google.golang.org/grpc/transport/http2_client.go
deleted file mode 100644
index 516ea06..0000000
--- a/vendor/google.golang.org/grpc/transport/http2_client.go
+++ /dev/null
@@ -1,1369 +0,0 @@
1/*
2 *
3 * Copyright 2014 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package transport
20
21import (
22 "bytes"
23 "io"
24 "math"
25 "net"
26 "strings"
27 "sync"
28 "sync/atomic"
29 "time"
30
31 "golang.org/x/net/context"
32 "golang.org/x/net/http2"
33 "golang.org/x/net/http2/hpack"
34 "google.golang.org/grpc/codes"
35 "google.golang.org/grpc/credentials"
36 "google.golang.org/grpc/keepalive"
37 "google.golang.org/grpc/metadata"
38 "google.golang.org/grpc/peer"
39 "google.golang.org/grpc/stats"
40 "google.golang.org/grpc/status"
41)
42
43// http2Client implements the ClientTransport interface with HTTP2.
44type http2Client struct {
45 ctx context.Context
46 target string // server name/addr
47 userAgent string
48 md interface{}
49 conn net.Conn // underlying communication channel
50 remoteAddr net.Addr
51 localAddr net.Addr
52 authInfo credentials.AuthInfo // auth info about the connection
53 nextID uint32 // the next stream ID to be used
54
55 // writableChan synchronizes write access to the transport.
56 // A writer acquires the write lock by sending a value on writableChan
57 // and releases it by receiving from writableChan.
58 writableChan chan int
59 // shutdownChan is closed when Close is called.
60 // Blocking operations should select on shutdownChan to avoid
61 // blocking forever after Close.
62 // TODO(zhaoq): Maybe have a channel context?
63 shutdownChan chan struct{}
64 // errorChan is closed to notify the I/O error to the caller.
65 errorChan chan struct{}
66 // goAway is closed to notify the upper layer (i.e., addrConn.transportMonitor)
67 // that the server sent GoAway on this transport.
68 goAway chan struct{}
69 // awakenKeepalive is used to wake up keepalive when after it has gone dormant.
70 awakenKeepalive chan struct{}
71
72 framer *framer
73 hBuf *bytes.Buffer // the buffer for HPACK encoding
74 hEnc *hpack.Encoder // HPACK encoder
75
76 // controlBuf delivers all the control related tasks (e.g., window
77 // updates, reset streams, and various settings) to the controller.
78 controlBuf *controlBuffer
79 fc *inFlow
80 // sendQuotaPool provides flow control to outbound message.
81 sendQuotaPool *quotaPool
82 // streamsQuota limits the max number of concurrent streams.
83 streamsQuota *quotaPool
84
85 // The scheme used: https if TLS is on, http otherwise.
86 scheme string
87
88 isSecure bool
89
90 creds []credentials.PerRPCCredentials
91
92 // Boolean to keep track of reading activity on transport.
93 // 1 is true and 0 is false.
94 activity uint32 // Accessed atomically.
95 kp keepalive.ClientParameters
96
97 statsHandler stats.Handler
98
99 initialWindowSize int32
100
101 bdpEst *bdpEstimator
102 outQuotaVersion uint32
103
104 mu sync.Mutex // guard the following variables
105 state transportState // the state of underlying connection
106 activeStreams map[uint32]*Stream
107 // The max number of concurrent streams
108 maxStreams int
109 // the per-stream outbound flow control window size set by the peer.
110 streamSendQuota uint32
111 // prevGoAway ID records the Last-Stream-ID in the previous GOAway frame.
112 prevGoAwayID uint32
113 // goAwayReason records the http2.ErrCode and debug data received with the
114 // GoAway frame.
115 goAwayReason GoAwayReason
116}
117
118func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error), addr string) (net.Conn, error) {
119 if fn != nil {
120 return fn(ctx, addr)
121 }
122 return dialContext(ctx, "tcp", addr)
123}
124
125func isTemporary(err error) bool {
126 switch err {
127 case io.EOF:
128 // Connection closures may be resolved upon retry, and are thus
129 // treated as temporary.
130 return true
131 case context.DeadlineExceeded:
132 // In Go 1.7, context.DeadlineExceeded implements Timeout(), and this
133 // special case is not needed. Until then, we need to keep this
134 // clause.
135 return true
136 }
137
138 switch err := err.(type) {
139 case interface {
140 Temporary() bool
141 }:
142 return err.Temporary()
143 case interface {
144 Timeout() bool
145 }:
146 // Timeouts may be resolved upon retry, and are thus treated as
147 // temporary.
148 return err.Timeout()
149 }
150 return false
151}
152
153// newHTTP2Client constructs a connected ClientTransport to addr based on HTTP2
154// and starts to receive messages on it. Non-nil error returns if construction
155// fails.
156func newHTTP2Client(ctx context.Context, addr TargetInfo, opts ConnectOptions) (_ ClientTransport, err error) {
157 scheme := "http"
158 conn, err := dial(ctx, opts.Dialer, addr.Addr)
159 if err != nil {
160 if opts.FailOnNonTempDialError {
161 return nil, connectionErrorf(isTemporary(err), err, "transport: error while dialing: %v", err)
162 }
163 return nil, connectionErrorf(true, err, "transport: Error while dialing %v", err)
164 }
165 // Any further errors will close the underlying connection
166 defer func(conn net.Conn) {
167 if err != nil {
168 conn.Close()
169 }
170 }(conn)
171 var (
172 isSecure bool
173 authInfo credentials.AuthInfo
174 )
175 if creds := opts.TransportCredentials; creds != nil {
176 scheme = "https"
177 conn, authInfo, err = creds.ClientHandshake(ctx, addr.Addr, conn)
178 if err != nil {
179 // Credentials handshake errors are typically considered permanent
180 // to avoid retrying on e.g. bad certificates.
181 temp := isTemporary(err)
182 return nil, connectionErrorf(temp, err, "transport: authentication handshake failed: %v", err)
183 }
184 isSecure = true
185 }
186 kp := opts.KeepaliveParams
187 // Validate keepalive parameters.
188 if kp.Time == 0 {
189 kp.Time = defaultClientKeepaliveTime
190 }
191 if kp.Timeout == 0 {
192 kp.Timeout = defaultClientKeepaliveTimeout
193 }
194 dynamicWindow := true
195 icwz := int32(initialWindowSize)
196 if opts.InitialConnWindowSize >= defaultWindowSize {
197 icwz = opts.InitialConnWindowSize
198 dynamicWindow = false
199 }
200 var buf bytes.Buffer
201 t := &http2Client{
202 ctx: ctx,
203 target: addr.Addr,
204 userAgent: opts.UserAgent,
205 md: addr.Metadata,
206 conn: conn,
207 remoteAddr: conn.RemoteAddr(),
208 localAddr: conn.LocalAddr(),
209 authInfo: authInfo,
210 // The client initiated stream id is odd starting from 1.
211 nextID: 1,
212 writableChan: make(chan int, 1),
213 shutdownChan: make(chan struct{}),
214 errorChan: make(chan struct{}),
215 goAway: make(chan struct{}),
216 awakenKeepalive: make(chan struct{}, 1),
217 framer: newFramer(conn),
218 hBuf: &buf,
219 hEnc: hpack.NewEncoder(&buf),
220 controlBuf: newControlBuffer(),
221 fc: &inFlow{limit: uint32(icwz)},
222 sendQuotaPool: newQuotaPool(defaultWindowSize),
223 scheme: scheme,
224 state: reachable,
225 activeStreams: make(map[uint32]*Stream),
226 isSecure: isSecure,
227 creds: opts.PerRPCCredentials,
228 maxStreams: defaultMaxStreamsClient,
229 streamsQuota: newQuotaPool(defaultMaxStreamsClient),
230 streamSendQuota: defaultWindowSize,
231 kp: kp,
232 statsHandler: opts.StatsHandler,
233 initialWindowSize: initialWindowSize,
234 }
235 if opts.InitialWindowSize >= defaultWindowSize {
236 t.initialWindowSize = opts.InitialWindowSize
237 dynamicWindow = false
238 }
239 if dynamicWindow {
240 t.bdpEst = &bdpEstimator{
241 bdp: initialWindowSize,
242 updateFlowControl: t.updateFlowControl,
243 }
244 }
245 // Make sure awakenKeepalive can't be written upon.
246 // keepalive routine will make it writable, if need be.
247 t.awakenKeepalive <- struct{}{}
248 if t.statsHandler != nil {
249 t.ctx = t.statsHandler.TagConn(t.ctx, &stats.ConnTagInfo{
250 RemoteAddr: t.remoteAddr,
251 LocalAddr: t.localAddr,
252 })
253 connBegin := &stats.ConnBegin{
254 Client: true,
255 }
256 t.statsHandler.HandleConn(t.ctx, connBegin)
257 }
258 // Start the reader goroutine for incoming message. Each transport has
259 // a dedicated goroutine which reads HTTP2 frame from network. Then it
260 // dispatches the frame to the corresponding stream entity.
261 go t.reader()
262 // Send connection preface to server.
263 n, err := t.conn.Write(clientPreface)
264 if err != nil {
265 t.Close()
266 return nil, connectionErrorf(true, err, "transport: failed to write client preface: %v", err)
267 }
268 if n != len(clientPreface) {
269 t.Close()
270 return nil, connectionErrorf(true, err, "transport: preface mismatch, wrote %d bytes; want %d", n, len(clientPreface))
271 }
272 if t.initialWindowSize != defaultWindowSize {
273 err = t.framer.writeSettings(true, http2.Setting{
274 ID: http2.SettingInitialWindowSize,
275 Val: uint32(t.initialWindowSize),
276 })
277 } else {
278 err = t.framer.writeSettings(true)
279 }
280 if err != nil {
281 t.Close()
282 return nil, connectionErrorf(true, err, "transport: failed to write initial settings frame: %v", err)
283 }
284 // Adjust the connection flow control window if needed.
285 if delta := uint32(icwz - defaultWindowSize); delta > 0 {
286 if err := t.framer.writeWindowUpdate(true, 0, delta); err != nil {
287 t.Close()
288 return nil, connectionErrorf(true, err, "transport: failed to write window update: %v", err)
289 }
290 }
291 go t.controller()
292 if t.kp.Time != infinity {
293 go t.keepalive()
294 }
295 t.writableChan <- 0
296 return t, nil
297}
298
299func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *Stream {
300 // TODO(zhaoq): Handle uint32 overflow of Stream.id.
301 s := &Stream{
302 id: t.nextID,
303 done: make(chan struct{}),
304 goAway: make(chan struct{}),
305 method: callHdr.Method,
306 sendCompress: callHdr.SendCompress,
307 buf: newRecvBuffer(),
308 fc: &inFlow{limit: uint32(t.initialWindowSize)},
309 sendQuotaPool: newQuotaPool(int(t.streamSendQuota)),
310 headerChan: make(chan struct{}),
311 }
312 t.nextID += 2
313 s.requestRead = func(n int) {
314 t.adjustWindow(s, uint32(n))
315 }
316 // The client side stream context should have exactly the same life cycle with the user provided context.
317 // That means, s.ctx should be read-only. And s.ctx is done iff ctx is done.
318 // So we use the original context here instead of creating a copy.
319 s.ctx = ctx
320 s.trReader = &transportReader{
321 reader: &recvBufferReader{
322 ctx: s.ctx,
323 goAway: s.goAway,
324 recv: s.buf,
325 },
326 windowHandler: func(n int) {
327 t.updateWindow(s, uint32(n))
328 },
329 }
330
331 return s
332}
333
334// NewStream creates a stream and registers it into the transport as "active"
335// streams.
336func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Stream, err error) {
337 pr := &peer.Peer{
338 Addr: t.remoteAddr,
339 }
340 // Attach Auth info if there is any.
341 if t.authInfo != nil {
342 pr.AuthInfo = t.authInfo
343 }
344 ctx = peer.NewContext(ctx, pr)
345 var (
346 authData = make(map[string]string)
347 audience string
348 )
349 // Create an audience string only if needed.
350 if len(t.creds) > 0 || callHdr.Creds != nil {
351 // Construct URI required to get auth request metadata.
352 var port string
353 if pos := strings.LastIndex(t.target, ":"); pos != -1 {
354 // Omit port if it is the default one.
355 if t.target[pos+1:] != "443" {
356 port = ":" + t.target[pos+1:]
357 }
358 }
359 pos := strings.LastIndex(callHdr.Method, "/")
360 if pos == -1 {
361 pos = len(callHdr.Method)
362 }
363 audience = "https://" + callHdr.Host + port + callHdr.Method[:pos]
364 }
365 for _, c := range t.creds {
366 data, err := c.GetRequestMetadata(ctx, audience)
367 if err != nil {
368 return nil, streamErrorf(codes.Internal, "transport: %v", err)
369 }
370 for k, v := range data {
371 // Capital header names are illegal in HTTP/2.
372 k = strings.ToLower(k)
373 authData[k] = v
374 }
375 }
376 callAuthData := make(map[string]string)
377 // Check if credentials.PerRPCCredentials were provided via call options.
378 // Note: if these credentials are provided both via dial options and call
379 // options, then both sets of credentials will be applied.
380 if callCreds := callHdr.Creds; callCreds != nil {
381 if !t.isSecure && callCreds.RequireTransportSecurity() {
382 return nil, streamErrorf(codes.Unauthenticated, "transport: cannot send secure credentials on an insecure conneciton")
383 }
384 data, err := callCreds.GetRequestMetadata(ctx, audience)
385 if err != nil {
386 return nil, streamErrorf(codes.Internal, "transport: %v", err)
387 }
388 for k, v := range data {
389 // Capital header names are illegal in HTTP/2
390 k = strings.ToLower(k)
391 callAuthData[k] = v
392 }
393 }
394 t.mu.Lock()
395 if t.activeStreams == nil {
396 t.mu.Unlock()
397 return nil, ErrConnClosing
398 }
399 if t.state == draining {
400 t.mu.Unlock()
401 return nil, ErrStreamDrain
402 }
403 if t.state != reachable {
404 t.mu.Unlock()
405 return nil, ErrConnClosing
406 }
407 t.mu.Unlock()
408 sq, err := wait(ctx, nil, nil, t.shutdownChan, t.streamsQuota.acquire())
409 if err != nil {
410 return nil, err
411 }
412 // Returns the quota balance back.
413 if sq > 1 {
414 t.streamsQuota.add(sq - 1)
415 }
416 if _, err := wait(ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil {
417 // Return the quota back now because there is no stream returned to the caller.
418 if _, ok := err.(StreamError); ok {
419 t.streamsQuota.add(1)
420 }
421 return nil, err
422 }
423 t.mu.Lock()
424 if t.state == draining {
425 t.mu.Unlock()
426 t.streamsQuota.add(1)
427 // Need to make t writable again so that the rpc in flight can still proceed.
428 t.writableChan <- 0
429 return nil, ErrStreamDrain
430 }
431 if t.state != reachable {
432 t.mu.Unlock()
433 return nil, ErrConnClosing
434 }
435 s := t.newStream(ctx, callHdr)
436 t.activeStreams[s.id] = s
437 // If the number of active streams change from 0 to 1, then check if keepalive
438 // has gone dormant. If so, wake it up.
439 if len(t.activeStreams) == 1 {
440 select {
441 case t.awakenKeepalive <- struct{}{}:
442 t.framer.writePing(false, false, [8]byte{})
443 default:
444 }
445 }
446
447 t.mu.Unlock()
448
449 // HPACK encodes various headers. Note that once WriteField(...) is
450 // called, the corresponding headers/continuation frame has to be sent
451 // because hpack.Encoder is stateful.
452 t.hBuf.Reset()
453 t.hEnc.WriteField(hpack.HeaderField{Name: ":method", Value: "POST"})
454 t.hEnc.WriteField(hpack.HeaderField{Name: ":scheme", Value: t.scheme})
455 t.hEnc.WriteField(hpack.HeaderField{Name: ":path", Value: callHdr.Method})
456 t.hEnc.WriteField(hpack.HeaderField{Name: ":authority", Value: callHdr.Host})
457 t.hEnc.WriteField(hpack.HeaderField{Name: "content-type", Value: "application/grpc"})
458 t.hEnc.WriteField(hpack.HeaderField{Name: "user-agent", Value: t.userAgent})
459 t.hEnc.WriteField(hpack.HeaderField{Name: "te", Value: "trailers"})
460
461 if callHdr.SendCompress != "" {
462 t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-encoding", Value: callHdr.SendCompress})
463 }
464 if dl, ok := ctx.Deadline(); ok {
465 // Send out timeout regardless its value. The server can detect timeout context by itself.
466 timeout := dl.Sub(time.Now())
467 t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-timeout", Value: encodeTimeout(timeout)})
468 }
469
470 for k, v := range authData {
471 t.hEnc.WriteField(hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
472 }
473 for k, v := range callAuthData {
474 t.hEnc.WriteField(hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
475 }
476 var (
477 endHeaders bool
478 )
479 if md, ok := metadata.FromOutgoingContext(ctx); ok {
480 for k, vv := range md {
481 // HTTP doesn't allow you to set pseudoheaders after non pseudoheaders were set.
482 if isReservedHeader(k) {
483 continue
484 }
485 for _, v := range vv {
486 t.hEnc.WriteField(hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
487 }
488 }
489 }
490 if md, ok := t.md.(*metadata.MD); ok {
491 for k, vv := range *md {
492 if isReservedHeader(k) {
493 continue
494 }
495 for _, v := range vv {
496 t.hEnc.WriteField(hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
497 }
498 }
499 }
500 first := true
501 bufLen := t.hBuf.Len()
502 // Sends the headers in a single batch even when they span multiple frames.
503 for !endHeaders {
504 size := t.hBuf.Len()
505 if size > http2MaxFrameLen {
506 size = http2MaxFrameLen
507 } else {
508 endHeaders = true
509 }
510 var flush bool
511 if callHdr.Flush && endHeaders {
512 flush = true
513 }
514 if first {
515 // Sends a HeadersFrame to server to start a new stream.
516 p := http2.HeadersFrameParam{
517 StreamID: s.id,
518 BlockFragment: t.hBuf.Next(size),
519 EndStream: false,
520 EndHeaders: endHeaders,
521 }
522 // Do a force flush for the buffered frames iff it is the last headers frame
523 // and there is header metadata to be sent. Otherwise, there is flushing until
524 // the corresponding data frame is written.
525 err = t.framer.writeHeaders(flush, p)
526 first = false
527 } else {
528 // Sends Continuation frames for the leftover headers.
529 err = t.framer.writeContinuation(flush, s.id, endHeaders, t.hBuf.Next(size))
530 }
531 if err != nil {
532 t.notifyError(err)
533 return nil, connectionErrorf(true, err, "transport: %v", err)
534 }
535 }
536 s.mu.Lock()
537 s.bytesSent = true
538 s.mu.Unlock()
539
540 if t.statsHandler != nil {
541 outHeader := &stats.OutHeader{
542 Client: true,
543 WireLength: bufLen,
544 FullMethod: callHdr.Method,
545 RemoteAddr: t.remoteAddr,
546 LocalAddr: t.localAddr,
547 Compression: callHdr.SendCompress,
548 }
549 t.statsHandler.HandleRPC(s.ctx, outHeader)
550 }
551 t.writableChan <- 0
552 return s, nil
553}
554
555// CloseStream clears the footprint of a stream when the stream is not needed any more.
556// This must not be executed in reader's goroutine.
557func (t *http2Client) CloseStream(s *Stream, err error) {
558 t.mu.Lock()
559 if t.activeStreams == nil {
560 t.mu.Unlock()
561 return
562 }
563 if err != nil {
564 // notify in-flight streams, before the deletion
565 s.write(recvMsg{err: err})
566 }
567 delete(t.activeStreams, s.id)
568 if t.state == draining && len(t.activeStreams) == 0 {
569 // The transport is draining and s is the last live stream on t.
570 t.mu.Unlock()
571 t.Close()
572 return
573 }
574 t.mu.Unlock()
575 // rstStream is true in case the stream is being closed at the client-side
576 // and the server needs to be intimated about it by sending a RST_STREAM
577 // frame.
578 // To make sure this frame is written to the wire before the headers of the
579 // next stream waiting for streamsQuota, we add to streamsQuota pool only
580 // after having acquired the writableChan to send RST_STREAM out (look at
581 // the controller() routine).
582 var rstStream bool
583 var rstError http2.ErrCode
584 defer func() {
585 // In case, the client doesn't have to send RST_STREAM to server
586 // we can safely add back to streamsQuota pool now.
587 if !rstStream {
588 t.streamsQuota.add(1)
589 return
590 }
591 t.controlBuf.put(&resetStream{s.id, rstError})
592 }()
593 s.mu.Lock()
594 rstStream = s.rstStream
595 rstError = s.rstError
596 if s.state == streamDone {
597 s.mu.Unlock()
598 return
599 }
600 if !s.headerDone {
601 close(s.headerChan)
602 s.headerDone = true
603 }
604 s.state = streamDone
605 s.mu.Unlock()
606 if _, ok := err.(StreamError); ok {
607 rstStream = true
608 rstError = http2.ErrCodeCancel
609 }
610}
611
612// Close kicks off the shutdown process of the transport. This should be called
613// only once on a transport. Once it is called, the transport should not be
614// accessed any more.
615func (t *http2Client) Close() (err error) {
616 t.mu.Lock()
617 if t.state == closing {
618 t.mu.Unlock()
619 return
620 }
621 if t.state == reachable || t.state == draining {
622 close(t.errorChan)
623 }
624 t.state = closing
625 t.mu.Unlock()
626 close(t.shutdownChan)
627 err = t.conn.Close()
628 t.mu.Lock()
629 streams := t.activeStreams
630 t.activeStreams = nil
631 t.mu.Unlock()
632 // Notify all active streams.
633 for _, s := range streams {
634 s.mu.Lock()
635 if !s.headerDone {
636 close(s.headerChan)
637 s.headerDone = true
638 }
639 s.mu.Unlock()
640 s.write(recvMsg{err: ErrConnClosing})
641 }
642 if t.statsHandler != nil {
643 connEnd := &stats.ConnEnd{
644 Client: true,
645 }
646 t.statsHandler.HandleConn(t.ctx, connEnd)
647 }
648 return
649}
650
651func (t *http2Client) GracefulClose() error {
652 t.mu.Lock()
653 switch t.state {
654 case unreachable:
655 // The server may close the connection concurrently. t is not available for
656 // any streams. Close it now.
657 t.mu.Unlock()
658 t.Close()
659 return nil
660 case closing:
661 t.mu.Unlock()
662 return nil
663 }
664 if t.state == draining {
665 t.mu.Unlock()
666 return nil
667 }
668 t.state = draining
669 active := len(t.activeStreams)
670 t.mu.Unlock()
671 if active == 0 {
672 return t.Close()
673 }
674 return nil
675}
676
677// Write formats the data into HTTP2 data frame(s) and sends it out. The caller
678// should proceed only if Write returns nil.
679// TODO(zhaoq): opts.Delay is ignored in this implementation. Support it later
680// if it improves the performance.
681func (t *http2Client) Write(s *Stream, data []byte, opts *Options) error {
682 r := bytes.NewBuffer(data)
683 var (
684 p []byte
685 oqv uint32
686 )
687 for {
688 oqv = atomic.LoadUint32(&t.outQuotaVersion)
689 if r.Len() > 0 || p != nil {
690 size := http2MaxFrameLen
691 // Wait until the stream has some quota to send the data.
692 sq, err := wait(s.ctx, s.done, s.goAway, t.shutdownChan, s.sendQuotaPool.acquire())
693 if err != nil {
694 return err
695 }
696 // Wait until the transport has some quota to send the data.
697 tq, err := wait(s.ctx, s.done, s.goAway, t.shutdownChan, t.sendQuotaPool.acquire())
698 if err != nil {
699 return err
700 }
701 if sq < size {
702 size = sq
703 }
704 if tq < size {
705 size = tq
706 }
707 if p == nil {
708 p = r.Next(size)
709 }
710 ps := len(p)
711 if ps < sq {
712 // Overbooked stream quota. Return it back.
713 s.sendQuotaPool.add(sq - ps)
714 }
715 if ps < tq {
716 // Overbooked transport quota. Return it back.
717 t.sendQuotaPool.add(tq - ps)
718 }
719 }
720 var (
721 endStream bool
722 forceFlush bool
723 )
724 if opts.Last && r.Len() == 0 {
725 endStream = true
726 }
727 // Indicate there is a writer who is about to write a data frame.
728 t.framer.adjustNumWriters(1)
729 // Got some quota. Try to acquire writing privilege on the transport.
730 if _, err := wait(s.ctx, s.done, s.goAway, t.shutdownChan, t.writableChan); err != nil {
731 if _, ok := err.(StreamError); ok || err == io.EOF {
732 // Return the connection quota back.
733 t.sendQuotaPool.add(len(p))
734 }
735 if t.framer.adjustNumWriters(-1) == 0 {
736 // This writer is the last one in this batch and has the
737 // responsibility to flush the buffered frames. It queues
738 // a flush request to controlBuf instead of flushing directly
739 // in order to avoid the race with other writing or flushing.
740 t.controlBuf.put(&flushIO{})
741 }
742 return err
743 }
744 select {
745 case <-s.ctx.Done():
746 t.sendQuotaPool.add(len(p))
747 if t.framer.adjustNumWriters(-1) == 0 {
748 t.controlBuf.put(&flushIO{})
749 }
750 t.writableChan <- 0
751 return ContextErr(s.ctx.Err())
752 default:
753 }
754 if oqv != atomic.LoadUint32(&t.outQuotaVersion) {
755 // InitialWindowSize settings frame must have been received after we
756 // acquired send quota but before we got the writable channel.
757 // We must forsake this write.
758 t.sendQuotaPool.add(len(p))
759 s.sendQuotaPool.add(len(p))
760 if t.framer.adjustNumWriters(-1) == 0 {
761 t.controlBuf.put(&flushIO{})
762 }
763 t.writableChan <- 0
764 continue
765 }
766 if r.Len() == 0 && t.framer.adjustNumWriters(0) == 1 {
767 // Do a force flush iff this is last frame for the entire gRPC message
768 // and the caller is the only writer at this moment.
769 forceFlush = true
770 }
771 // If WriteData fails, all the pending streams will be handled
772 // by http2Client.Close(). No explicit CloseStream() needs to be
773 // invoked.
774 if err := t.framer.writeData(forceFlush, s.id, endStream, p); err != nil {
775 t.notifyError(err)
776 return connectionErrorf(true, err, "transport: %v", err)
777 }
778 p = nil
779 if t.framer.adjustNumWriters(-1) == 0 {
780 t.framer.flushWrite()
781 }
782 t.writableChan <- 0
783 if r.Len() == 0 {
784 break
785 }
786 }
787 if !opts.Last {
788 return nil
789 }
790 s.mu.Lock()
791 if s.state != streamDone {
792 s.state = streamWriteDone
793 }
794 s.mu.Unlock()
795 return nil
796}
797
798func (t *http2Client) getStream(f http2.Frame) (*Stream, bool) {
799 t.mu.Lock()
800 defer t.mu.Unlock()
801 s, ok := t.activeStreams[f.Header().StreamID]
802 return s, ok
803}
804
805// adjustWindow sends out extra window update over the initial window size
806// of stream if the application is requesting data larger in size than
807// the window.
808func (t *http2Client) adjustWindow(s *Stream, n uint32) {
809 s.mu.Lock()
810 defer s.mu.Unlock()
811 if s.state == streamDone {
812 return
813 }
814 if w := s.fc.maybeAdjust(n); w > 0 {
815 // Piggyback conneciton's window update along.
816 if cw := t.fc.resetPendingUpdate(); cw > 0 {
817 t.controlBuf.put(&windowUpdate{0, cw, false})
818 }
819 t.controlBuf.put(&windowUpdate{s.id, w, true})
820 }
821}
822
823// updateWindow adjusts the inbound quota for the stream and the transport.
824// Window updates will deliver to the controller for sending when
825// the cumulative quota exceeds the corresponding threshold.
826func (t *http2Client) updateWindow(s *Stream, n uint32) {
827 s.mu.Lock()
828 defer s.mu.Unlock()
829 if s.state == streamDone {
830 return
831 }
832 if w := s.fc.onRead(n); w > 0 {
833 if cw := t.fc.resetPendingUpdate(); cw > 0 {
834 t.controlBuf.put(&windowUpdate{0, cw, false})
835 }
836 t.controlBuf.put(&windowUpdate{s.id, w, true})
837 }
838}
839
840// updateFlowControl updates the incoming flow control windows
841// for the transport and the stream based on the current bdp
842// estimation.
843func (t *http2Client) updateFlowControl(n uint32) {
844 t.mu.Lock()
845 for _, s := range t.activeStreams {
846 s.fc.newLimit(n)
847 }
848 t.initialWindowSize = int32(n)
849 t.mu.Unlock()
850 t.controlBuf.put(&windowUpdate{0, t.fc.newLimit(n), false})
851 t.controlBuf.put(&settings{
852 ack: false,
853 ss: []http2.Setting{
854 {
855 ID: http2.SettingInitialWindowSize,
856 Val: uint32(n),
857 },
858 },
859 })
860}
861
862func (t *http2Client) handleData(f *http2.DataFrame) {
863 size := f.Header().Length
864 var sendBDPPing bool
865 if t.bdpEst != nil {
866 sendBDPPing = t.bdpEst.add(uint32(size))
867 }
868 // Decouple connection's flow control from application's read.
869 // An update on connection's flow control should not depend on
870 // whether user application has read the data or not. Such a
871 // restriction is already imposed on the stream's flow control,
872 // and therefore the sender will be blocked anyways.
873 // Decoupling the connection flow control will prevent other
874 // active(fast) streams from starving in presence of slow or
875 // inactive streams.
876 //
877 // Furthermore, if a bdpPing is being sent out we can piggyback
878 // connection's window update for the bytes we just received.
879 if sendBDPPing {
880 t.controlBuf.put(&windowUpdate{0, uint32(size), false})
881 t.controlBuf.put(bdpPing)
882 } else {
883 if err := t.fc.onData(uint32(size)); err != nil {
884 t.notifyError(connectionErrorf(true, err, "%v", err))
885 return
886 }
887 if w := t.fc.onRead(uint32(size)); w > 0 {
888 t.controlBuf.put(&windowUpdate{0, w, true})
889 }
890 }
891 // Select the right stream to dispatch.
892 s, ok := t.getStream(f)
893 if !ok {
894 return
895 }
896 if size > 0 {
897 s.mu.Lock()
898 if s.state == streamDone {
899 s.mu.Unlock()
900 return
901 }
902 if err := s.fc.onData(uint32(size)); err != nil {
903 s.rstStream = true
904 s.rstError = http2.ErrCodeFlowControl
905 s.finish(status.New(codes.Internal, err.Error()))
906 s.mu.Unlock()
907 s.write(recvMsg{err: io.EOF})
908 return
909 }
910 if f.Header().Flags.Has(http2.FlagDataPadded) {
911 if w := s.fc.onRead(uint32(size) - uint32(len(f.Data()))); w > 0 {
912 t.controlBuf.put(&windowUpdate{s.id, w, true})
913 }
914 }
915 s.mu.Unlock()
916 // TODO(bradfitz, zhaoq): A copy is required here because there is no
917 // guarantee f.Data() is consumed before the arrival of next frame.
918 // Can this copy be eliminated?
919 if len(f.Data()) > 0 {
920 data := make([]byte, len(f.Data()))
921 copy(data, f.Data())
922 s.write(recvMsg{data: data})
923 }
924 }
925 // The server has closed the stream without sending trailers. Record that
926 // the read direction is closed, and set the status appropriately.
927 if f.FrameHeader.Flags.Has(http2.FlagDataEndStream) {
928 s.mu.Lock()
929 if s.state == streamDone {
930 s.mu.Unlock()
931 return
932 }
933 s.finish(status.New(codes.Internal, "server closed the stream without sending trailers"))
934 s.mu.Unlock()
935 s.write(recvMsg{err: io.EOF})
936 }
937}
938
939func (t *http2Client) handleRSTStream(f *http2.RSTStreamFrame) {
940 s, ok := t.getStream(f)
941 if !ok {
942 return
943 }
944 s.mu.Lock()
945 if s.state == streamDone {
946 s.mu.Unlock()
947 return
948 }
949 if !s.headerDone {
950 close(s.headerChan)
951 s.headerDone = true
952 }
953 statusCode, ok := http2ErrConvTab[http2.ErrCode(f.ErrCode)]
954 if !ok {
955 warningf("transport: http2Client.handleRSTStream found no mapped gRPC status for the received http2 error %v", f.ErrCode)
956 statusCode = codes.Unknown
957 }
958 s.finish(status.Newf(statusCode, "stream terminated by RST_STREAM with error code: %d", f.ErrCode))
959 s.mu.Unlock()
960 s.write(recvMsg{err: io.EOF})
961}
962
963func (t *http2Client) handleSettings(f *http2.SettingsFrame) {
964 if f.IsAck() {
965 return
966 }
967 var ss []http2.Setting
968 f.ForeachSetting(func(s http2.Setting) error {
969 ss = append(ss, s)
970 return nil
971 })
972 // The settings will be applied once the ack is sent.
973 t.controlBuf.put(&settings{ack: true, ss: ss})
974}
975
976func (t *http2Client) handlePing(f *http2.PingFrame) {
977 if f.IsAck() {
978 // Maybe it's a BDP ping.
979 if t.bdpEst != nil {
980 t.bdpEst.calculate(f.Data)
981 }
982 return
983 }
984 pingAck := &ping{ack: true}
985 copy(pingAck.data[:], f.Data[:])
986 t.controlBuf.put(pingAck)
987}
988
989func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) {
990 t.mu.Lock()
991 if t.state != reachable && t.state != draining {
992 t.mu.Unlock()
993 return
994 }
995 if f.ErrCode == http2.ErrCodeEnhanceYourCalm {
996 infof("Client received GoAway with http2.ErrCodeEnhanceYourCalm.")
997 }
998 id := f.LastStreamID
999 if id > 0 && id%2 != 1 {
1000 t.mu.Unlock()
1001 t.notifyError(connectionErrorf(true, nil, "received illegal http2 GOAWAY frame: stream ID %d is even", f.LastStreamID))
1002 return
1003 }
1004 // A client can recieve multiple GoAways from server (look at https://github.com/grpc/grpc-go/issues/1387).
1005 // The idea is that the first GoAway will be sent with an ID of MaxInt32 and the second GoAway will be sent after an RTT delay
1006 // with the ID of the last stream the server will process.
1007 // Therefore, when we get the first GoAway we don't really close any streams. While in case of second GoAway we
1008 // close all streams created after the second GoAwayId. This way streams that were in-flight while the GoAway from server
1009 // was being sent don't get killed.
1010 select {
1011 case <-t.goAway: // t.goAway has been closed (i.e.,multiple GoAways).
1012 // If there are multiple GoAways the first one should always have an ID greater than the following ones.
1013 if id > t.prevGoAwayID {
1014 t.mu.Unlock()
1015 t.notifyError(connectionErrorf(true, nil, "received illegal http2 GOAWAY frame: previously recv GOAWAY frame with LastStramID %d, currently recv %d", id, f.LastStreamID))
1016 return
1017 }
1018 default:
1019 t.setGoAwayReason(f)
1020 close(t.goAway)
1021 t.state = draining
1022 }
1023 // All streams with IDs greater than the GoAwayId
1024 // and smaller than the previous GoAway ID should be killed.
1025 upperLimit := t.prevGoAwayID
1026 if upperLimit == 0 { // This is the first GoAway Frame.
1027 upperLimit = math.MaxUint32 // Kill all streams after the GoAway ID.
1028 }
1029 for streamID, stream := range t.activeStreams {
1030 if streamID > id && streamID <= upperLimit {
1031 close(stream.goAway)
1032 }
1033 }
1034 t.prevGoAwayID = id
1035 active := len(t.activeStreams)
1036 t.mu.Unlock()
1037 if active == 0 {
1038 t.Close()
1039 }
1040}
1041
1042// setGoAwayReason sets the value of t.goAwayReason based
1043// on the GoAway frame received.
1044// It expects a lock on transport's mutext to be held by
1045// the caller.
1046func (t *http2Client) setGoAwayReason(f *http2.GoAwayFrame) {
1047 t.goAwayReason = NoReason
1048 switch f.ErrCode {
1049 case http2.ErrCodeEnhanceYourCalm:
1050 if string(f.DebugData()) == "too_many_pings" {
1051 t.goAwayReason = TooManyPings
1052 }
1053 }
1054}
1055
1056func (t *http2Client) GetGoAwayReason() GoAwayReason {
1057 t.mu.Lock()
1058 defer t.mu.Unlock()
1059 return t.goAwayReason
1060}
1061
1062func (t *http2Client) handleWindowUpdate(f *http2.WindowUpdateFrame) {
1063 id := f.Header().StreamID
1064 incr := f.Increment
1065 if id == 0 {
1066 t.sendQuotaPool.add(int(incr))
1067 return
1068 }
1069 if s, ok := t.getStream(f); ok {
1070 s.sendQuotaPool.add(int(incr))
1071 }
1072}
1073
1074// operateHeaders takes action on the decoded headers.
1075func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
1076 s, ok := t.getStream(frame)
1077 if !ok {
1078 return
1079 }
1080 s.mu.Lock()
1081 s.bytesReceived = true
1082 s.mu.Unlock()
1083 var state decodeState
1084 if err := state.decodeResponseHeader(frame); err != nil {
1085 s.mu.Lock()
1086 if !s.headerDone {
1087 close(s.headerChan)
1088 s.headerDone = true
1089 }
1090 s.mu.Unlock()
1091 s.write(recvMsg{err: err})
1092 // Something wrong. Stops reading even when there is remaining.
1093 return
1094 }
1095
1096 endStream := frame.StreamEnded()
1097 var isHeader bool
1098 defer func() {
1099 if t.statsHandler != nil {
1100 if isHeader {
1101 inHeader := &stats.InHeader{
1102 Client: true,
1103 WireLength: int(frame.Header().Length),
1104 }
1105 t.statsHandler.HandleRPC(s.ctx, inHeader)
1106 } else {
1107 inTrailer := &stats.InTrailer{
1108 Client: true,
1109 WireLength: int(frame.Header().Length),
1110 }
1111 t.statsHandler.HandleRPC(s.ctx, inTrailer)
1112 }
1113 }
1114 }()
1115
1116 s.mu.Lock()
1117 if !endStream {
1118 s.recvCompress = state.encoding
1119 }
1120 if !s.headerDone {
1121 if !endStream && len(state.mdata) > 0 {
1122 s.header = state.mdata
1123 }
1124 close(s.headerChan)
1125 s.headerDone = true
1126 isHeader = true
1127 }
1128 if !endStream || s.state == streamDone {
1129 s.mu.Unlock()
1130 return
1131 }
1132
1133 if len(state.mdata) > 0 {
1134 s.trailer = state.mdata
1135 }
1136 s.finish(state.status())
1137 s.mu.Unlock()
1138 s.write(recvMsg{err: io.EOF})
1139}
1140
1141func handleMalformedHTTP2(s *Stream, err error) {
1142 s.mu.Lock()
1143 if !s.headerDone {
1144 close(s.headerChan)
1145 s.headerDone = true
1146 }
1147 s.mu.Unlock()
1148 s.write(recvMsg{err: err})
1149}
1150
1151// reader runs as a separate goroutine in charge of reading data from network
1152// connection.
1153//
1154// TODO(zhaoq): currently one reader per transport. Investigate whether this is
1155// optimal.
1156// TODO(zhaoq): Check the validity of the incoming frame sequence.
1157func (t *http2Client) reader() {
1158 // Check the validity of server preface.
1159 frame, err := t.framer.readFrame()
1160 if err != nil {
1161 t.notifyError(err)
1162 return
1163 }
1164 atomic.CompareAndSwapUint32(&t.activity, 0, 1)
1165 sf, ok := frame.(*http2.SettingsFrame)
1166 if !ok {
1167 t.notifyError(err)
1168 return
1169 }
1170 t.handleSettings(sf)
1171
1172 // loop to keep reading incoming messages on this transport.
1173 for {
1174 frame, err := t.framer.readFrame()
1175 atomic.CompareAndSwapUint32(&t.activity, 0, 1)
1176 if err != nil {
1177 // Abort an active stream if the http2.Framer returns a
1178 // http2.StreamError. This can happen only if the server's response
1179 // is malformed http2.
1180 if se, ok := err.(http2.StreamError); ok {
1181 t.mu.Lock()
1182 s := t.activeStreams[se.StreamID]
1183 t.mu.Unlock()
1184 if s != nil {
1185 // use error detail to provide better err message
1186 handleMalformedHTTP2(s, streamErrorf(http2ErrConvTab[se.Code], "%v", t.framer.errorDetail()))
1187 }
1188 continue
1189 } else {
1190 // Transport error.
1191 t.notifyError(err)
1192 return
1193 }
1194 }
1195 switch frame := frame.(type) {
1196 case *http2.MetaHeadersFrame:
1197 t.operateHeaders(frame)
1198 case *http2.DataFrame:
1199 t.handleData(frame)
1200 case *http2.RSTStreamFrame:
1201 t.handleRSTStream(frame)
1202 case *http2.SettingsFrame:
1203 t.handleSettings(frame)
1204 case *http2.PingFrame:
1205 t.handlePing(frame)
1206 case *http2.GoAwayFrame:
1207 t.handleGoAway(frame)
1208 case *http2.WindowUpdateFrame:
1209 t.handleWindowUpdate(frame)
1210 default:
1211 errorf("transport: http2Client.reader got unhandled frame type %v.", frame)
1212 }
1213 }
1214}
1215
1216func (t *http2Client) applySettings(ss []http2.Setting) {
1217 for _, s := range ss {
1218 switch s.ID {
1219 case http2.SettingMaxConcurrentStreams:
1220 // TODO(zhaoq): This is a hack to avoid significant refactoring of the
1221 // code to deal with the unrealistic int32 overflow. Probably will try
1222 // to find a better way to handle this later.
1223 if s.Val > math.MaxInt32 {
1224 s.Val = math.MaxInt32
1225 }
1226 t.mu.Lock()
1227 ms := t.maxStreams
1228 t.maxStreams = int(s.Val)
1229 t.mu.Unlock()
1230 t.streamsQuota.add(int(s.Val) - ms)
1231 case http2.SettingInitialWindowSize:
1232 t.mu.Lock()
1233 for _, stream := range t.activeStreams {
1234 // Adjust the sending quota for each stream.
1235 stream.sendQuotaPool.add(int(s.Val) - int(t.streamSendQuota))
1236 }
1237 t.streamSendQuota = s.Val
1238 t.mu.Unlock()
1239 atomic.AddUint32(&t.outQuotaVersion, 1)
1240 }
1241 }
1242}
1243
1244// controller running in a separate goroutine takes charge of sending control
1245// frames (e.g., window update, reset stream, setting, etc.) to the server.
1246func (t *http2Client) controller() {
1247 for {
1248 select {
1249 case i := <-t.controlBuf.get():
1250 t.controlBuf.load()
1251 select {
1252 case <-t.writableChan:
1253 switch i := i.(type) {
1254 case *windowUpdate:
1255 t.framer.writeWindowUpdate(i.flush, i.streamID, i.increment)
1256 case *settings:
1257 if i.ack {
1258 t.framer.writeSettingsAck(true)
1259 t.applySettings(i.ss)
1260 } else {
1261 t.framer.writeSettings(true, i.ss...)
1262 }
1263 case *resetStream:
1264 // If the server needs to be to intimated about stream closing,
1265 // then we need to make sure the RST_STREAM frame is written to
1266 // the wire before the headers of the next stream waiting on
1267 // streamQuota. We ensure this by adding to the streamsQuota pool
1268 // only after having acquired the writableChan to send RST_STREAM.
1269 t.streamsQuota.add(1)
1270 t.framer.writeRSTStream(true, i.streamID, i.code)
1271 case *flushIO:
1272 t.framer.flushWrite()
1273 case *ping:
1274 if !i.ack {
1275 t.bdpEst.timesnap(i.data)
1276 }
1277 t.framer.writePing(true, i.ack, i.data)
1278 default:
1279 errorf("transport: http2Client.controller got unexpected item type %v\n", i)
1280 }
1281 t.writableChan <- 0
1282 continue
1283 case <-t.shutdownChan:
1284 return
1285 }
1286 case <-t.shutdownChan:
1287 return
1288 }
1289 }
1290}
1291
1292// keepalive running in a separate goroutune makes sure the connection is alive by sending pings.
1293func (t *http2Client) keepalive() {
1294 p := &ping{data: [8]byte{}}
1295 timer := time.NewTimer(t.kp.Time)
1296 for {
1297 select {
1298 case <-timer.C:
1299 if atomic.CompareAndSwapUint32(&t.activity, 1, 0) {
1300 timer.Reset(t.kp.Time)
1301 continue
1302 }
1303 // Check if keepalive should go dormant.
1304 t.mu.Lock()
1305 if len(t.activeStreams) < 1 && !t.kp.PermitWithoutStream {
1306 // Make awakenKeepalive writable.
1307 <-t.awakenKeepalive
1308 t.mu.Unlock()
1309 select {
1310 case <-t.awakenKeepalive:
1311 // If the control gets here a ping has been sent
1312 // need to reset the timer with keepalive.Timeout.
1313 case <-t.shutdownChan:
1314 return
1315 }
1316 } else {
1317 t.mu.Unlock()
1318 // Send ping.
1319 t.controlBuf.put(p)
1320 }
1321
1322 // By the time control gets here a ping has been sent one way or the other.
1323 timer.Reset(t.kp.Timeout)
1324 select {
1325 case <-timer.C:
1326 if atomic.CompareAndSwapUint32(&t.activity, 1, 0) {
1327 timer.Reset(t.kp.Time)
1328 continue
1329 }
1330 t.Close()
1331 return
1332 case <-t.shutdownChan:
1333 if !timer.Stop() {
1334 <-timer.C
1335 }
1336 return
1337 }
1338 case <-t.shutdownChan:
1339 if !timer.Stop() {
1340 <-timer.C
1341 }
1342 return
1343 }
1344 }
1345}
1346
1347func (t *http2Client) Error() <-chan struct{} {
1348 return t.errorChan
1349}
1350
1351func (t *http2Client) GoAway() <-chan struct{} {
1352 return t.goAway
1353}
1354
1355func (t *http2Client) notifyError(err error) {
1356 t.mu.Lock()
1357 // make sure t.errorChan is closed only once.
1358 if t.state == draining {
1359 t.mu.Unlock()
1360 t.Close()
1361 return
1362 }
1363 if t.state == reachable {
1364 t.state = unreachable
1365 close(t.errorChan)
1366 infof("transport: http2Client.notifyError got notified that the client transport was broken %v.", err)
1367 }
1368 t.mu.Unlock()
1369}
diff --git a/vendor/google.golang.org/grpc/naming/go18.go b/vendor/google.golang.org/grpc/version.go
index b5a0f84..45eace5 100644
--- a/vendor/google.golang.org/grpc/naming/go18.go
+++ b/vendor/google.golang.org/grpc/version.go
@@ -1,8 +1,6 @@
1// +build go1.8
2
3/* 1/*
4 * 2 *
5 * Copyright 2017 gRPC authors. 3 * Copyright 2018 gRPC authors.
6 * 4 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License. 6 * you may not use this file except in compliance with the License.
@@ -18,11 +16,7 @@
18 * 16 *
19 */ 17 */
20 18
21package naming 19package grpc
22
23import "net"
24 20
25var ( 21// Version is the current grpc version.
26 lookupHost = net.DefaultResolver.LookupHost 22const Version = "1.18.0"
27 lookupSRV = net.DefaultResolver.LookupSRV
28)
diff --git a/vendor/google.golang.org/grpc/vet.sh b/vendor/google.golang.org/grpc/vet.sh
new file mode 100644
index 0000000..94a5064
--- /dev/null
+++ b/vendor/google.golang.org/grpc/vet.sh
@@ -0,0 +1,141 @@
1#!/bin/bash
2
3if [[ `uname -a` = *"Darwin"* ]]; then
4 echo "It seems you are running on Mac. This script does not work on Mac. See https://github.com/grpc/grpc-go/issues/2047"
5 exit 1
6fi
7
8set -ex # Exit on error; debugging enabled.
9set -o pipefail # Fail a pipe if any sub-command fails.
10
11die() {
12 echo "$@" >&2
13 exit 1
14}
15
16# Check to make sure it's safe to modify the user's git repo.
17if git status --porcelain | read; then
18 die "Uncommitted or untracked files found; commit changes first"
19fi
20
21if [[ -d "${GOPATH}/src" ]]; then
22 die "\${GOPATH}/src (${GOPATH}/src) exists; this script will delete it."
23fi
24
25# Undo any edits made by this script.
26cleanup() {
27 rm -rf "${GOPATH}/src"
28 git reset --hard HEAD
29}
30trap cleanup EXIT
31
32fail_on_output() {
33 tee /dev/stderr | (! read)
34}
35
36PATH="${GOPATH}/bin:${GOROOT}/bin:${PATH}"
37
38if [[ "$1" = "-install" ]]; then
39 # Check for module support
40 if go help mod >& /dev/null; then
41 go install \
42 golang.org/x/lint/golint \
43 golang.org/x/tools/cmd/goimports \
44 honnef.co/go/tools/cmd/staticcheck \
45 github.com/client9/misspell/cmd/misspell \
46 github.com/golang/protobuf/protoc-gen-go
47 else
48 # Ye olde `go get` incantation.
49 # Note: this gets the latest version of all tools (vs. the pinned versions
50 # with Go modules).
51 go get -u \
52 golang.org/x/lint/golint \
53 golang.org/x/tools/cmd/goimports \
54 honnef.co/go/tools/cmd/staticcheck \
55 github.com/client9/misspell/cmd/misspell \
56 github.com/golang/protobuf/protoc-gen-go
57 fi
58 if [[ -z "${VET_SKIP_PROTO}" ]]; then
59 if [[ "${TRAVIS}" = "true" ]]; then
60 PROTOBUF_VERSION=3.3.0
61 PROTOC_FILENAME=protoc-${PROTOBUF_VERSION}-linux-x86_64.zip
62 pushd /home/travis
63 wget https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/${PROTOC_FILENAME}
64 unzip ${PROTOC_FILENAME}
65 bin/protoc --version
66 popd
67 elif ! which protoc > /dev/null; then
68 die "Please install protoc into your path"
69 fi
70 fi
71 exit 0
72elif [[ "$#" -ne 0 ]]; then
73 die "Unknown argument(s): $*"
74fi
75
76# - Ensure all source files contain a copyright message.
77git ls-files "*.go" | xargs grep -L "\(Copyright [0-9]\{4,\} gRPC authors\)\|DO NOT EDIT" 2>&1 | fail_on_output
78
79# - Make sure all tests in grpc and grpc/test use leakcheck via Teardown.
80(! grep 'func Test[^(]' *_test.go)
81(! grep 'func Test[^(]' test/*.go)
82
83# - Do not import math/rand for real library code. Use internal/grpcrand for
84# thread safety.
85git ls-files "*.go" | xargs grep -l '"math/rand"' 2>&1 | (! grep -v '^examples\|^stress\|grpcrand')
86
87# - Ensure all ptypes proto packages are renamed when importing.
88git ls-files "*.go" | (! xargs grep "\(import \|^\s*\)\"github.com/golang/protobuf/ptypes/")
89
90# - Check imports that are illegal in appengine (until Go 1.11).
91# TODO: Remove when we drop Go 1.10 support
92go list -f {{.Dir}} ./... | xargs go run test/go_vet/vet.go
93
94# - gofmt, goimports, golint (with exceptions for generated code), go vet.
95gofmt -s -d -l . 2>&1 | fail_on_output
96goimports -l . 2>&1 | fail_on_output
97golint ./... 2>&1 | (! grep -vE "(_mock|\.pb)\.go:")
98go tool vet -all .
99
100# - Check that generated proto files are up to date.
101if [[ -z "${VET_SKIP_PROTO}" ]]; then
102 PATH="/home/travis/bin:${PATH}" make proto && \
103 git status --porcelain 2>&1 | fail_on_output || \
104 (git status; git --no-pager diff; exit 1)
105fi
106
107# - Check that our module is tidy.
108if go help mod >& /dev/null; then
109 go mod tidy && \
110 git status --porcelain 2>&1 | fail_on_output || \
111 (git status; git --no-pager diff; exit 1)
112fi
113
114# - Collection of static analysis checks
115### HACK HACK HACK: Remove once staticcheck works with modules.
116# Make a symlink in ${GOPATH}/src to its ${GOPATH}/pkg/mod equivalent for every package we use.
117for x in $(find "${GOPATH}/pkg/mod" -name '*@*' | grep -v \/mod\/cache\/); do
118 pkg="$(echo ${x#"${GOPATH}/pkg/mod/"} | cut -f1 -d@)";
119 # If multiple versions exist, just use the existing one.
120 if [[ -L "${GOPATH}/src/${pkg}" ]]; then continue; fi
121 mkdir -p "$(dirname "${GOPATH}/src/${pkg}")";
122 ln -s $x "${GOPATH}/src/${pkg}";
123done
124### END HACK HACK HACK
125
126# TODO(menghanl): fix errors in transport_test.
127staticcheck -go 1.9 -ignore '
128balancer.go:SA1019
129balancer_test.go:SA1019
130clientconn_test.go:SA1019
131balancer/roundrobin/roundrobin_test.go:SA1019
132benchmark/benchmain/main.go:SA1019
133internal/transport/handler_server.go:SA1019
134internal/transport/handler_server_test.go:SA1019
135internal/transport/transport_test.go:SA2002
136stats/stats_test.go:SA1019
137test/channelz_test.go:SA1019
138test/end2end_test.go:SA1019
139test/healthcheck_test.go:SA1019
140' ./...
141misspell -error .